LCD

[English]


ESP 系列芯片 LCD 驱动及参考例程在哪?


ESP 系列芯片 LCD 屏幕适配情况是怎样的?

  • 各系列 ESP 芯片对 SPI、I80、RGB、MIPI-DSI 等接口的支持情况,请参考 LCD 开发指南 - 支持的接口类型。其中部分芯片(如 ESP32-C5/C6/H2/H4)不具备原生 I80 外设,可通过 esp_lcdParlio 接口模拟 I80 时序驱动 LCD。

  • 乐鑫官方已基于 esp_lcd 移植的 LCD 驱动 IC 组件列表(含 I2C、SPI、QSPI、I80、MIPI-DSI、3-wire SPI + RGB 等接口),请参考 LCD 开发指南 - 驱动及示例


ESP 系列芯片在应用开发中的常见问题

关于 LCD 屏幕的常见问题,请参考 LCD 应用开发笔记


ESP32-P4 驱动 MIPI-DSI LCD 的一些说明

  • 最高支持 2-lane,每路最高支持 1.5 Gbps 的速率(共 3 Gbps),并且支持 RGB565RGB666RGB888 颜色格式。

  • 部分 MIPI-DSI LCD 默认通过硬件配置为 4-lane,如 ILI9881CJD9365,但大多数 IC 支持通过修改初始化寄存器切换为 2-lane,具体寄存器地址及操作因 IC 型号而异,需查阅 LCD 驱动 IC 数据手册或咨询屏厂确认。ESP32-P4 仅支持 1-lane 和 2-lane 两种配置。

  • 配置 lane_bit_rate_mbps 时:最大不超过 1500 Mbps;建议最小不低于 480 Mbps。实际值可根据分辨率、刷新率、色深和通道数通过公式计算后预留 20% 余量确定,计算方法请参考 MIPI DSI LCD 详解

  • MIPI-DSI 驱动默认开启了通信应答机制 (frame ACK),如果 ESP 与 LCD 之间出现通信异常,ESP 可能会卡死并触发看门狗。此时请检查硬件连接是否正确、初始化命令是否正确、复位时序是否正确,或使用逻辑分析仪排查通信问题。

  • 驱动 MIPI-DSI 屏幕需要为 MIPI DSI PHY 提供 2.5 V 的稳定电源(通过 LDO 获取),请参考对应示例代码的 LDO 配置部分。


ESP 系列芯片的带屏开发板是否支持使用 Arduino IDE 开发 GUI?

  • 目前官方已推出用于 Arduino 开发的 LCD 驱动库 ESP32_Display_Panel,可以直接在 Arduino IDE 上下载,支持的开发板请参考 文档

  • 需要注意以下几点:

    • ESP32_Display_Panel 依赖于 arduino-esp32

    • 由于 ESP32-S3 的 RGB 接口存在 屏幕漂移 问题,需要使用 ESP-IDF release/v5.1 及以上版本的特性来解决,而 arduino-esp32 v2.x.x 版本中使用的 ESP-IDF 版本为 v4.4.x,因此该版本无法解决此问题,需要使用 arduino-esp32 v3.x.x 版本,详细说明请参考 文档

    • 由于使用 Arduino 无法像 ESP-IDF 一样通过 menuconfig 来调整各种参数配置,如编译优化等级等,所以为了实现最佳的性能,推荐基于 ESP-IDF 开发 GUI。


