news 2026/9/20 22:47:00

esp-iot-solution LVGL Common Demo 实战:一套代码驱动 MIPI DSI / RGB / QSPI / SPI 四类 LCD 并跑通官方 Benchmark

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
esp-iot-solution LVGL Common Demo 实战:一套代码驱动 MIPI DSI / RGB / QSPI / SPI 四类 LCD 并跑通官方 Benchmark

esp-iot-solution LVGL Common Demo 实战:一套代码驱动 MIPI DSI / RGB / QSPI / SPI 四类 LCD 并跑通官方 Benchmark

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

导读lvgl_common_demo是 esp-iot-solution 仓库中基于esp_lvgl_adapter组件与 LVGL 9 的"统一显示"参考示例,仅需一份代码即可在 MIPI DSI、RGB、QSPI、SPI 四类 LCD 接口上运行 LVGL 官方 Benchmark(基准测试)。本文以该示例的 README.md 为骨架,结合hw_initexample_lvgl_init等源码实现,完整讲解硬件选型、menuconfig 配置、编译烧录、八步初始化流程、FPS 监控与撕裂规避原理,帮助你在自己的开发板上快速跑通 LVGL 性能评估。

示例定位与适用场景

lvgl_common_demo展示的是如何使用esp_lvgl_adapter组件与 LVGL 协同工作,在不同 LCD 接口上运行 LVGL 官方 benchmark demo,是"以统一方式把 LVGL 接入不同类型显示屏"的参考实现(见 README.md)。

它最典型的用途包括:

  • 评估不同 LCD 接口的显示性能(DSI / RGB / QSPI / SPI 横向对比渲染能力);
  • 验证硬件连接与驱动配置是否正确;
  • 对 LVGL 渲染能力做基准测试(Benchmark);
  • 学习基于esp_lvgl_adapter的 LVGL 应用标准工程结构

该示例支持以下芯片与接口组合(见 README 首部表格):

Supported TargetsESP32-P4ESP32-S3ESP32-S31ESP32-C3

核心特性一览

  • 统一 LCD 接口支持:单套代码即可驱动 MIPI DSI、RGB、QSPI、SPI 四种 LCD 面板;
  • LVGL benchmark demo:运行标准 LVGL 基准测试,量化渲染性能;
  • 多输入方式:同时支持触摸屏与旋转编码器(旋钮)输入;
  • FPS 监控:可选帧率统计,便于性能分析;
  • 显示旋转:可配置屏幕方向(0°/90°/180°/270°);
  • 防撕裂(Tear Avoidance):内置撕裂规避机制。

硬件准备与推荐组合

硬件需求

根据 README.md,你需要:

  • 一块 ESP32-P4、ESP32-S3、ESP32-S31 或 ESP32-C3 开发板;
  • 一块带以下任一接口的 LCD 面板:
    • MIPI DSI:面向高分辨率屏(如 1024x600);
    • RGB:并行 RGB 接口(如 800x480);
    • QSPI:四线 SPI 屏(如 360x360、400x400);
    • SPI:标准 SPI 屏(如 240x240、320x240);
  • (可选)触摸屏或旋转编码器作为输入;
  • 一条用于供电与烧录的 USB 线。

推荐硬件组合

ChipLCD InterfaceDevelopment Board
ESP32-P4MIPI DSIESP32-P4-Function-EV-Board
ESP32-S3RGBESP32-S3-LCD-EV-Board
ESP32-S3QSPIESP-VoCat
ESP32-S3SPIESP32-S3-BOX-3
ESP32-S31RGB参考你的开发板文档
ESP32-C3SPIESP32-C3-LCDkit

上表中开发板的官方资料链接请查阅 README.md 原文(各开发板的硬件手册由乐鑫官方维护)。

硬件连接要点

LCD 与触摸屏的具体接线取决于你的硬件配置。本示例使用hw_init组件提供针对不同板卡的硬件抽象(详见 hw_init 目录)。常见接口的接线特征如下(见 README.md):

  • MIPI DSI:使用专用 MIPI 差分线(D0+/-、D1+/-、CLK+/-);
  • RGB:并行数据线(RGB565 为 16 根数据线 + HSYNC/VSYNC/DE/PCLK);
  • QSPI:4 根数据线(IO0-IO3 + CLK + CS);
  • SPI:标准 SPI 引脚(MOSI/MISO/CLK + CS + DC)。

