ESP IoT Solution 中的 ST7123 MIPI-DSI LCD 驱动实践:esp_lcd_st7123 组件使用与源码解析
2026/9/19 2:12:53 网站建设 项目流程

ESP IoT Solution 中的 ST7123 MIPI-DSI LCD 驱动实践:esp_lcd_st7123 组件使用与源码解析

【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution

ST7123 是一款通过MIPI-DSI 接口驱动的高分辨率 LCD 控制芯片,在乐鑫 ESP IoT Solution 仓库中由esp_lcd_st7123组件提供完整驱动支持。本文以该组件文档为主体,结合 esp_lcd_st7123.c 与 esp_lcd_st7123.h 源码、test_apps 测试用例,系统讲解从组件引入、硬件初始化到逐命令执行的完整流程,帮助读者在 ESP32-P4 等支持 MIPI-DSI 的平台上快速点亮 720×1560 分辨率屏幕,并能自定义厂商初始化序列。

一、组件概览与适用前提

esp_lcd_st7123是基于esp_lcd组件对 ST7123 LCD 控制器的实现,其核心特征如下:

LCD 控制器通信接口组件名称
ST7123MIPI-DSIesp_lcd_st7123

注意:MIPI-DSI 接口仅在 ESP-IDFv5.3 及以上版本受支持。进一步看,组件清单 idf_component.yml 将 IDF 依赖声明为>=5.4,且目标芯片限定为esp32p4——这也是当前仓库中唯一带SOC_MIPI_DSI_SUPPORTED能力宏的验证平台。从源码结构看,驱动实现整体被包裹在#if SOC_MIPI_DSI_SUPPORTED条件编译中,不具备 MIPI-DSI 外设的芯片不会编译该驱动。

二、将组件加入项目

该组件已发布到乐鑫官方组件服务,可通过以下两种方式引入:

方式一:命令行添加依赖

idf.py add-dependency "espressif/esp_lcd_st7123"

方式二:手动编辑idf_component.yml,在项目根目录创建或修改该文件并声明依赖,之后由 IDF 组件管理器自动拉取,详见 ESP-IDF 组件管理器文档。

组件自身的idf_component.yml还声明了对cmake_utilities的依赖(用于在 CMakeLists.txt 中通过cu_pkg_define_version注入组件版本号),编译时仅REQUIRES "esp_lcd",依赖非常轻量。

三、驱动初始化:从 DSI 总线到面板的完整链路

ST7123 的初始化遵循 esp_lcd 标准的"总线 → IO → 面板"三级结构,但总线层是 MIPI-DSI 而非传统的 SPI/8080 并行总线。README 给出的初始化流程如下:

/** * Uncomment these line if use custom initialization commands. * The array should be declared as static const and positioned outside the function. */ // static const st7123_lcd_init_cmd_t lcd_init_cmds[] = { // {cmd, { data }, data_size, delay_ms} // {0x11, (uint8_t []){0x00}, 120, 0}, // {0x29, (uint8_t []){0x00}, 20, 0}, // ... // }; ESP_LOGI(TAG, "MIPI DSI PHY Powered on"); esp_ldo_channel_handle_t ldo_mipi_phy = NULL; esp_ldo_channel_config_t ldo_mipi_phy_config = { .chan_id = 3, .voltage_mv = 2500, }; ESP_ERROR_CHECK(esp_ldo_acquire_channel(&ldo_mipi_phy_config, &ldo_mipi_phy)); ESP_LOGI(TAG, "Initialize MIPI DSI bus"); esp_lcd_dsi_bus_handle_t mipi_dsi_bus = NULL; esp_lcd_dsi_bus_config_t bus_config = ST7123_PANEL_BUS_DSI_2CH_CONFIG(); ESP_ERROR_CHECK(esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus)); ESP_LOGI(TAG, "Install panel IO"); esp_lcd_panel_io_handle_t mipi_dbi_io = NULL; esp_lcd_dbi_io_config_t dbi_config = ST7123_PANEL_IO_DBI_CONFIG(); ESP_ERROR_CHECK(esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &mipi_dbi_io)); ESP_LOGI(TAG, "Install ST7123S panel driver"); esp_lcd_panel_handle_t panel_handle = NULL; #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(6, 0, 0) const esp_lcd_dpi_panel_config_t dpi_config = ST7123_1560_720_PANEL_60HZ_DPI_CONFIG(EXAMPLE_MIPI_DPI_PX_FORMAT); #else const esp_lcd_dpi_panel_config_t dpi_config = ST7123_1560_720_PANEL_60HZ_DPI_CONFIG_CF(EXAMPLE_MIPI_DPI_PX_FORMAT); #endif st7123_vendor_config_t vendor_config = { .mipi_config = { .dsi_bus = mipi_dsi_bus, .dpi_config = &dpi_config, }, }; const esp_lcd_panel_dev_config_t panel_config = { .reset_gpio_num = EXAMPLE_LCD_IO_RST, // Set to -1 if not use .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, // Implemented by LCD command `36h` .bits_per_pixel = EXAMPLE_LCD_BIT_PER_PIXEL, // Implemented by LCD command `3Ah` (16/18/24) .vendor_config = &vendor_config, }; ESP_ERROR_CHECK(esp_lcd_new_panel_st7123(mipi_dbi_io, &panel_config, &panel_handle)); ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle)); ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle));