如何提高 LCD 的显示帧率?

  • 关于帧率的详细介绍请参考 ESP-IoT-Solution 编程指南 - LCD 概述。一般来说,受限于 ESP 的计算性能,“接口帧率”往往远大于“渲染帧率”,因此该问题可以表述为“如何提高 LCD 的渲染帧率”。针对这个问题,可以从以下三个方面进行考虑:

    • 提高 ESP 的性能。在使用 ESP-IDF 开发时可以通过 menuconfig 来配置 ESP,而默认并没有配置到最佳性能,这里以 ESP32-S3 为例,我们可以提高 CPU 频率到最高 240 MHz,提高 FreeRTOS tick 的频率到 1000,增大 flash 或 PSRAM 的带宽。除此之外,还有增大 data cache line size,设置编译优化等级为 -O2 等等。

    • 提高 LVGL 的性能。LVGL 本身也是可以通过 menuconfig 或者 lv_conf.h 文件进行配置的,例如设置 LVGL 使用 ESP-IDF 中的 mallocmemcpy 等内存操作函数,开启 fast memory 编译选项等。

    • 优化应用设计。一方面可以通过调整任务的优先级或指定 CPU 核使得 LVGL 和其他任务充分利用 CPU 资源,尤其是对具有双核的 ESP;另一方面也可以优化 GUI 的设计,比如尽量避免使用复杂的动画以及具有透明度的图层混叠效果。

  • 以 ESP32-S3R8 为例,以下 ESP 配置项对帧率提升有帮助 (IDF release/v5.1):

    • CONFIG_FREERTOS_HZ=1000

    • CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y

    • CONFIG_ESPTOOLPY_FLASHMODE_QIO=y

    • CONFIG_ESPTOOLPY_FLASHFREQ_120M=y [需要与 PSRAM 保持一致]

    • CONFIG_SPIRAM_MODE_OCT=y

    • CONFIG_IDF_EXPERIMENTAL_FEATURES=y and CONFIG_SPIRAM_SPEED_120M=y [需要与 FLASH 保持一致]

    • CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y

    • CONFIG_SPIRAM_RODATA=y

    • CONFIG_ESP32S3_DATA_CACHE_LINE_64B=y

    • CONFIG_COMPILER_OPTIMIZATION_PERF=y

  • 在 ESP32-P4 上,可以调整以下配置项以提高帧率(适用于 ESP-IDF release/v5.4 及以上,推荐使用 release/v6.0):

    • CONFIG_CACHE_L2_CACHE_256KB=y

    • CONFIG_CACHE_L2_CACHE_LINE_128B=y

    • CONFIG_SPIRAM_XIP_FROM_PSRAM=y

    • CONFIG_COMPILER_OPTIMIZATION_PERF=y

  • 以下 LVGL 配置项对帧率提升有帮助:

    • LVGL v8CONFIG_LV_MEM_CUSTOM=yCONFIG_LV_MEMCPY_MEMSET_STD=yCONFIG_LV_ATTRIBUTE_FAST_MEM=y

    • LVGL v9CONFIG_LV_OS_FREERTOS=yCONFIG_LV_USE_CLIB_MALLOC=yCONFIG_LV_USE_CLIB_STRING=yCONFIG_LV_USE_CLIB_SPRINTF=yCONFIG_LV_DEF_REFR_PERIOD=15

  • 如果对帧率、旋转效率和防撕裂效果有更高的要求,建议使用 esp_lvgl_adapter 组件


ESP32/ESP32-S2 是否有 I2S 驱动 I80 LCD 的参考代码?

在早期 ESP-IDF(v4.x 及之前)中,ESP32/ESP32-S2 是通过复用 I2S 外设来模拟 I80 (8080) 并行接口驱动 LCD 的。从 ESP-IDF v5.0 起,统一改为使用 esp_lcd 组件的 I80 接口 (esp_lcd_new_i80_bus),不再依赖 I2S 实现,API 更加规范统一。

如需驱动 I80 LCD,请直接参考 LCD 例程 中的 i80_controller 示例,以及 ESP-IDF 编程指南 - I80 LCD


ESP 系列芯片推荐驱动的 LCD 分辨率上限是多少?相应的帧率是多少?

分辨率上限取决于接口类型和实际应用对帧率的要求,建议以能达到流畅帧率(通常 ≥ 30 FPS)的最大分辨率为实际上限,而不是追求硬件理论极限。各平台的典型分辨率与对应帧率(基于 esp_lvgl_adapter + LVGL v9 Benchmark)请查阅 LCD 驱动芯片选型


ESP32-S3R8 如何开启 PSRAM 120M Octal (DDR)?

  • ESP-IDF 需要使用 release/v5.1 及以上分支版本。

  • 通过 menuconfig 开启配置项: IDF_EXPERIMENTAL_FEATURES, SPIRAM_SPEED_120M, SPIRAM_MODE_OCT

  • ESP32-S3-WROOM-1-N16R16V 模组目前不支持此功能,如果启用,可能会出现芯片在上电时卡死然后复位的问题。

  • 需注意,该特性是一种仍在测试完善中的实验功能,并具有以下温度风险:

    • 在温度高于 65°C 的情况下,即使开启 ECC 功能也无法保证正常工作。

    • 温度变化也可能导致访问 PSRAM/flash 时程序崩溃,具体参考 文档


