LCD
简介
ESP 系列芯片可以发出市场上常见的 LCD(如 SPI LCD、I2C LCD、并行 LCD (Intel 8080)、RGB/SRGB LCD、MIPI DSI LCD 等)所需的各种时序。esp_lcd
组件为上述各类 LCD 提供了一个统一的抽象驱动框架。
LCD 通常由两个主要平面组成:
控制平面:通过该平面,可以读取、写入 LCD 设备控制器的内部寄存器。主机通常使用该平面来初始化 LCD 电源或进行伽玛校正等。
数据平面:数据平面负责向 LCD 设备传输像素数据。
功能概述
在 esp_lcd
的上下文中,数据平面和控制平面都由 esp_lcd_panel_handle_t
数据类型表示。
在某些 LCD 中,上述两个平面可能会合并为一个平面。此时,像素数据通过控制平面传输,实现类似数据平面的功能。这在 SPI LCD 和 I2C LCD 中很常见。
此外,还有一些 LCD 不需要单独的控制平面。例如,某些 RGB LCD 在上电后会自动执行必要的初始化过程,主机只需通过数据平面不断刷新像素数据即可。但要注意,并非所有 RGB LCD 都完全不需要控制平面。部分 LCD 设备同时支持多种接口,需要主机通过控制平面(例如基于 SPI 接口)发送特定命令以启用 RGB 模式。
本文将讨论如何为不同类型的 LCD 创建控制平面和数据平面。
备注
ESP-IDF 仓库中自带的 LCD 设备控制器驱动程序数量有限(例如,ST7789 驱动程序是开箱即用的)。更多驱动程序可通过 乐鑫组件注册表 获取。
LCD 控制面板操作
esp_lcd_panel_reset()
可以重置 LCD 控制面板。esp_lcd_panel_init()
执行基本的控制面板初始化。有关特定制造商的初始化设置,请参阅 添加特定制造商的初始化设置。通过组合使用
esp_lcd_panel_swap_xy()
和esp_lcd_panel_mirror()
,可以实现 LCD 屏幕旋转和 LCD 屏幕镜像功能。esp_lcd_panel_disp_on_off()
可以通过切断从帧 buffer 到 LCD 屏幕的输出路径来打开或关闭 LCD 屏幕。请注意,这与控制 LCD 背光不同,esp_lcd
驱动程序无法控制 LCD 背光。esp_lcd_panel_disp_sleep()
可以通过进入睡眠模式减少 LCD 屏幕的功耗,而内部的帧 buffer 仍然保留。
LCD 数据面板操作
esp_lcd_panel_reset()
可以重置 LCD 数据面板。esp_lcd_panel_init()
执行基本的数据面板初始化。esp_lcd_panel_draw_bitmap()
可以将绘制 buffer 刷新到 LCD 屏幕上,其中目标绘制窗口是可配置的。请注意,使用该函数需要确保绘制 buffer 是一维数组,且每行像素数据之间没有跨距。
添加特定制造商的初始化设置
在 ESP-IDF 中,LCD 控制器驱动程序(例如 st7789)在函数 esp_lcd_panel_init()
中只提供了基本的控制面板初始化设置,大部分设置使用默认值。部分 LCD 模组需要进行一系列特定制造商的配置(通常包含伽玛配置、电压配置等)才能正常显示。若想添加特定制造商的初始化设置,请参照以下步骤:
esp_lcd_panel_reset(panel_handle);
esp_lcd_panel_init(panel_handle);
// 进行额外的配置,例如伽玛控制
// 使用底层 IO 句柄
// 请咨询制造商来获取特殊命令和相应的值
esp_lcd_panel_io_tx_param(io_handle, GAMMA_CMD, (uint8_t[]) {
GAMMA_ARRAY
}, N);
// 打开显示屏
esp_lcd_panel_disp_on_off(panel_handle, true);
应用示例
peripherals/lcd/tjpgd 演示了如何解码 JPEG 图像并在 SPI 接口的 LCD 上显示图像,同时周期性地旋转图像。
peripherals/lcd/spi_lcd_touch 演示了如何在 ESP-IDF 项目中使用 esp_lcd 组件为 LCD 屏幕添加自定义驱动,例如 GC9A01 或 ILI9341,以及如何启用 STMPE610 触摸控制器。
peripherals/lcd/i80_controller 演示了如何将 LVGL 库移植到 esp_lcd 驱动层,以创建图形用户界面。
peripherals/lcd/i2c_oled 演示了如何使用 esp_lcd 组件中的 SSD1306 面板驱动来简化移植 LVGL 库,并在 OLED 屏幕上显示滚动文本。
API 参考
Header File
This header file can be included with:
#include "hal/lcd_types.h"
Type Definitions
-
typedef soc_periph_lcd_clk_src_t lcd_clock_source_t
LCD clock source.
Enumerations
-
enum lcd_rgb_data_endian_t
RGB data endian.
Values:
-
enumerator LCD_RGB_DATA_ENDIAN_BIG
RGB data endian: MSB first
-
enumerator LCD_RGB_DATA_ENDIAN_LITTLE
RGB data endian: LSB first
-
enumerator LCD_RGB_DATA_ENDIAN_BIG
-
enum lcd_color_space_t
LCD color space.
Values:
-
enumerator LCD_COLOR_SPACE_RGB
Color space: RGB
-
enumerator LCD_COLOR_SPACE_YUV
Color space: YUV
-
enumerator LCD_COLOR_SPACE_RGB
-
enum lcd_color_rgb_pixel_format_t
LCD color pixel format in RGB color space.
Values:
-
enumerator LCD_COLOR_PIXEL_FORMAT_RGB565
16 bits, 5 bits per R/B value, 6 bits for G value
-
enumerator LCD_COLOR_PIXEL_FORMAT_RGB666
18 bits, 6 bits per R/G/B value
-
enumerator LCD_COLOR_PIXEL_FORMAT_RGB888
24 bits, 8 bits per R/G/B value
-
enumerator LCD_COLOR_PIXEL_FORMAT_RGB565
-
enum lcd_color_range_t
LCD color range.
Values:
-
enumerator LCD_COLOR_RANGE_LIMIT
Limited color range
-
enumerator LCD_COLOR_RANGE_FULL
Full color range
-
enumerator LCD_COLOR_RANGE_LIMIT
Header File
This header file can be included with:
#include "esp_lcd_types.h"
This header file is a part of the API provided by the
esp_lcd
component. To declare that your component depends onesp_lcd
, add the following to your CMakeLists.txt:REQUIRES esp_lcd
or
PRIV_REQUIRES esp_lcd
Structures
-
struct esp_lcd_video_timing_t
Timing parameters for the video data transmission.
Public Members
-
uint32_t h_size
Horizontal resolution, i.e. the number of pixels in a line
-
uint32_t v_size
Vertical resolution, i.e. the number of lines in the frame
-
uint32_t hsync_pulse_width
Horizontal sync width, in pixel clock
-
uint32_t hsync_back_porch
Horizontal back porch, number of pixel clock between hsync and start of line active data
-
uint32_t hsync_front_porch
Horizontal front porch, number of pixel clock between the end of active data and the next hsync
-
uint32_t vsync_pulse_width
Vertical sync width, in number of lines
-
uint32_t vsync_back_porch
Vertical back porch, number of invalid lines between vsync and start of frame
-
uint32_t vsync_front_porch
Vertical front porch, number of invalid lines between the end of frame and the next vsync
-
uint32_t h_size
-
struct esp_lcd_panel_io_event_data_t
Type of LCD panel IO event data.
-
struct esp_lcd_panel_io_callbacks_t
Type of LCD panel IO callbacks.
Public Members
-
esp_lcd_panel_io_color_trans_done_cb_t on_color_trans_done
Callback invoked when color data transfer has finished
-
esp_lcd_panel_io_color_trans_done_cb_t on_color_trans_done
Type Definitions
-
typedef struct esp_lcd_panel_io_t *esp_lcd_panel_io_handle_t
Type of LCD panel IO handle
-
typedef struct esp_lcd_panel_t *esp_lcd_panel_handle_t
Type of LCD panel handle
-
typedef bool (*esp_lcd_panel_io_color_trans_done_cb_t)(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx)
Declare the prototype of the function that will be invoked when panel IO finishes transferring color data.
- Param panel_io
[in] LCD panel IO handle, which is created by factory API like
esp_lcd_new_panel_io_spi()
- Param edata
[in] Panel IO event data, fed by driver
- Param user_ctx
[in] User data, passed from
esp_lcd_panel_io_xxx_config_t
- Return
Whether a high priority task has been waken up by this function
Enumerations
Header File
This header file can be included with:
#include "esp_lcd_panel_io.h"
This header file is a part of the API provided by the
esp_lcd
component. To declare that your component depends onesp_lcd
, add the following to your CMakeLists.txt:REQUIRES esp_lcd
or
PRIV_REQUIRES esp_lcd
Functions
-
esp_err_t esp_lcd_panel_io_rx_param(esp_lcd_panel_io_handle_t io, int lcd_cmd, void *param, size_t param_size)
Transmit LCD command and receive corresponding parameters.
备注
Commands sent by this function are short, so they are sent using polling transactions. The function does not return before the command transfer is completed. If any queued transactions sent by
esp_lcd_panel_io_tx_color()
are still pending when this function is called, this function will wait until they are finished and the queue is empty before sending the command(s).- 参数
io -- [in] LCD panel IO handle, which is created by other factory API like
esp_lcd_new_panel_io_spi()
lcd_cmd -- [in] The specific LCD command, set to -1 if no command needed
param -- [out] Buffer for the command data
param_size -- [in] Size of
param
buffer
- 返回
ESP_ERR_INVALID_ARG if parameter is invalid
ESP_ERR_NOT_SUPPORTED if read is not supported by transport
ESP_OK on success
-
esp_err_t esp_lcd_panel_io_tx_param(esp_lcd_panel_io_handle_t io, int lcd_cmd, const void *param, size_t param_size)
Transmit LCD command and corresponding parameters.
备注
Commands sent by this function are short, so they are sent using polling transactions. The function does not return before the command transfer is completed. If any queued transactions sent by
esp_lcd_panel_io_tx_color()
are still pending when this function is called, this function will wait until they are finished and the queue is empty before sending the command(s).- 参数
io -- [in] LCD panel IO handle, which is created by other factory API like
esp_lcd_new_panel_io_spi()
lcd_cmd -- [in] The specific LCD command, set to -1 if no command needed
param -- [in] Buffer that holds the command specific parameters, set to NULL if no parameter is needed for the command
param_size -- [in] Size of
param
in memory, in bytes, set to zero if no parameter is needed for the command
- 返回
ESP_ERR_INVALID_ARG if parameter is invalid
ESP_OK on success
-
esp_err_t esp_lcd_panel_io_tx_color(esp_lcd_panel_io_handle_t io, int lcd_cmd, const void *color, size_t color_size)
Transmit LCD RGB data.
备注
This function will package the command and RGB data into a transaction, and push into a queue. The real transmission is performed in the background (DMA+interrupt). The caller should take care of the lifecycle of the
color
buffer. Recycling of color buffer should be done in the callbackon_color_trans_done()
.- 参数
io -- [in] LCD panel IO handle, which is created by factory API like
esp_lcd_new_panel_io_spi()
lcd_cmd -- [in] The specific LCD command, set to -1 if no command needed
color -- [in] Buffer that holds the RGB color data
color_size -- [in] Size of
color
in memory, in bytes
- 返回
ESP_ERR_INVALID_ARG if parameter is invalid
ESP_OK on success
-
esp_err_t esp_lcd_panel_io_del(esp_lcd_panel_io_handle_t io)
Destroy LCD panel IO handle (deinitialize panel and free all corresponding resource)
- 参数
io -- [in] LCD panel IO handle, which is created by factory API like
esp_lcd_new_panel_io_spi()
- 返回
ESP_ERR_INVALID_ARG if parameter is invalid
ESP_OK on success
-
esp_err_t esp_lcd_panel_io_register_event_callbacks(esp_lcd_panel_io_handle_t io, const esp_lcd_panel_io_callbacks_t *cbs, void *user_ctx)
Register LCD panel IO callbacks.
- 参数
io -- [in] LCD panel IO handle, which is created by factory API like
esp_lcd_new_panel_io_spi()
cbs -- [in] structure with all LCD panel IO callbacks
user_ctx -- [in] User private data, passed directly to callback's user_ctx
- 返回
ESP_ERR_INVALID_ARG if parameter is invalid
ESP_OK on success
Header File
This header file can be included with:
#include "esp_lcd_panel_ops.h"
This header file is a part of the API provided by the
esp_lcd
component. To declare that your component depends onesp_lcd
, add the following to your CMakeLists.txt:REQUIRES esp_lcd
or
PRIV_REQUIRES esp_lcd
Functions
-
esp_err_t esp_lcd_panel_reset(esp_lcd_panel_handle_t panel)
Reset LCD panel.
备注
Panel reset must be called before attempting to initialize the panel using
esp_lcd_panel_init()
.- 参数
panel -- [in] LCD panel handle, which is created by other factory API like
esp_lcd_new_panel_st7789()
- 返回
ESP_OK on success
-
esp_err_t esp_lcd_panel_init(esp_lcd_panel_handle_t panel)
Initialize LCD panel.
备注
Before calling this function, make sure the LCD panel has finished the
reset
stage byesp_lcd_panel_reset()
.- 参数
panel -- [in] LCD panel handle, which is created by other factory API like
esp_lcd_new_panel_st7789()
- 返回
ESP_OK on success
-
esp_err_t esp_lcd_panel_del(esp_lcd_panel_handle_t panel)
Deinitialize the LCD panel.
- 参数
panel -- [in] LCD panel handle, which is created by other factory API like
esp_lcd_new_panel_st7789()
- 返回
ESP_OK on success
-
esp_err_t esp_lcd_panel_draw_bitmap(esp_lcd_panel_handle_t panel, int x_start, int y_start, int x_end, int y_end, const void *color_data)
Draw bitmap on LCD panel.
- 参数
panel -- [in] LCD panel handle, which is created by other factory API like
esp_lcd_new_panel_st7789()
x_start -- [in] Start pixel index in the target frame buffer, on x-axis (x_start is included)
y_start -- [in] Start pixel index in the target frame buffer, on y-axis (y_start is included)
x_end -- [in] End pixel index in the target frame buffer, on x-axis (x_end is not included)
y_end -- [in] End pixel index in the target frame buffer, on y-axis (y_end is not included)
color_data -- [in] RGB color data that will be dumped to the specific window range
- 返回
ESP_OK on success
-
esp_err_t esp_lcd_panel_mirror(esp_lcd_panel_handle_t panel, bool mirror_x, bool mirror_y)
Mirror the LCD panel on specific axis.
备注
Combined with
esp_lcd_panel_swap_xy()
, one can realize screen rotation- 参数
panel -- [in] LCD panel handle, which is created by other factory API like
esp_lcd_new_panel_st7789()
mirror_x -- [in] Whether the panel will be mirrored about the x axis
mirror_y -- [in] Whether the panel will be mirrored about the y axis
- 返回
ESP_OK on success
ESP_ERR_NOT_SUPPORTED if this function is not supported by the panel
-
esp_err_t esp_lcd_panel_swap_xy(esp_lcd_panel_handle_t panel, bool swap_axes)
Swap/Exchange x and y axis.
备注
Combined with
esp_lcd_panel_mirror()
, one can realize screen rotation- 参数
panel -- [in] LCD panel handle, which is created by other factory API like
esp_lcd_new_panel_st7789()
swap_axes -- [in] Whether to swap the x and y axis
- 返回
ESP_OK on success
ESP_ERR_NOT_SUPPORTED if this function is not supported by the panel
-
esp_err_t esp_lcd_panel_set_gap(esp_lcd_panel_handle_t panel, int x_gap, int y_gap)
Set extra gap in x and y axis.
The gap is the space (in pixels) between the left/top sides of the LCD panel and the first row/column respectively of the actual contents displayed.
备注
Setting a gap is useful when positioning or centering a frame that is smaller than the LCD.
- 参数
panel -- [in] LCD panel handle, which is created by other factory API like
esp_lcd_new_panel_st7789()
x_gap -- [in] Extra gap on x axis, in pixels
y_gap -- [in] Extra gap on y axis, in pixels
- 返回
ESP_OK on success
-
esp_err_t esp_lcd_panel_invert_color(esp_lcd_panel_handle_t panel, bool invert_color_data)
Invert the color (bit-wise invert the color data line)
- 参数
panel -- [in] LCD panel handle, which is created by other factory API like
esp_lcd_new_panel_st7789()
invert_color_data -- [in] Whether to invert the color data
- 返回
ESP_OK on success
-
esp_err_t esp_lcd_panel_disp_on_off(esp_lcd_panel_handle_t panel, bool on_off)
Turn on or off the display.
- 参数
panel -- [in] LCD panel handle, which is created by other factory API like
esp_lcd_new_panel_st7789()
on_off -- [in] True to turns on display, False to turns off display
- 返回
ESP_OK on success
ESP_ERR_NOT_SUPPORTED if this function is not supported by the panel
-
esp_err_t esp_lcd_panel_disp_off(esp_lcd_panel_handle_t panel, bool off)
Turn off the display.
- 参数
panel -- [in] LCD panel handle, which is created by other factory API like
esp_lcd_new_panel_st7789()
off -- [in] Whether to turn off the screen
- 返回
ESP_OK on success
ESP_ERR_NOT_SUPPORTED if this function is not supported by the panel
-
esp_err_t esp_lcd_panel_disp_sleep(esp_lcd_panel_handle_t panel, bool sleep)
Enter or exit sleep mode.
- 参数
panel -- [in] LCD panel handle, which is created by other factory API like
esp_lcd_new_panel_st7789()
sleep -- [in] True to enter sleep mode, False to wake up
- 返回
ESP_OK on success
ESP_ERR_NOT_SUPPORTED if this function is not supported by the panel
Header File
This header file can be included with:
#include "esp_lcd_panel_vendor.h"
This header file is a part of the API provided by the
esp_lcd
component. To declare that your component depends onesp_lcd
, add the following to your CMakeLists.txt:REQUIRES esp_lcd
or
PRIV_REQUIRES esp_lcd