下面拆解这条链路的每一步。

1. 给 MIPI-DSI PHY 供电(LDO 通道)

MIPI-DSI PHY 需要先上电才能从 "No Power" 状态进入 "Shutdown" 状态。示例使用esp_ldo_acquire_channel打开编号为 3、电压 2500 mV 的 LDO 通道。测试用例 test_esp_lcd_st7123.c 以宏形式定义了同样的参数:

#define TEST_MIPI_DSI_PHY_PWR_LDO_CHAN (3) #define TEST_MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV (2500)

2. 创建 MIPI-DSI 总线

ST7123_PANEL_BUS_DSI_2CH_CONFIG()宏在头文件中展开为:

#define ST7123_PANEL_BUS_DSI_2CH_CONFIG() \ { \ .bus_id = 0, \ .num_data_lanes = 2, \ .lane_bit_rate_mbps = 1300, \ }

即使用2 条数据通道,单通道比特率1300 Mbps。这也是 ST7123 这类高分辨率(720×1560)面板所需的带宽基础。

3. 安装 DBI 面板 IO

ST7123 的控制命令通过 MIPI-DBI 协议发送,IO 配置宏如下:

#define ST7123_PANEL_IO_DBI_CONFIG() \ { \ .virtual_channel = 0, \ .lcd_cmd_bits = 8, \ .lcd_param_bits = 8, \ }

命令和参数宽度均为 8 bit,使用虚拟通道 0。

4. DPI 视频时序配置(按版本选择宏)

ST7123 的像素数据走 MIPI-DPI 视频模式通道,头文件给出 720×1560@60Hz 的时序配置:

#define ST7123_1560_720_PANEL_60HZ_DPI_CONFIG(px_format) \ { \ .dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT, \ .dpi_clock_freq_mhz = 78, \ .virtual_channel = 0, \ .pixel_format = px_format, \ .num_fbs = 1, \ .video_timing = { \ .h_size = 720, \ .v_size = 1560, \ .hsync_back_porch = 40, \ .hsync_pulse_width = 2, \ .hsync_front_porch = 40, \ .vsync_back_porch = 4, \ .vsync_pulse_width = 2, \ .vsync_front_porch = 320, \ }, \ .flags.use_dma2d = true, \ }