ESP32-S3 使用 RGB 屏幕必须要外接 PSRAM 吗?

  • 通常来说是的,RGB 屏幕要求主控提供至少一个整屏大小的帧缓存,而 RGB 屏幕的分辨率一般较大,ESP32-S3 的 SRAM 很可能无法满足需求。

  • 不推荐使用 4 线 PSRAM,因为 4 线 PSRAM 的带宽较低,会导致 RGB LCD 的 PCLK 无法设置到需要的频率大小。

  • 推荐使用 8 线 PSRAM 并且需要配置时钟为 80 MHz 及以上。


ESP32-S3 如何在保证 RGB 屏幕显示正常的情况下提高 PCLK 的设置上限?

  • 通常来说,PCLK 的设置上限受限于 PSRAM 的带宽,因此需要提高 PSRAM 的带宽:

    • 使用更高频率的 PSRAM 时钟,或者使用更宽的 PSRAM 总线(8 线)。

    • 减少其他外设对 PSRAM 带宽的占用,如 Wi-Fi、flash 等。

    • 降低 Data Cache Line Size 到 32 Byte(使用 RGB Bounce Buffer 模式时需要设置到 64 Byte)。

  • 开启 RGB 驱动的 Bounce Buffer 模式,并且 buffer 越大效果越好,使用方法请参考 文档。需注意,由于该模式下是先通过 CPU 搬运 PSRAM 数据到 SRAM,再通过 GDMA 传输数据到 RGB 外设,因此需要同时开启 CONFIG_ESP32S3_DATA_CACHE_LINE_64B=y,否则可能会导致屏幕出现漂移。

  • 经过少量测试,4 线 PSRAM 80 MHz 时的 PCLK 最高设置至 11 MHz,8 线 PSRAM 80 MHz 时的 PCLK 最高设置至 22 MHz,8 线 PSRAM 120 MHz 时的 PCLK 最高设置至 30 MHz。

  • 对于使用 LVGL 的应用,可以将执行 RGB 外设初始化的任务与执行 LVGL lv_timer_handler() 的任务分配在同一个核上,能够显著提升 PCLK 的设置上限。


ESP 系列芯片的 LCD 应用支持哪些图片解码格式?

  • 软件 JPEG 解码:ESP-IDF 内置 tjpgd 软件解码器,支持 JPEG 格式,参考例程 esp-idf/examples/peripherals/lcd/tjpgd

  • 硬件 JPEG 解码:ESP32-S31 和 ESP32-P4 集成了硬件 JPEG 编解码器 (SOC_JPEG_CODEC_SUPPORTED),支持通过 esp_driver_jpeg 组件进行硬件加速 JPEG 解码,速度显著快于软件解码。

  • 通过 esp_lvgl_adapter + esp_lv_decoder:推荐使用 esp_lvgl_adapter 配合 esp_lv_decoder,支持以下格式:

    • 标准格式:JPG、PNG、QOI

    • 分片格式(针对嵌入式内存优化):SJPG、SPNG、SQOI

    • 硬件加速(仅支持的芯片):JPEG、PJPG

  • 基于 LVGL 内置库:LVGL 本身也提供了 PNG、BMP、GIF 等格式的解码支持,具体见 LVGL libs

  • EAF 动图格式:乐鑫自定义动图格式,原生设计用于配合 esp_emote_gfx 组件刷屏(分段解码),也已适配至 LVGL,参考 EAF 动图格式示例