输入设备方面:触摸屏通常走 I2C 或 SPI;旋转编码器使用 3 个 GPIO(A、B 相与按键)。具体 GPIO 映射请参考开发板原理图或hw_init组件配置。

工程结构与依赖关系

目录结构

examples/display/gui/lvgl_common_demo/ ├── main/ │ ├── CMakeLists.txt │ ├── idf_component.yml # 组件依赖声明 │ └── main.c # 主应用逻辑 ├── CMakeLists.txt # 项目级 CMake ├── README.md ├── partitions.csv # 自定义分区表 ├── sdkconfig.defaults # 默认配置 ├── sdkconfig.defaults.esp32c3 ├── sdkconfig.defaults.esp32p4 ├── sdkconfig.defaults.esp32s3 └── sdkconfig.defaults.esp32s31 # 各芯片专属配置

组件依赖(idf_component.yml)

main/idf_component.yml 声明了关键依赖:

dependencies: idf: version: ">=5.5.0" lvgl/lvgl: version: "^9" public: true espressif/esp_lvgl_adapter: version: "*" override_path: "../../../../../components/display/tools/esp_lvgl_adapter" public: true example_lvgl_init: version: "*" override_path: "../../common/example_lvgl_init" hw_init: version: "*" override_path: "../../common/hw_init"

要点解读:

  • IDF 版本要求 ≥ 5.5.0
  • LVGL 采用9.x版本;
  • esp_lvgl_adapter通过override_path直接指向仓库内组件源码 components/display/tools/esp_lvgl_adapter,保证示例与仓库最新实现同步;
  • example_lvgl_inithw_initgui/common目录下的共享参考组件,被本示例及其他 GUI 示例复用。

其中hw_init组件内部又分为lcd/lcd_init_mipi_dsi.clcd_init_rgb.clcd_init_qspi.clcd_init_spi_with_psram.clcd_init_spi_without_psram.c)、input/touch_init.cknob_init.c)与helpers/(旋转辅助工具),覆盖了五类 LCD 接口与两类输入设备的初始化。

menuconfig 配置详解

运行idf.py menuconfig后,进入Example Configuration菜单即可配置示例(见 README.md)。

LCD 接口选择

LCD Interface Type:在 MIPI DSI、RGB、QSPI、SPI 之间选择。该选项定义于 common/hw_init/Kconfig.projbuild,其默认值随芯片自动切换:

接口选项分辨率输入设备适用芯片
MIPI DSI Interface1024x600Touch仅 ESP32-P4
QSPI Interface360x360Touch非 ESP32-C3(需 PSRAM)
RGB Interface800x480TouchESP32-S3 / ESP32-P4 / ESP32-S31(需 PSRAM)
SPI Interface with PSRAM320x240Touch非 ESP32-C3
SPI Interface without PSRAM240x240Encoder/Knob全部(适合资源受限芯片)

选中接口后,分辨率与输入设备类型由hw_init.h中的宏自动确定(见 common/hw_init/hw_init.h),例如:

#if CONFIG_EXAMPLE_LCD_INTERFACE_MIPI_DSI #define HW_LCD_H_RES 1024 #define HW_LCD_V_RES 600 #define HW_USE_TOUCH 1 #define HW_USE_ENCODER 0 #elif CONFIG_EXAMPLE_LCD_INTERFACE_RGB #define HW_LCD_H_RES 800 #define HW_LCD_V_RES 480 ... #endif

注意:如果未选中任何接口,编译时会在 hw_init.c 触发#error "No LCD interface selected! Please select one in menuconfig.";若接口不支持触摸却也没启用编码器,则会报#error "No input device configured!"

显示设置

Display Rotation:选择屏幕方向 0°/90°/180°/270°(顺时针)。该选项同样由 Kconfig.projbuild 定义,默认 0 度。旋转会同时作用于 LCD 面板与触摸控制器,使 LVGL 坐标与屏幕方向保持一致——这也是example_lvgl_initget_configured_rotation()所读取的内容(见 example_lvgl_init.c):

