ESP32-LVGL 安装移植应用实训记录表(课程记录)
本文详细记录了基于ESP32和LVGL 9.4.0的嵌入式界面开发实训过程。主要内容包括:1) LVGL环境配置步骤与常见问题解决方法;2) LCD驱动代码与LVGL的适配修改方案;3) 主程序调用流程设计;4) 功能测试方法与问题排查步骤;5) 典型问题分析与优化建议。通过实际案例演示了如何将LVGUI框架与原有LCD驱动进行整合,实现触摸交互、控件显示等核心功能,并总结了路径配置、触摸响应、性
机器人设计与应用综合实训技术分享
ESP32-LVGL 安装移植应用实训记录表
适配开发环境:ESP-IDF、LVGL 9.4.0
前置基础:ESP32-LCD 汉字 / 时钟 / 动图基础开发文档性质:技术博客模板 | 实训报告辅助 | 工程实操复盘表
一、LVGL 环境配置与问题解决表
配置步骤 具体操作内容 预期结果 实测结果 问题现象 解决方法 经验总结
1. 组件版本配置 在 main/idf_component.yml 中添加依赖:
lvgl/lvgl: ^9.4.0
espressif/esp_lvgl_port: ^2.6.3
espressif/esp_lcd_touch_ft5x06: ^1.0.6 保存后 ESP-IDF 自动拉取对应版本组件
2.SDK 配置开启 LVGL 执行 idf.py menuconfig → Component config → LVGL,开启 Enable LVGL LVGL 核心功能开启,支持调用相关 API
3. 加载 LVGL 内置 Demo 在 menuconfig-LVGL 中勾选 LVGL Demos,选择需要的测试 Demo 工程自动关联 Demo 源码,可直接调用
4. 路径问题处理 检查工程保存路径,确认无中文 / 特殊字符 / 空格 工程路径可被 ESP-IDF 正常识别,组件编译无路径报错 工程保存至 QQ 中文路径,组件安装失败、编译报错 1. 将工程迁移至纯英文 / 数字无空格路径;
2. 执行 idf.py reconfigure 重新加载配置;
3. 执行 idf.py build 验证 ESP-IDF 对中文 / 特殊字符路径兼容性差,所有工程需放在纯英文路径
二、代码修改记录表(LCD.c + LCD.h)
2.1 LCD.c 文件修改
表格
修改位置 新增 / 修改代码内容 代码功能说明 调用 / 生效方式
全局变量区域 // 引入 LVGL 相关头文件
#include "lvgl.h"
#include "esp_lvgl_port.h"
#include "esp_lcd_touch_ft5x06.h"
// LVGL 核心句柄定义
static esp_lcd_touch_handle_t tp;
static lv_disp_t *disp;
static lv_indev_t *disp_indev = NULL; 引入 LVGL 和触摸屏驱动头文件,定义液晶屏、触摸屏句柄 全局生效,仅在 LCD.c 内部调用
自定义函数区域 void lvgl_lcd_init(void){
lv_init();
esp_lvgl_port_init();
disp = esp_lvgl_port_add_disp(NULL);
disp_indev = esp_lvgl_port_add_indev(tp, disp);
lv_indev_set_type(disp_indev, LV_INDEV_TYPE_POINTER);
} LVGL 内核、ESP32 适配层初始化,绑定液晶屏与触摸屏 供 app_main.c 调用,工程启动时初始化
事件回调区域 static void btn_click_event(lv_event_t *e){
lv_obj_t *label = lv_event_get_user_data(e);
lv_label_set_text(label, "Touched!");
lv_obj_center(label);
} 触摸屏点击事件回调,实现按钮点击文本切换 绑定到触摸按钮,点击时触发
原有代码区域 保留原有 LCD 驱动、绘图、汉字显示等代码 延续基础 LCD 硬件驱动和功能 与 LVGL 代码无冲突,硬件复用
2.2 LCD.h 文件修改
表格
修改位置 新增 / 修改代码内容 代码功能说明 注意事项
头文件引入区域 // 新增 LVGL 核心头文件
#include "lvgl.h"
#include "esp_lvgl_port.h" 声明 LVGL 相关头文件,供外部调用 保留原有 LCD 驱动头文件,避免冲突
函数声明区域 // 新增 LVGL 初始化函数声明
void lvgl_lcd_init(void); 声明 LVGL 初始化函数,开放给 app_main.c 调用 保证头文件 #ifndef/define/endif 保护,避免重复包含
原有函数区域 保留 void bsp_lcd_init (void);
保留 void lcd_draw_pictrue (uint16_t x, uint16_t y, const unsigned char *pic); 延续原有 LCD 基础驱动功能 与 LVGL 功能复用硬件,无需修改原有代码
三、主函数(app_main.c)功能调用表
表格
调用顺序 函数名称 函数功能 调用目的 实测运行状态 备注
1 bsp_i2c_init(); 初始化 I2C 通信接口 为 LCD、触摸屏提供通信基础 原有基础代码,直接复用
2 pca9557_init(); 初始化外设 IO 扩展 驱动 LCD 相关外设 原有基础代码,直接复用
3 bsp_lcd_init(); 初始化 LCD 硬件驱动 完成液晶屏底层硬件配置 原有基础代码,直接复用
4 lvgl_lcd_init(); 初始化 LVGL 与硬件适配 绑定 LVGL 到 LCD 和触摸屏 本次新增核心函数
5 lv_demo_widgets(); 启动 LVGL 官方控件 Demo 测试 LCD 显示和触摸屏交互 可替换为 lv_demo_music/lv_demo_benchmark
6 lv_timer_handler(); LVGL 定时器核心处理 处理触摸事件和界面刷新 必须在主循环中持续调用
7 vTaskDelay(pdMS_TO_TICKS(5)); 短暂延时 降低 CPU 占用,避免阻塞 替换原有 delay (),适配 FreeRTOS
四、LVGL 功能测试表
表格
测试项目 测试操作 预期效果 实测结果 异常排查步骤 测试结论(正常 / 异常)
LVGL 基础显示 烧录程序后启动开发板,等待界面加载 LCD 屏幕正常显示 LVGL 官方 Demo 界面(按钮、滑块、文本等控件) 1. 检查 LCD 硬件接线;
2. 验证 bsp_lcd_init () 是否执行;
3. 确认 lvgl_lcd_init () 中 disp 句柄绑定成功
触摸屏基础触摸 用手指点击 Demo 中的按钮、拖动滑块控件 点击按钮触发对应事件,拖动滑块实现参数调节,界面实时响应 1. 检查触摸屏接线;
2. 验证 FT5x06 驱动初始化;
3. 确认 disp_indev 句柄与 disp 绑定;
4. 调用坐标校准函数 esp_lcd_touch_calibrate ()
自定义触摸控件 点击自定义创建的 “Touch Me!” 按钮 按钮文本切换为 “Touched!”,文本保持居中显示 1. 检查按钮创建与坐标设置;
2. 验证事件回调函数是否绑定;
3. 确认 lv_timer_handler () 持续调用
多任务调度兼容性 同时运行 LVGL 界面和原有 LCD 动图 / 时钟功能 LVGL 界面无卡顿,触摸响应灵敏,原有 LCD 功能正常运行 1. 提高 LVGL 任务优先级;
2. 优化延时逻辑,使用 vTaskDelay ();
3. 降低 LCD 刷新帧率
LVGL 函数调用测试 从 LVGL 百问网调用字符、颜色设置函数,写入 LCD 屏幕正常显示自定义字符 / 颜色,参数修改实时生效 1. 确认函数头文件正确引入;
2. 检查函数参数与屏幕分辨率匹配;
3. 验证 LVGL 内核初始化完成
五、实训收获与问题复盘表
5.1 技术收获
表格
收获类别 具体内容
LVGL 基础操作 1. 掌握 LVGL 9.4.0 组件的配置与安装方法;
2. 理解 idf_component.yml 文件的组件依赖配置规则;
3. 学会通过 menuconfig 开启 LVGL 功能并加载官方 Demo
代码开发能力 1. 掌握在原有 LCD 驱动代码中添加 LVGL 适配代码的方法,实现代码兼容;
2. 理解 LVGL 核心句柄(disp/indev/tp)的作用与硬件绑定逻辑;
3. 学会编写 LVGL 自定义触摸控件和事件回调函数,实现基础交互
硬件软件适配 1. 掌握 ESP32 与 LVGL、FT5x06 触摸屏的多层适配逻辑;
2. 复用原有 LCD 硬件引脚和通信接口,实现基础功能与 LVGL 功能的硬件兼容;
3. 理解 FreeRTOS 与 LVGL 的任务调度适配要点
问题解决能力 1. 解决中文路径导致的 ESP-IDF 组件安装失败问题,掌握环境配置排错思路;
2. 掌握 LVGL 无显示、触摸屏无响应的基础排查流程(硬件→初始化→句柄绑定→逻辑);
3. 学会 LVGL 界面卡顿的优化方法,适配嵌入式系统资源限制
5.2 典型问题复盘
表格
问题编号 问题现象 涉及模块 根因分析 解决方法 复盘总结
1 工程保存至 QQ 中文路径,LVGL 组件拉取失败、编译报路径错误 开发环境 ESP-IDF 对中文 / 特殊字符 / 空格路径兼容性差,无法识别路径中的中文编码 1. 将工程迁移至纯英文 / 数字无空格路径;
2. 执行 idf.py reconfigure 重新加载工程配置;
3. 执行 idf.py build 重新编译验证 开发工程需提前规划路径,统一使用纯英文命名,规避环境配置底层问题
2 LVGL Demo 正常显示,触摸屏点击无任何响应 触摸屏驱动 + LVGL 适配 触摸屏句柄 disp_indev 未与液晶屏句柄 disp 绑定,输入事件无法传递到显示层 1. 在 lvgl_lcd_init () 中确认 disp_indev = esp_lvgl_port_add_indev (tp, disp);
2. 添加 lv_indev_set_type (disp_indev, LV_INDEV_TYPE_POINTER) 设置触摸类型;
3. 检查触摸屏驱动初始化是否在 LVGL 初始化前执行 硬件句柄需严格一一绑定,输入设备必须关联到对应显示设备,初始化有先后顺序
3 LVGL 界面刷新卡顿,触摸响应存在明显延迟 任务调度 + LVGL 配置 主循环延时过长,LVGL 定时器处理不及时,CPU 被过度占用,界面刷新帧率低 1. 将主循环延时从 pdMS_TO_TICKS (100) 改为 pdMS_TO_TICKS (5);
2. 在 menuconfig 中关闭 LVGL 不必要的动画、反走样效果;
3. 提高 LVGL 任务优先级,避免被其他任务阻塞 LVGL 开发需使用非阻塞式延时,适配 FreeRTOS 任务调度,根据硬件资源精简 LVGL 配置
4 自定义按钮创建后,LCD 屏幕无任何显示,无报错信息 LVGL 控件开发 按钮创建未关联到屏幕根对象,或按钮坐标 / 大小超出 LCD 屏幕分辨率 1. 确认按钮创建代码为 lv_btn_create (lv_scr_act ()),绑定到根对象;
2. 根据 LCD 实际分辨率设置合理的按钮坐标(x/y)和大小(宽 / 高);
3. 添加屏幕背景色设置,确认屏幕初始化正常 控件创建需先绑定显示根对象,所有坐标 / 尺寸参数必须匹配硬件屏幕实际参数
5 调用 LVGL 百问网函数时,编译报 “函数未定义” 错误 头文件与代码引用 未引入函数对应的头文件,或函数名 / 参数与 LVGL 版本不匹配 1. 从 LVGL 9.4.0 官方文档 / 百问网确认函数对应的头文件并引入;
2. 检查函数名、参数类型是否与 LVGL 9.x 版本兼容(避免使用 8.x 废弃函数);
3. 确认 LVGL 组件已正常拉取,头文件路径无误 不同 LVGL 版本函数存在兼容性差异,调用前需匹配版本,确保头文件完整引入
5.3 教学建议
表格
建议类别 具体建议内容
课程内容设计 1. 增加 LVGL 9.x 版本的专属案例教学,重点讲解组件配置、硬件适配和句柄绑定;
2. 补充 FT5x06 等主流触摸屏的驱动、校准实操内容,结合硬件讲解;
3. 结合 FreeRTOS 讲解 LVGL 任务调度,重点讲解非阻塞式延时和任务优先级设置;
4. 增加 LVGL 百问网常用函数的实操讲解,指导学生快速查询和调用
实操指导优化 1. 实训前提前强调 ESP-IDF 工程的纯英文路径要求,规避环境配置基础坑;
2. 提供 LVGL 与原有 LCD 代码的整合模板,标注新增代码和修改位置,降低开发难度;
3. 制作 LVGL 常见问题排查流程图(硬件→初始化→句柄→逻辑),方便学生自主排错;
4. 提供 LVGL 9.4.0 官方 Demo 和自定义控件的完整代码,供学生参考调试
硬件支持配套 1. 提供配套的 LVGL 兼容触摸屏,统一 FT5x06 硬件型号,减少驱动适配问题;
2. 标注 LCD 与触摸屏的接线对应关系,制作硬件接线图,减少接线错误;
3. 提供屏幕分辨率、引脚定义等硬件参数表,方便学生匹配代码参数
实训安排调整 1. 将 LVGL 学习分为 “配置安装→基础显示→触摸交互→综合应用” 四个阶段,循序渐进;
2. 增加小组实操答疑环节,针对环境配置、硬件接线等共性问题集中讲解;
3. 设置综合实训任务,要求基于 LVGL 实现 “触摸控制 + 显示 + 原有 LCD 功能” 的整合应用
六.部分代码:
static void event_handler(lv_event_t * e)
{
}
void lv_example_demo(void)
{
lv_obj_t * label;
lv_obj_t * btn1 = lv_button_create(lv_screen_active());
lv_obj_add_event_cb(btn1, event_handler, LV_EVENT_ALL, NULL);
// lv_obj_align(btn1, LV_ALIGN_CENTER, 0, -40);
lv_obj_remove_flag(btn1, LV_OBJ_FLAG_PRESS_LOCK);
lv_obj_set_width(btn1, 240);
lv_obj_set_height(btn1, 24);
lv_obj_set_x(btn1, 0);
lv_obj_set_y(btn1, 0);
label = lv_label_create(btn1);
lv_label_set_text(label, "login");
lv_obj_center(label);
lv_obj_t * btn2 = lv_button_create(lv_screen_active());
lv_obj_add_event_cb(btn2, event_handler, LV_EVENT_ALL, NULL);
lv_obj_align(btn2, LV_ALIGN_CENTER, 0, 40);
lv_obj_add_flag(btn2, LV_OBJ_FLAG_CHECKABLE);
lv_obj_set_height(btn2, LV_SIZE_CONTENT);
label = lv_label_create(btn2);
lv_label_set_text(label, "Toggle");
lv_obj_center(label);
lv_obj_set_flex_flow(lv_screen_active(), LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(lv_screen_active(), LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER);
lv_obj_t * cb;
cb = lv_checkbox_create(lv_screen_active());
lv_checkbox_set_text(cb, "Apple");
lv_obj_add_event_cb(cb, event_handler, LV_EVENT_ALL, NULL);
cb = lv_checkbox_create(lv_screen_active());
lv_checkbox_set_text(cb, "Banana");
lv_obj_add_state(cb, LV_STATE_CHECKED);
lv_obj_add_event_cb(cb, event_handler, LV_EVENT_ALL, NULL);
lv_obj_update_layout(cb);
// 创建文本输入区域
lv_obj_t *textarea = lv_textarea_create(lv_scr_act());
lv_textarea_set_placeholder_text(textarea, "please input...");
lv_textarea_set_one_line(textarea, true); // 单行模式
lv_obj_set_size(textarea, 300, 40);
}
void app_main(void)
{
// 初始化硬件
bsp_i2c_init();
pca9557_init();
bsp_lcd_init();
bsp_lvgl_start();
lv_example_demo();
while (1){
vTaskDelay(10); // 延时1秒
}
}
更多推荐



所有评论(0)