为什么 ESP32-S3 驱动 RGB LCD 屏幕时出现偏移(显示画面整体漂移)?

  • 原因

    • RGB 外设的 PCLK 设置过高,PSRAM 或 GDMA 的带宽无法满足。

    • PSRAM 和 flash 共用一组 SPI 接口,受写 flash 操作(如 Wi-Fi、OTA、低功耗蓝牙)影响,期间 PSRAM 被禁用。

    • 读取大量的 flash/PSRAM 数据,导致 PSRAM 带宽不足。

  • 配置方面

    • 提高 PSRAM 和 flash 带宽,比如在硬件允许的条件下,采用更高的频率或更大的位宽。

    • 开启 CONFIG_COMPILER_OPTIMIZATION_PERF

    • 降低 Data Cache Line Size 到 32 Byte(使用 RGB Bounce Buffer 模式时需要设置到 64 Byte)。

    • 开启 CONFIG_SPIRAM_FETCH_INSTRUCTIONSCONFIG_SPIRAM_RODATA

    • (不推荐)开启 CONFIG_LCD_RGB_RESTART_IN_VSYNC,可以在屏幕漂移后自动恢复,但无法避免该问题并且降低帧率。

  • 应用方面

    • 在保证屏幕正常工作的前提下,尽量减小 PCLK 的频率,降低 PSRAM 的带宽占用。

    • 如果需要使用 Wi-Fi、低功耗蓝牙和连续写 flash 的操作,请采用 XIP on PSRAM + RGB Bounce buffer 的方法,其中, XIP on PSRAM 用于将代码段和只读段的数据加载到 PSRAM,开启后执行写 flash 操作不会禁用 PSRAM。 RGB Bounce buffer 用于将帧缓存的数据分块通过 CPU 从 PSRAM 搬运到 SRAM,然后再使用 GDMA 传输数据到 RGB 外设,相较于直接采用 PSRAM GDMA 的方式能够实现更高的传输带宽。设置步骤如下:

      • 确认 ESP-IDF 版本为较新 (> 2022.12.12) 的 release/v5.0 及以上,因为旧版本不支持 XIP on PSRAM 的功能(release/v4.4 可以通过打补丁的方式实现,但不推荐)。

      • 确认 PSRAM 配置里面是否能开启 CONFIG_SPIRAM_FETCH_INSTRUCTIONSCONFIG_SPIRAM_RODATA 这两项。如果只读段数据过大(如大量图片),会导致 PSRAM 空间不够,此时可以采用文件系统或将图片制作成 bin 加载到指定分区。

      • 确认内存 (SRAM) 是否有余量,大概需要占用 [10 × screen_width × 4] 字节。

      • 设置 Data cache line size 为 64 Byte(可设置 Data cache size 为 32 KB 以节省内存)。

      • 设置 CONFIG_FREERTOS_HZ 为 1000。

      • 如以上均符合条件,那么就可以参考 文档 修改 RGB 驱动为 Bounce Buffer 模式。如果开启后仍存在漂移现象,可以尝试增大 buffer,但是会占用更多的 SRAM 内存。

      • 如操作 Wi-Fi 仍存在屏幕漂移问题,可以尝试关闭 PSRAM 里 CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP 一项(会占用较大 SRAM)。

      • 设置后带来的影响包括:CPU 使用率升高、可能会造成中断看门狗复位、会造成较大内存开销。

      • 由于 Bounce Buffer 是在 GDMA 中断里通过 CPU 搬运 PSRAM 的数据到 SRAM,程序需要避免长时间执行关中断的操作(如调用 portENTER_CRITICAL()),否则仍会造成屏幕漂移。

    • 短时操作 flash 导致漂移的情况,如 wifi 连接等操作前后,可以在操作前调用 esp_lcd_rgb_panel_set_pclk() 降低 PCLK(如 6 MHz)并延时大约 20 ms(RGB 刷完一帧的时间),然后在操作结束后提高 PCLK 至原始水平,期间可能会造成短暂的闪白屏现象。

    • 如果无法避免,可以开启 CONFIG_LCD_RGB_RESTART_IN_VSYNC 或调用 esp_lcd_rgb_panel_restart() 接口重置 RGB 时序,防止永久性漂移。

    • 关于如何在 Arduino 中避免 RGB 屏幕漂移问题,请参考 链接


为什么驱动 SPI/8080 LCD 屏幕显示 LVGL 时出现纵向错位?

如果采用 DMA 中断传输的方式,flush 完成回调需要在 DMA 传输结束后调用,而不是在 draw_bitmap() 后立即调用。

  • LVGL v8:在 DMA 传输完成中断中调用 lv_disp_flush_ready()

  • LVGL v9:在 DMA 传输完成中断中调用 lv_display_flush_ready()


使用 ESP32-C3 通过 SPI 接口驱动 LCD 液晶显示屏,是否可使用 RTC_CLK 作为 SPI 时钟,让 LCD 液晶显示屏能在 Deep-sleep 模式下正常显示静态图片?

  • Deep-sleep 模式:CPU 和大部分外设都会掉电,只有 RTC 存储器处于工作状态。具体请参考 《ESP32-C3 技术规格书》 中关于“低功耗管理”的说明。

  • ESP32-C3 的 SPI 只支持 APB_CLK 和 XTAL_CLK 两种时钟源,不支持使用 RTC_CLK。因此在 Deep-sleep 模式下,LCD 液晶屏无法显示静态图片。具体请参考 《ESP32-C3 技术参考手册》 > 复位和时钟 [PDF]。

  • 对于 SPI 接口驱动的 LCD 屏幕,一般来说驱动 IC 内置 GRAM,不需要 ESP 持续输出 SPI 时钟的就能正常显示静态图片,只是期间画面无法更新。