static esp_lv_adapter_rotation_t get_configured_rotation(void) { #if CONFIG_EXAMPLE_DISPLAY_ROTATION_0 return ESP_LV_ADAPTER_ROTATE_0; #elif CONFIG_EXAMPLE_DISPLAY_ROTATION_90 return ESP_LV_ADAPTER_ROTATE_90; #elif CONFIG_EXAMPLE_DISPLAY_ROTATION_180 return ESP_LV_ADAPTER_ROTATE_180; #elif CONFIG_EXAMPLE_DISPLAY_ROTATION_270 return ESP_LV_ADAPTER_ROTATE_270; #else return ESP_LV_ADAPTER_ROTATE_0; #endif }

LCD 分辨率与时序参数则在hw_init中配置。

输入设备

  • 选择触摸或编码器输入;
  • 触摸控制器需配置 I2C/SPI 参数(并核对 I2C 地址)。

性能选项

Enable FPS Statistics:开启后将在日志中周期性打印帧率(对应CONFIG_ESP_LVGL_ADAPTER_ENABLE_FPS_STATS)。

sdkconfig.defaults 中的关键调优

仓库为示例预设了一组面向性能的默认配置(见 sdkconfig.defaults):

CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_COMPILER_OPTIMIZATION_PERF=y CONFIG_FREERTOS_HZ=1000 CONFIG_LV_USE_CLIB_MALLOC=y CONFIG_LV_USE_CLIB_STRING=y CONFIG_LV_USE_CLIB_SPRINTF=y CONFIG_LV_DEF_REFR_PERIOD=15 CONFIG_LV_DPI_DEF=60 CONFIG_LV_OS_FREERTOS=y CONFIG_LV_DRAW_LAYER_SIMPLE_BUF_SIZE=48000 CONFIG_LV_DRAW_THREAD_PRIO=4 CONFIG_LV_DRAW_SW_SHADOW_CACHE_SIZE=4 CONFIG_LV_GRADIENT_MAX_STOPS=4 CONFIG_LV_OBJ_STYLE_CACHE=y CONFIG_LV_USE_SYSMON=y CONFIG_LV_USE_PERF_MONITOR=y CONFIG_LV_USE_DEMO_BENCHMARK=y CONFIG_ESP_LVGL_ADAPTER_ENABLE_FPS_STATS=y

其中值得关注的是:编译器启用性能优化、CONFIG_LV_OS_FREERTOS=y(LVGL 由 FreeRTOS 承载)、刷新周期 15ms、启用 benchmark demo 与 FPS 统计。各芯片专属的sdkconfig.defaults.esp32p4/esp32s3/esp32s31/esp32c3则按芯片能力进一步差异化配置。

编译、烧录与运行

构建命令

  1. 先设置目标芯片(见 README.md):
idf.py set-target esp32p4 # 或 idf.py set-target esp32s3 # 或 idf.py set-target esp32s31 # 或 idf.py set-target esp32c3
  1. 编译、烧录并打开串口监视器:
idf.py -p PORT build flash monitor

(退出串口监视器请按Ctrl-]。)

首次构建会花较长时间,因为构建系统需要从组件仓库下载组件到managed_components目录。完整的 ESP-IDF 环境搭建步骤参考官方 Getting Started Guide(链接见 README 原文)。此外,若构建报错,可尝试idf.py fullclean后重新构建。

预期输出

烧录成功后,LCD 将显示 LVGL benchmark demo——包含多种动画与 UI 元素以压力测试渲染性能。串口控制台会打印初始化日志(README.md):

I (xxx) main: Selected LCD interface: MIPI DSI I (xxx) main: Initializing LCD: 1024x600 I (xxx) main: Starting LVGL benchmark demo

若开启了 FPS 统计,将周期性看到帧率报告:

I (xxx) main: Current FPS: 45

Benchmark 会自动循环切换不同测试场景,展示形状、图片、文本与动画。示例的app_main本身非常精简(main/main.c):

