基于 ESP32S3 的 LVGL 9.4 图形库移植与 UI 开发实践分享(课程作业)
摘要:本文介绍了在ESP32S3开发板上部署LVGL 9.4图形库的关键步骤,包括组件安装、配置初始化及布局方式。详细说明了通过ESP-IDF环境安装LVGL核心库和适配组件的方法,并演示了绝对定位和弹性布局两种UI开发方式。重点记录了登录界面开发中遇到的问题:当文本框单独置于顶部时会出现白屏现象,需添加文本标签才能正常显示。文章提供了完整的核心代码实现,包括硬件初始化、LVGL刷新任务和UI事件
一、LVGL 图形库简介
LVGL(Light and Versatile Graphics Library)是一款开源嵌入式图形库,可用于构建美观、响应迅速的图形用户界面(GUI),广泛适配智能手表、智能家居设备、工业控制终端等嵌入式场景,具备轻量级、跨平台、易扩展的特性。
二、ESP32S3 开发板部署 LVGL 9.4 关键步骤
1. 组件安装
基于 ESP-IDF 开发环境,通过终端指令完成 LVGL 核心库及适配组件的安装:
bash
运行
idf.py add-dependency "lvgl/lvgl^9.4.0"
idf.py add-dependency "espressif/esp_lvgl_port^2.6.3"
安装完成后,在自动生成的idf_component.yml文件中补充触摸屏驱动依赖:
yaml
dependencies:
espressif/esp_lcd_touch_ft5x06: ^1.0.6
2. 配置与初始化
- 在
LCD.h头文件中添加 LVGL 相关头文件引入及初始化函数声明,确保硬件层与图形库的适配; - 打开 SDK 配置编辑器,搜索并勾选
Benchmark your system选项以启用系统基准测试功能; - 按需添加字体配置,本次开发选择 16 号、24 号、26 号字体以满足界面显示需求;
- 在主函数中引入 LVGL 示例头文件:
#include "demos/lv_demos.h",为界面开发提供基础接口。
3. 布局方式说明
LVGL 支持两种核心布局方式,适配不同 UI 开发场景:
(1)绝对定位
通过lv_obj_set_x()/lv_obj_set_y()函数精准控制组件坐标,示例:
c
运行
lv_obj_set_x(btn_obj, 0); // 设置组件x轴坐标为0
(2)弹性布局(Flex Layout)
- 排列方向配置:
lv_obj_set_flex_flow(lv_obj_t * obj, lv_flex_flow_t flow),用于定义组件排列方向及换行规则,如垂直列布局(从上到下排列):c
运行
lv_obj_set_flex_flow(root, LV_FLEX_FLOW_COLUMN); - 对齐方式配置:
lv_obj_set_flex_align(lv_obj_t * obj, lv_flex_align_t main_align, lv_flex_align_t cross_align, lv_flex_align_t track_align),用于控制组件对齐及间距,示例:c
运行
lv_obj_set_flex_align(root, LV_FLEX_ALIGN_CENTER, // 子元素水平居中 LV_FLEX_ALIGN_SPACE_EVENLY, // 子元素垂直间距均匀 LV_FLEX_ALIGN_CENTER); // 交叉轴居中
三、核心代码实现(主函数及 UI 逻辑)
c
运行
#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "LCD/LCD.h"
#include "demos/lv_demos.h"
// LVGL刷新任务(必须)
static void lvgl_refresh_task(void *arg)
{
while(1) {
lv_timer_handler(); // 处理LVGL定时器/渲染任务
vTaskDelay(pdMS_TO_TICKS(5)); // 5ms刷新一次,适配320x240屏幕
}
}
// 事件回调函数(处理按钮/复选框交互)
static void event_handler(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
if(code == LV_EVENT_CLICKED) {
ESP_LOGI("UI_EVENT", "Clicked event triggered");
}
else if(code == LV_EVENT_VALUE_CHANGED) {
ESP_LOGI("UI_EVENT", "Toggled event triggered");
}
}
// 登录界面创建函数
void lv_example_login(void)
{
lv_obj_t * root = lv_scr_act(); // 获取屏幕根对象
// 配置弹性布局:垂直列排列+居中对齐+均匀间距
lv_obj_set_flex_flow(root, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(root,
LV_FLEX_ALIGN_CENTER,
LV_FLEX_ALIGN_SPACE_EVENLY,
LV_FLEX_ALIGN_CENTER);
lv_obj_set_style_pad_all(root, 20, LV_PART_MAIN); // 根对象内边距
// 文本标签(解决文本框单独置顶白屏问题)
lv_obj_t *label_title = lv_label_create(root);
lv_label_set_text(label_title, "Login"); // 标题文本(英文)
lv_obj_set_style_text_font(label_title, &lv_font_montserrat_24, LV_PART_MAIN);
// 账号输入文本框
lv_obj_t *textarea_account = lv_textarea_create(root);
lv_textarea_set_placeholder_text(textarea_account, "please input account");
lv_textarea_set_one_line(textarea_account, true); // 单行模式
lv_obj_set_size(textarea_account, 280, 40); // 适配320x240屏幕
// 密码输入文本框
lv_obj_t *textarea_pwd = lv_textarea_create(root);
lv_textarea_set_placeholder_text(textarea_pwd, "please input password");
lv_textarea_set_one_line(textarea_pwd, true);
lv_textarea_set_password_mode(textarea_pwd, true); // 密码隐藏模式
lv_obj_set_size(textarea_pwd, 280, 40);
// 同意条款复选框
lv_obj_t * cb_agree = lv_checkbox_create(root);
lv_checkbox_set_text(cb_agree, "I agree to the terms of service");
lv_obj_add_event_cb(cb_agree, event_handler, LV_EVENT_ALL, NULL);
lv_obj_set_width(cb_agree, 280);
// 登录按钮
lv_obj_t * btn_login = lv_button_create(root);
lv_obj_add_event_cb(btn_login, event_handler, LV_EVENT_ALL, NULL);
lv_obj_remove_flag(btn_login, LV_OBJ_FLAG_PRESS_LOCK);
lv_obj_set_size(btn_login, 240, 30);
// 按钮文本
lv_obj_t *label_btn = lv_label_create(btn_login);
lv_label_set_text(label_btn, "login");
lv_obj_center(label_btn);
}
// 主函数入口
void app_main(void)
{
// 硬件初始化
bsp_i2c_init(); // I2C总线初始化
pca9557_init(); // IO扩展芯片初始化
bsp_lcd_init(); // LCD屏幕初始化(关键,避免白屏)
// 启动LVGL
bsp_lvgl_start();
// 创建LVGL刷新任务(优先级5,避免界面卡顿)
xTaskCreate(lvgl_refresh_task, "lvgl_refresh", 4096, NULL, 5, NULL);
// 创建登录界面
lv_example_login();
// 主循环
while (1) {
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
四、登录界面开发问题与现象记录
基于上述配置开发登录界面时,选用文本框、复选框、按钮三类核心组件,计划按 “文本框→复选框→按钮” 的顺序垂直排列。开发过程中发现关键问题:单独将文本框置于界面最上方时,程序烧录至 ESP32S3 开发板后屏幕呈现白屏状态,无任何 UI 元素显示;仅在文本框上方额外添加一个文本标签(如 “Login”)后,整个界面才能正常渲染,各组件按预期顺序显示。
五、参考资源
LVGL 相关组件及开发文档可参考百问网开源资源:http://lvgl.100ask.net/9.2/
总结
本次实践完成了 LVGL 9.4 在 ESP32S3 开发板的移植与基础 UI 开发,验证了弹性布局在嵌入式界面开发中的实用性,但仍存在文本框单独置顶导致白屏的异常现象,后续将进一步排查硬件初始化顺序、LVGL 组件渲染机制等方面的原因,以解决该兼容性问题。
更多推荐



所有评论(0)