使用 ILI9488 LCD 屏幕测试 屏幕 例程,是否支持 9-bit 总线和 18-bit 色深?

ILI9488 驱动芯片可以支持 9-bit 总线和 18-bit 色深,但目前我们的驱动只支持 8-bit 总线和 16-bit 色深。


使用 ESP32-S3 驱动 RGB 屏幕时,为什么运行到 esp_lcd_new_rgb_panel()esp_lcd_panel_init() 就会卡死或复位 (TG1WDT_SYS_RST)?

  • 请检查 ESP 芯片或模组中与 PSRAM 占用的引脚是否与 RGB 引脚有冲突,如有冲突请修改 RGB 引脚配置。

  • 如使用 ESP32-S3R8,请避免使用 GPIO35、GPIO36、GPIO37 引脚。


使用 ESP32-S3 驱动 RGB 屏幕时发现屏幕颜色出现异常反色,即黑色变白色,白色变黑色,如何处理?

请检查屏幕驱动 IC 的初始化寄存器是否设置了 invert_color 功能,举例 ST7789,可通过配置 Inversion 寄存器来修正:

  • INVOFF (20h): Display Inversion Off

  • INVON (21h): Display Inversion On


使用 ESP32-S3 驱动 RGB 屏幕时发现屏幕颜色不正,出现缺色,如何处理?

很可能是 RGB 配置有误,可以排查以下几个方面:

  • 检查是否为 RGB/BGR 设置错误:如将屏幕配置为红色 (0xC0, 0x0, 0x0),但屏幕实际显示黑色。

  • 检查 RGB 和 BGR 的寄存器是否设置:如 ST7789,可通过 MADCTL (36h) 寄存器修正(当 MADCTL (36h) = 1 时,为 BGR,当 MADCTL (36h) = 0 时,为 RGB)。

  • 检查是否为 LVGL SWAP16 设置错误:如将屏幕配置为红色 (0xC0, 0x0, 0x0),但屏幕实际显示蓝色,此时可 menuconfig → Component config → LVGL configuration → Color settings

  • 如 RGB TTL 屏幕显示缺色,需要分别设置 R、G、B 显示,检查有波形的通道和 RGB 数据线设计是否符合。


LVGL 的 label 中正确输入了空格,比如“室内温度 25.5℃”,但在屏幕上没有显示空格,请问是什么原因,怎么排查?

这属于 LVGL label 显示缺失,可以打开如下调试项,缺失字符会用方块填充,防止 map 缺失:

  • Component configLVGL configurationFont usageEnable drawing placeholders when glyph dsc is not found


LVGL v8 连续加载存放在 flash 上的不同图片时速度太慢,比如在屏幕首页循环展示三张图片时该如何规避速度慢的问题?

  • 速度慢的原因是没有打开对应的图片缓存机制,每次使用时都需要通过解析器进行解析。

  • 直接通过 #define LV_IMG_CACHE_DEF_SIZE 1 宏打开对应的图片缓存机制即可,这里的 1 代表图片缓存的数量。请注意,此操作会消耗更多内存。


LVGL v8 加载 flash 里的 PNG、JPEG 图片失败。屏幕上显示一片空白,什么原因?

  • 首先需要查看下剩余内存的情况,LVGL 加载图片需要进行 loadpng_get_raw_size 和 loadpng_convert 两个步骤,如内存不够会直接返回错误码 83。

  • 也可以提前估计下内存需求:loadpng_get_raw_size 需要和图片大小一致的内存, loadpng_convert 需要图片长度*宽度*3 字节的内存,如果还开启了图片缓存机制导致 image_cache 过大,会同步导致内存紧张。


如何将 GIF 动图转成 C 语言代码来使用?

将 GIF 转成 Map 选项,Color format 为 CF_RAW。


屏幕显示 GIF 动图时是否能设置为透明?

可以,但是 GIF 只有 1 bit Alpha 描述值,所以只能全透或者不透明,没有半透明。


LVGL 界面上的图片格式选择哪种比较好?有没有对比说明?

可以参考以下表格:

图片格式

透明支持

大小

解码速度

PNG

完美支持

适中

适中

BMP

有限支持

较大

最快,无需解码

JPG

不支持

较小

快速

在将图片用 LVGL imageconverter 转成 MAP 时,如采用 CF_TRUE_COLOR 等格式(非 RAW 格式)转换,后续 LVGL 加载均不需要二次解码,但会占用比较大的代码段。