void app_main(void) { example_lvgl_ctx_t ctx; ESP_ERROR_CHECK(example_lvgl_init(&ctx)); ESP_LOGI(TAG, "Starting LVGL benchmark demo"); if (esp_lv_adapter_lock(-1) == ESP_OK) { lv_demo_benchmark(); esp_lv_adapter_unlock(); } }

可见:初始化全部由example_lvgl_init()完成,主任务通过esp_lv_adapter_lock()获取 LVGL 互斥锁后调用lv_demo_benchmark()启动基准测试,运行完毕释放锁——这正是适配器提供的线程安全调用模式。

八步初始化流程(源码级拆解)

example_lvgl_init()的注释明确说明该文件采用"平铺、逐步"风格编写,旨在成为新项目的复制粘贴起点(见 example_lvgl_init.c)。完整序列如下(对应头文件中的步骤说明 example_lvgl_init.h):

  1. 读取旋转配置:从 Kconfig(CONFIG_EXAMPLE_DISPLAY_ROTATION_*)解析出esp_lv_adapter_rotation_t存入ctx->rotation
  2. 选择撕裂规避模式:按接口类型确定ctx->tear_mode
    • MIPI DSI →ESP_LV_ADAPTER_TEAR_AVOID_MODE_DEFAULT_MIPI_DSI
    • RGB →ESP_LV_ADAPTER_TEAR_AVOID_MODE_DEFAULT_RGB
    • SPI/QSPI → 通过hw_lcd_get_te_gpio()检测面板是否提供 TE 引脚:有则启用ESP_LV_ADAPTER_TEAR_AVOID_MODE_TE_SYNC并打印TE sync enabled on GPIO x,无则回退默认模式;
  3. 初始化 LCD 面板hw_lcd_init(&ctx->panel, &ctx->panel_io, ctx->tear_mode, ctx->rotation)
  4. 初始化 LVGL 适配器esp_lv_adapter_init(&adapter_cfg),使用默认配置宏ESP_LV_ADAPTER_DEFAULT_CONFIG()
  5. 注册显示设备esp_lv_adapter_register_display(&display_cfg)。关键点在于按接口选择不同的默认配置宏(example_lvgl_init.c):
    • MIPI DSI →ESP_LV_ADAPTER_DISPLAY_MIPI_DEFAULT_CONFIG(panel, panel_io, h, v, rotation)
    • RGB →ESP_LV_ADAPTER_DISPLAY_RGB_DEFAULT_CONFIG(...)
    • SPI(无 PSRAM)→ESP_LV_ADAPTER_DISPLAY_SPI_WITHOUT_PSRAM_DEFAULT_CONFIG(...)
    • QSPI / SPI(有 PSRAM)→ 有 TE 时用..._SPI_WITH_PSRAM_TE_DEFAULT_CONFIG(..., te_gpio, bus_freq, data_lines, bits_per_pixel),无 TE 时用普通版本;
  6. 初始化输入设备HW_USE_TOUCH时走hw_touch_init()+esp_lv_adapter_register_touch()HW_USE_ENCODER && CONFIG_ESP_LVGL_ADAPTER_ENABLE_KNOB时用hw_knob_get_config()/hw_knob_get_button()填充编码器配置后esp_lv_adapter_register_encoder()(example_lvgl_init.c);
  7. 启动 LVGL 工作任务esp_lv_adapter_start()
  8. (可选)启动 FPS 监控:仅当CONFIG_ESP_LVGL_ADAPTER_ENABLE_FPS_STATS开启时,先调用esp_lv_adapter_fps_stats_enable(ctx->disp, true),再创建fps_monitor_task,每 1000ms 通过esp_lv_adapter_get_fps(disp, &fps)读取并打印帧率(example_lvgl_init.c)。

所有初始化结果统一封装进example_lvgl_ctx_t结构体(example_lvgl_init.h),包含显示句柄、触摸/编码器输入设备句柄、面板句柄、旋转与撕裂规避模式等字段;不适用的字段置 NULL。

fps_monitor_taskesp_lv_adapter_get_fps()等接口的底层实现,可进一步在 esp_lvgl_adapter 组件 中查阅(include/esp_lv_adapter.h声明、src/adapter/esp_lv_adapter.c实现),组件的 benchmark 测试例程 test_esp_lvgl_adapter_fps.c 也展示了 FPS 统计接口的典型用法。