注意三点:

  • 刷新率计算公式(头文件注释明确给出):refresh_rate = (dpi_clock_freq_mhz * 1000000) / (h_res + hsync_pulse_width + hsync_back_porch + hsync_front_porch) / (v_res + vsync_pulse_width + vsync_back_porch + vsync_front_porch)。代入 78 MHz 时钟与上述时序,可验证约等于 60 Hz;
  • IDF 版本差异:IDF v6.0 之前使用ST7123_1560_720_PANEL_60HZ_DPI_CONFIG(),字段为pixel_format;IDF v6.0 起改用ST7123_1560_720_PANEL_60HZ_DPI_CONFIG_CF(),字段更名为in_color_format,且不再内联开启 DMA2D。CHANGELOG v1.0.2 明确指出:从 esp-idf v6.0 开始,DMA2D 只能通过显式调用esp_lcd_dpi_panel_enable_dma2d开启;
  • 像素格式由调用方传入,如测试用例中按TEST_LCD_BIT_PER_PIXEL映射为LCD_COLOR_PIXEL_FORMAT_RGB888/RGB666/RGB565之一。

5. 创建 ST7123 面板驱动

esp_lcd_new_panel_st7123()是组件的入口函数,其底层做了三件关键事(见 esp_lcd_st7123.c):

  1. 校验 vendor 配置vendor_config及其中的mipi_config.dsi_busdpi_config均不可为空;
  2. 配置复位 GPIO:当reset_gpio_num >= 0时将该引脚配置为输出模式;
  3. 内部创建 MIPI-DPI 面板并"包装"回调:调用esp_lcd_new_panel_dpi()创建底层 DPI 面板后,把delinitresetmirrorinvert_colordisp_on_off六个函数指针替换为 ST7123 的私有实现,同时保存原del/init以便链式调用,user_data指向驱动私有结构st7123_panel_t

6. 复位与初始化

esp_lcd_panel_reset()优先做硬件复位(拉低→拉高→拉低,分别延时 5/10/120 ms);若reset_gpio_num = -1,则退化为发送LCD_CMD_SWRESET软件复位命令(见 esp_lcd_st7123.c)。

esp_lcd_panel_init()则逐条发送初始化命令序列(见 esp_lcd_st7123.c),见下文。

四、厂商初始化命令序列:默认值与自定义

ST7123 的初始化命令因屏厂而异,组件在 esp_lcd_st7123.c 中内置了默认序列vendor_specific_init_default,共约 30 条命令,涵盖:

  • 0x60/0xB0/0xB7/0xBF/0xA4等基础设置命令(如0xA4亮度、0xB7电源时序相关参数);
  • 超长参数命令:0xC80xC9(各 37 字节)、0xA3(39 字节)、0xA6(54 字节)、0xA7(61 字节)、0xAC(44 字节)、0xAD(25 字节)、0xB2(17 字节)等,多为 Gamma、时序与驱动相关的厂家私有寄存器配置;
  • 最后以0x11(Sleep Out,延时 120 ms)和0x29(Display On,延时 50 ms)收尾。

自定义初始化序列是实战中最常见的需求:不同批次或厂家的模组初始化代码可能不同,此时应咨询 LCD 供应商获取序列。使用方式在 README 注释中已有明确模板:

static const st7123_lcd_init_cmd_t lcd_init_cmds[] = { // {cmd, { data }, data_size, delay_ms} {0x11, (uint8_t []){0x00}, 120, 0}, {0x29, (uint8_t []){0x00}, 20, 0}, // ... };

数组必须声明为static const并置于函数体外(防止栈上生命周期问题),随后将其指针与长度填入st7123_vendor_config_t

typedef struct { const st7123_lcd_init_cmd_t *init_cmds; /*!< Pointer to initialization commands array. Set to NULL if using default commands. */ uint16_t init_cmds_size; /*<! Number of commands in above array */ struct { esp_lcd_dsi_bus_handle_t dsi_bus; /*!< MIPI-DSI bus configuration */ const esp_lcd_dpi_panel_config_t *dpi_config; /*!< MIPI-DPI panel configuration */ } mipi_config; } st7123_vendor_config_t;

init_cmds为 NULL 时,驱动自动回退到内置默认序列。命令结构体定义如下:

typedef struct { int cmd; /*<! The specific LCD command */ const void *data; /*<! Buffer that holds the command specific data */ size_t data_bytes; /*<! Size of `data` in memory, in bytes */ unsigned int delay_ms; /*<! Delay in milliseconds after this command */ } st7123_lcd_init_cmd_t;

逐命令发送逻辑(见 esp_lcd_st7123.c)还有一个值得注意的细节:驱动会扫描自定义序列中是否包含LCD_CMD_MADCTL(36h,地址控制命令),若被自定义命令占用,会打印The XXh command has been used and will be overwritten by external initialization sequence警告并同步更新内部保存的madctl_val——这保证了镜像(mirror)操作仍能基于正确的寄存器基值工作。每条命令经esp_lcd_panel_io_tx_param()发送后,先等待命令自带的delay_ms,再固定追加 5 ms 延时。

五、面板操作接口:镜像、反色与开关显示

ST7123 驱动通过madctl_val(MADCTL 寄存器值)统一管理颜色序与镜像:

  • RGB/BGR 选择:创建面板时根据rgb_ele_order设置LCD_CMD_BGR_BIT位(LCD_RGB_ELEMENT_ORDER_BGR时置位),对应 LCD 命令 36h;
  • 镜像esp_lcd_panel_mirror()通过 MADCTL 的ST7123_CMD_GS_BIT(bit0,行镜像)与ST7123_CMD_SS_BIT(bit1,列镜像)实现,操作后回写新值到madctl_val(见 esp_lcd_st7123.c);
  • 反色esp_lcd_panel_invert_color()发送LCD_CMD_INVON/LCD_CMD_INVOFF
  • 开关显示esp_lcd_panel_disp_on_off()发送LCD_CMD_DISPON/LCD_CMD_DISPOFF
  • 销毁esp_lcd_panel_del()先释放复位 GPIO,再调用保存的原 DPI 面板del释放底层资源并释放驱动私有结构。

六、测试用例与验证方法

组件自带完整的 Unity 测试工程 test_apps,基于ESP32-P4平台验证(pytest_esp_lcd_st7123.py使用@pytest.mark.target('esp32p4')),包含三个测试用例(见 test_esp_lcd_st7123.c):

  1. 硬件图案模式:调用esp_lcd_dpi_panel_set_pattern()依次显示MIPI_DSI_PATTERN_BAR_VERTICAL(垂直彩条)、MIPI_DSI_PATTERN_BAR_HORIZONTAL(水平彩条)、MIPI_DSI_PATTERN_NONE,用于无软件绘制时的链路自检;
  2. 软件彩条绘制:构造 DMA 内存中的彩色条带,通过esp_lcd_panel_draw_bitmap()逐行绘制,并注册on_color_trans_done回调配合信号量等待每帧刷新完成;
  3. 镜像旋转:循环 4 次调用esp_lcd_panel_mirror()组合镜像方向并绘制彩条,验证 MADCTL 镜像逻辑。

测试用例还通过heap_caps_get_free_size对比 setUp/tearDown 前后内存,检查驱动是否存在内存泄漏。这些用例既是驱动正确性的回归保障,也是读者自行搭建验证工程时可复用的最小初始化模板。

七、注意事项小结

  • 硬件前提:MIPI-DSI 仅 ESP-IDF v5.3+ 支持,本组件 manifest 实际要求 IDF>=5.4,目标芯片为 ESP32-P4;
  • 供电时序:初始化前必须先为 MIPI-DSI PHY 提供 LDO 电源(示例通道 3、2500 mV,具体以板卡原理图为准);
  • 分辨率与时序:默认面板配置为 720×1560@60Hz(2 lane、1300 Mbps、78 MHz DPI 时钟),若使用不同尺寸模组,需按刷新率公式重新计算dpi_clock_freq_mhz与各 porch 参数;
  • 厂商初始化:默认命令序列仅适用于特定厂家模组,量产不同屏体时务必向供应商索取初始化代码并通过init_cmds覆盖;
  • IDF v6.0 迁移:DPI 配置宏与字段名发生变化,DMA2D 需显式调用esp_lcd_dpi_panel_enable_dma2d开启。

以上内容以 esp_lcd_st7123/README.md 为骨架,结合组件头文件、实现与测试源码逐层展开。若需要了解同系列触摸驱动,可进一步查看配套的 esp_lcd_touch_st7123 组件。

【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询