在使用 LVGL 的一些第三方库如 FreeType、Lottie 时,程序正常加载,但是屏幕显示一片空白,为什么?

先考虑任务堆栈设置是否有误:

  • FreeType:使用 esp_lvgl_adapter 时,首先确认堆栈配置:LVGL v8 需将 CONFIG_ESP_MAIN_TASK_STACK_SIZE 设置为 32768(字体初始化在调用线程执行);LVGL v9 需将 CONFIG_LV_DRAW_THREAD_STACK_SIZE 设置为 32768(字体渲染在绘图线程执行)。此外,可通过以下两个 Kconfig 优化选项降低资源占用:

    • ESP_LVGL_ADAPTER_FREETYPE_SMALL_RENDER_POOL:将 FreeType render pool 从 16 KB 降至 4 KB,可同时减少 LVGL v9 绘图线程的栈需求。

    • ESP_LVGL_ADAPTER_FREETYPE_MINIMAL_BUILD:裁剪 FreeType 编译模块,仅保留 TTF/OTF 常用路径所需内容(去除 Type1/CID/BDF/PCF 等 legacy 驱动及压缩流辅助),可显著降低 flash 占用;若项目需要上述被裁剪的格式,请勿开启。

    参考示例:lvgl_freetype_font

  • Lottie:一般需要分配 30 KB 以上的任务堆栈,参考 lottie 移植


ESP32-S3 驱动 SPI 屏幕,内部 RAM 不够给整屏 buffer 分配空间,有什么好的办法?

可使用 PSRAM 做 framebuffer,然后用较小的 SRAM buffer 来将数据分多次搬运到 framebuffer(SPI DMA 无法直接搬运 PSRAM 数据),完成搬运后直接用 framebuffer 进行渲染即可。相比小 buffer 直接渲染然后发送数据,可防撕裂,加快渲染速度。具体实现可参考 esp_lvgl_adapter


SPI 屏幕上的图片在硬件旋转 90 度或 270 度后会出现斜撕裂的现象,如何处理?

建议在普通模式下使能 LVGL sw_rotate 标志位,使用 LVGL 的软件旋转功能进行处理。但要注意 sw_rotatefull_refreshdirect_mode 有冲突,请不要同时使用。例如在 full_refresh 下调用 sw_rotate 将直接 return,不会产生任何作用。

备注

sw_rotatefull_refreshdirect_mode 均为 LVGL v8 的 API。LVGL v9 的旋转方式有所不同,请参考 LVGL v9 旋转说明


ESP32-S2 USB 摄像头和 I80 LCD 同时使用会导致 LCD 显示缺图像或者异常,如何解决?

需要参考 此段代码 来增加 I2S 启动延迟时间。


通过非 LVGL 任务操作 LVGL 控件时出现异常 crash,如何解决?

LVGL API 不是线程安全的,在非 LVGL 任务中操作 LVGL 控件时必须加锁保护。

  • 若使用 esp_lvgl_adapter 组件,使用其提供的锁 API:

    if (esp_lv_adapter_lock(-1) == ESP_OK) {
        /* LVGL API 调用 */
        esp_lv_adapter_unlock();
    }
    
  • 若使用旧版 esp_lvgl_port 组件,对应 API 为 lvgl_port_lock(0)lvgl_port_unlock()


ESP32-S3 是否支持 RGB888?

不支持并行 RGB888(ESP32-P4 支持并行 RGB888),仅支持 RGB565。可以设置串行 RGB888 输出,具体配置如下:

esp_lcd_rgb_panel_config_t panel_conf = {
...
.data_width = 8,
.bits_per_pixel = 24,
...
}

在操作 LVGL 的 tabview 时,想要禁止其左右滑动功能,该怎么实现?

通过添加 lv_obj_clear_flag(lv_tabview_get_content(tabview), LV_OBJ_FLAG_SCROLLABLE); 这行代码即可。


LVGL 是否支持多 indev 输入?

支持,所有 indev 按照链表管理,支持多个同类型和不同类型的输入设备。使用例程可以参考组件 espressif/esp_lvgl_adapter,目前组件支持的输入设备类型有 touch、button、knob。


LVGL 是否支持多点触控?

LVGL 本身对多点触控的支持因版本而异:

  • LVGL v8:不支持原生多点触控,每个 indev 只能上报一个触点。

  • LVGL v9:支持多指针输入 (multi-pointer),可为同一显示注册多个触摸 indev,各触点独立控制不同控件。