示例展示的关键能力

根据 README.md,本示例集中演示了五方面能力:

  1. 统一 LCD API:同一代码库驱动多种 LCD 接口类型;
  2. LVGL 集成:规范的 LVGL 初始化与任务管理;
  3. 输入处理:触摸与编码器输入设备的注册;
  4. 性能监控:基于适配器特性的可选 FPS 统计;
  5. 线程安全:基于互斥锁(mutex)保护 LVGL API 调用。

故障排查(Troubleshooting)

以下是 README.md 给出的常见问题与排查思路:

屏幕无显示:

  • 检查 LCD 供电与背光连接;
  • 在 menuconfig 中核对 GPIO 引脚映射;
  • 确认选择了正确的 LCD 接口类型;
  • 核对面板的 LCD 初始化时序。

触摸/编码器无响应:

  • 检查 I2C/GPIO 连接;
  • 在 menuconfig 中启用输入设备;
  • 核对触摸控制器的 I2C 地址。

构建错误:

  • 确保 ESP-IDF 版本为 5.5.0 或更高;
  • 执行idf.py fullclean后重新构建;
  • 确认所有 managed components 均已正确下载。

技术问题可前往仓库 Issues 反馈(链接见 README 原文)。

延伸阅读

  • 组件源码:components/display/tools/esp_lvgl_adapter(含中英文 README、benchmark 测试用例)
  • 共享初始化参考组件:examples/display/gui/common/example_lvgl_init
  • 硬件抽象组件:examples/display/gui/common/hw_init
  • 同目录下其他 GUI 示例(如lvgl_multi_screenlvgl_light_sleep_demolvgl_freetype_font等)复用同一套example_lvgl_init/hw_init基础设施,可作为下一步改造与扩展的参考。

若你正在评估某款屏幕的渲染性能,或准备基于esp_lvgl_adapter从零搭建自己的 GUI 工程,lvgl_common_demo是理想的起点:先跑通 Benchmark,再以example_lvgl_init.c为模板逐步替换成自己的应用逻辑即可。

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

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/20 22:45:17

ChatTTS-ui 语音合成音色定制:10分钟拿到3种选音色方法

ChatTTS-ui 语音合成音色定制:10分钟拿到3种选音色方法 【免费下载链接】ChatTTS-ui 一个简单的本地网页界面,使用ChatTTS将文字合成为语音,同时支持对外提供API接口。A simple native web interface that uses ChatTTS to synthesize text i…

作者头像 李华
网站建设 2026/9/20 22:45:13

油猴脚本装完不生效?从匹配规则到CSP的完整排查指南

油猴脚本装好了,脚本也显示“安装成功”,打开网页却一动不动——这个情况我见得太多了。不管是 Tampermonkey 还是 Violentmonkey,凡是折腾过用户脚本的人,十有八九都栽过这个跟头。明明安装步骤没毛病,油猴扩展也在工…

作者头像 李华
网站建设 2026/9/20 22:44:54

QQ空间历史说说导出:免费开源工具的完整使用指南

QQ空间历史说说导出:免费开源工具的完整使用指南 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 为什么几年的QQ空间说说自己翻不到 想找一条几年前发的说说,从…

作者头像 李华
网站建设 2026/9/20 22:44:48

@mdx-js/vue 完全指南:在 Vue 项目中用 Context 为 MDX 注入组件

mdx-js/vue 完全指南:在 Vue 项目中用 Context 为 MDX 注入组件 【免费下载链接】mdx Markdown for the component era 项目地址: https://gitcode.com/gh_mirrors/md/mdx mdx-js/vue 是 MDX 官方生态中面向 Vue 的 context 组件提供器,它基于 Vu…

作者头像 李华
网站建设 2026/9/20 22:42:39

从网页对话到AI编程工作台:本地模型、模型网关与提示词实战

最近大半年,我把自己的开发环境逐步从“编辑器 浏览器问AI”切换成了一整套真正意义上的 AI 编程工作台。这里说的“工作台”不是某个软件,而是一套组合:终端、编辑器、本地模型、云端 API、提示词模板和自动化脚本协同工作,目的…

作者头像 李华