使用 esp_lvgl_adapter 时,可在注册触摸设备时启用多点模式(仅 LVGL v9):

esp_lv_adapter_touch_config_t touch_cfg = ESP_LV_ADAPTER_TOUCH_DEFAULT_CONFIG(disp, touch_handle);
touch_cfg.multi_touch.mode = ESP_LV_ADAPTER_TOUCH_MODE_MULTI_CONTROL;
touch_cfg.multi_touch.pointers = 2;  /* 需 >= 2,且不超过 CONFIG_ESP_LCD_TOUCH_MAX_POINTS */
lv_indev_t *touch = esp_lv_adapter_register_touch(&touch_cfg);

LVGL 统计的 CPU 占用率过高,有没有什么影响?

LVGL 统计的 CPU 占用率计算的是 500 ms 内 LVGL 渲染任务的时长,并不能代表 CPU 真实的占用率。可以用 FreeRTOS 的 vTaskGetRunTimeStats 来统计真实占用率。


使能 RGB 屏驱动后,ESP32-S3 能否进入 Light-sleep 模式?

直接使用 esp_lcd RGB 驱动:初始化 RGB 接口时,如果使能了 CONFIG_PM_ENABLE,驱动会自动持有 ESP_PM_NO_LIGHT_SLEEP 锁,导致无法进入 Light-sleep 模式。如需进入 Light-sleep,必须先调用 esp_lcd_panel_del() 删除 RGB 面板(释放锁),睡眠唤醒后再重新初始化。

使用 esp_lvgl_adapter 组件:该组件提供两种 Light-sleep 使用方式,LVGL 界面状态(控件树)在睡眠期间均可保留,无需重建 UI。

手动睡眠:由应用代码控制完整的睡眠/唤醒流程:

  1. 进入睡眠前调用 esp_lv_adapter_sleep_prepare() 暂停适配器并等待当前帧刷新完成。

  2. 调用 esp_lcd_panel_del() 释放显示硬件资源。

  3. 调用 esp_light_sleep_start() 进入 Light-sleep。

  4. 唤醒后重新初始化 LCD 硬件,再调用 esp_lv_adapter_sleep_recover() 重新绑定面板并恢复适配器运行。

自动睡眠 (auto_sleep):在初始化时配置空闲超时,适配器在 LVGL 空闲超过指定时间后自动触发睡眠:

esp_lv_adapter_config_t cfg = ESP_LV_ADAPTER_DEFAULT_CONFIG();
cfg.auto_sleep.enable = true;
cfg.auto_sleep.idle_timeout_ms = 5000;  /* 空闲 5 s 后自动睡眠 */

/* Pause 模式:适配器释放锁并暂停 LVGL,系统进入 tickless light sleep,
   面板休眠/背光由用户回调负责 */
cfg.auto_sleep.mode = ESP_LV_ADAPTER_AUTO_SLEEP_MODE_PAUSE;
cfg.auto_sleep.callbacks.on_enter_sleep = panel_sleep_cb;
cfg.auto_sleep.callbacks.on_exit_sleep  = panel_wake_cb;

/* User 模式:on_enter_sleep 回调负责完整的 sleep_prepare → LCD deinit →
   light_sleep_start → LCD init → sleep_recover 流程 */
/* cfg.auto_sleep.mode = ESP_LV_ADAPTER_AUTO_SLEEP_MODE_USER; */

ESP_ERROR_CHECK(esp_lv_adapter_init(&cfg));

Pause 模式下,已注册的触摸/按键/旋钮输入会自动通知适配器唤醒;自定义唤醒源可调用 esp_lv_adapter_request_wake()esp_lv_adapter_request_wake_from_isr()


我们是否支持驱动液晶段码屏?

我们的芯片无法通过 GPIO 直接连接液晶段码屏进行驱动,因为驱动段码屏需要高低电平循环,要求工作电压为 2.7 V 至 5.0 V 的交流电压,典型值为 3.0 V、3.3 V、4.5 V 和 5.0 V,而我们的芯片不支持调整电压范围。


使用 ESP32-P4 驱动 RGB LCD 时,屏幕出现颜色异常,如何排查?

ESP32-P4 拥有多路 VDDPST 电源域,每路 VDDPST 控制对应区域 GPIO 的最大输出电平(具体 GPIO 与 VDDPST 的对应关系请参考 ESP32-P4 数据手册)。若对应 VDDPST 供电不足或未正确配置,部分 GPIO 最大输出电平可能为 1.8 V,导致 RGB 接口信号电平不足,进而引发屏幕颜色异常。请检查 RGB 接口所用 GPIO 的 VDDPST 是否已配置为正确电压(通常为 3.3 V)。

另需说明:与 ESP32-S3(PCLK 最高约 30 MHz)不同,ESP32-S31 和 ESP32-P4 的 RGB 接口时钟频率无上述 30 MHz 上限,因此可支持更高的接口帧率和更大分辨率的 RGB 屏幕。


ESP32-P4 是否支持输出 HDMI 信号?

ESP32-P4 不支持直接输出 HDMI 信号,但可以通过 MIPI-DSI 转 HDMI 的芯片来实现 HDMI 信号输出。目前,乐鑫支持的 MIPI-DSI 转 HDMI 芯片为 LT8912B,相关使用方法可参考 示例代码


在 LVGL 应用中,RGB 或者 MIPI-DSI 接口屏幕如何旋转 90 度/270 度?如何避免撕裂现象?如何进一步提高帧率?


ESP32-P4 在未连接 MIPI 外设的情况下,能否产生 MIPI-DSI 信号(LP 和 HP)?

理论上可以,但有限制:LP 阶段可输出部分信号;HP 阶段因驱动默认开启 frame ACK 且无超时机制,FIFO 满后会一直等待 ACK (BTA),导致链路卡住。若仅需抓取波形片段即可满足需求。若要持续输出,需修改 IDF 内部的 MIPI-DSI 驱动,目前无法仅靠外部配置实现。


EAF 格式的 GIF 动画在 ESP32-S3/P4 上播放较慢,如何优化?

  • 可将 EAF 编码格式改为 JPEG(在转换工具中设置),体积会增大但解码更快;

  • 对于较大分辨率屏幕(如 466×466),LVGL 渲染负担较重;

  • 相比 EAF + LVGL,直接使用 esp_emote_gfx 组件刷屏(分段解码)效率更高,EAF 本来就是为 esp_emote_gfx 设计的,只是额外适配到了 LVGL;

  • AVI(JPEG 编码帧)在 LCD 上显示比 GIF 更流畅;

  • P4 revision v3.1 优化了 CPU 主频和 PSRAM 带宽,在 1080p RGB888 下,LVGL 和 MP4 可稳定达到 15 帧。


ESP32-P4 驱动 MIPI-DSI LCD 无图像显示,且无其他报错日志,如何排查?

首先检查 SPIRAM 时钟速率是否已配置为 200 MHz 及以上 (CONFIG_SPIRAM_SPEED_200M=y)。驱动 MIPI-DSI 接口屏幕需要 PSRAM 具备更高的带宽,带宽不足时屏幕可能无法正常显示但不报错。

其次检查 DSI 数据引脚 (DSI_DATAN0/DSI_DATAP0) 和时钟引脚 (DSI_CLKN/DSI_CLKP) 与屏幕的物理连接是否正确。


ESP32-P4 驱动 MIPI-DSI LCD 出现画面扭曲或错位,如何处理?

该问题一般由 lane_bit_rate_mbps 与实际 pixel_clock 不匹配,或 lane_bit_rate_mbps 与屏幕要求的速率不匹配引起。可根据分辨率、刷新率、色深和 lane 数量重新计算 lane_bit_rate_mbps (预留约 20% 余量),具体计算方法请参考 MIPI DSI LCD 详解。注意 ESP32-P4 上 lane_bit_rate_mbps 最大不超过 1500,建议最小不低于 480。


ESP32-P4 驱动 MIPI-DSI LCD 出现屏幕闪蓝屏,并提示 “can’t fetch data from external memory fast enough, underrun happens”,如何处理?

该问题由 PSRAM 带宽不足导致。可尝试以下方法:

  • 降低 lane_bit_rate_mbpsdpi_clock_freq_mhz (像素时钟频率)。

  • 若使用 RGB888 色彩格式,考虑改为 RGB565 以降低带宽需求。

  • 开启以下配置项以改善 PSRAM 带宽:

    • CONFIG_SPIRAM_XIP_FROM_PSRAM=y

    • CONFIG_CACHE_L2_CACHE_256KB=y

    • CONFIG_CACHE_L2_CACHE_LINE_128B=y

    • CONFIG_COMPILER_OPTIMIZATION_PERF=y