当前位置: 首页 > news >正文

ESP32-S3开发板LVGL图形界面开发实战教程

ESP32-S3开发板LVGL图形界面开发实战教程

前言

大家好!今天我们来深入探讨如何在ESP32-S3开发板上实现LVGL图形界面开发。随着物联网设备对用户友好界面需求的增加,掌握LVGL这样的轻量级图形库变得尤为重要。本文将带你从零开始,一步步实现一个可用的LVGL应用程序。

一、LVGL简介

LVGL(Light and Versatile Graphics Library)是一个开源的图形库,专为嵌入式系统设计,具有以下特点:

  • 资源占用少,适合微控制器使用
  • 支持多种显示控制器和输入设备
  • 丰富的UI控件和动画效果
  • 支持多语言、多主题
  • 完全免费且开源

二、开发环境准备

2.1 硬件准备

  • ESP32-S3开发板(带LCD显示屏和触摸屏)
  • USB数据线
  • 电脑一台

2.2 软件准备

  • ESP-IDF开发环境
  • VSCode编辑器
  • ESP-IDF VS Code插件

三、项目搭建

3.1 创建项目

我们以ESP-IDF中的示例项目为基础,修改为支持LVGL的项目。具体步骤如下:

  1. 复制一个基础项目(例如LCD显示项目)
  2. 重命名项目文件夹
  3. 使用VS Code打开项目

3.2 项目结构分析

项目目录
├── CMakeLists.txt          // 项目构建文件
├── main                    // 主程序目录
│   ├── CMakeLists.txt      // 主程序构建文件
│   ├── main.c              // 主函数入口
│   ├── esp32_s3_szp.c      // 开发板驱动程序
│   └── esp32_s3_szp.h      // 开发板驱动头文件
├── components              // 组件目录
└── managed_components      // 管理的组件目录

四、液晶屏与LVGL接口实现

4.1 液晶屏初始化函数

首先,我们需要实现液晶屏初始化并添加到LVGL的函数:

static lv_disp_t *bsp_display_lcd_init(void)
{/* 初始化液晶屏 */bsp_display_new();                      // 液晶屏驱动初始化app_lcd_set_color(0xffff);              // 设置整屏背景白色esp_lcd_panel_disp_on_off(panel_handle, true); // 打开液晶屏显示/* 添加LCD到LVGL */ESP_LOGD(TAG, "Add LCD screen");const lvgl_port_display_cfg_t disp_cfg = {.io_handle = io_handle,.panel_handle = panel_handle,.buffer_size = BSP_LCD_H_RES * BSP_LCD_DRAW_BUF_HEIGHT, // 缓冲区大小.double_buffer = true,              // 启用双缓冲提高显示速度.hres = BSP_LCD_H_RES,              // 水平分辨率.vres = BSP_LCD_V_RES,              // 垂直分辨率.monochrome = false,                // 是否为单色屏/* 旋转设置,必须与esp_lcd初始化时一致 */.rotation = {.swap_xy = true,                // 交换XY坐标.mirror_x = true,               // X轴镜像.mirror_y = false,              // Y轴不镜像},.flags = {.buff_dma = false,              // 不使用DMA传输.buff_spiram = true,            // 使用外部SPIRAM存储缓冲区}};return lvgl_port_add_disp(&disp_cfg);   // 添加显示设备到LVGL并返回句柄
}

注意:缓冲区大小设置为BSP_LCD_H_RES * BSP_LCD_DRAW_BUF_HEIGHT,其中BSP_LCD_DRAW_BUF_HEIGHT是一次绘制的高度。受内存限制,如果使用内部内存,这个值不能太大,建议设为20(屏幕高度的约1/10)。如果使用外部PSRAM,可以设置为整个屏幕高度。

4.2 触摸屏初始化函数

接下来实现触摸屏初始化函数:

esp_err_t bsp_touch_new(esp_lcd_touch_handle_t *ret_touch)
{/* 初始化触摸屏配置 */const esp_lcd_touch_config_t tp_cfg = {.x_max = BSP_LCD_V_RES,             // 触摸屏X最大值.y_max = BSP_LCD_H_RES,             // 触摸屏Y最大值.rst_gpio_num = GPIO_NUM_NC,        // 复位引脚未连接.int_gpio_num = GPIO_NUM_NC,        // 中断引脚未连接.levels = {.reset = 0,.interrupt = 0,},.flags = {.swap_xy = 0,                   // 是否交换XY.mirror_x = 1,                  // 是否X轴镜像.mirror_y = 0,                  // 是否Y轴镜像},};// 配置I2C通讯esp_lcd_panel_io_handle_t tp_io_handle = NULL;const esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_FT5x06_CONFIG();// 创建I2C通讯接口并初始化触摸控制器ESP_RETURN_ON_ERROR(esp_lcd_new_panel_io_i2c((esp_lcd_i2c_bus_handle_t)BSP_I2C_NUM, &tp_io_config, &tp_io_handle), TAG, "");return esp_lcd_touch_new_i2c_ft5x06(tp_io_handle, &tp_cfg, ret_touch);
}

4.3 触摸输入设备添加到LVGL

将触摸屏设备添加为LVGL的输入设备:

static lv_indev_t *bsp_display_indev_init(lv_disp_t *disp)
{ESP_ERROR_CHECK(bsp_touch_new(&tp));    // 初始化触摸屏assert(tp);                             // 确保触摸屏初始化成功/* 添加触摸输入设备到LVGL */const lvgl_port_touch_cfg_t touch_cfg = {.disp = disp,                       // 关联的显示设备.handle = tp,                       // 触摸屏句柄};return lvgl_port_add_touch(&touch_cfg); // 添加触摸设备到LVGL并返回句柄
}

4.4 LVGL初始化与启动函数

综合上面的函数,创建一个统一的LVGL启动函数:

// 开发板显示初始化
void bsp_lvgl_start(void)
{/* 初始化LVGL */lvgl_port_cfg_t lvgl_cfg = ESP_LVGL_PORT_INIT_CONFIG();lvgl_port_init(&lvgl_cfg);/* 初始化液晶屏并添加LVGL接口 */disp = bsp_display_lcd_init();/* 初始化触摸屏并添加LVGL接口 */disp_indev = bsp_display_indev_init(disp);/* 打开液晶屏背光 */bsp_display_backlight_on();
}

4.5 全局变量定义

需要定义以下全局变量:

static esp_lcd_touch_handle_t tp;           // 触摸屏句柄
static lv_disp_t *disp;                     // 指向液晶屏
static lv_indev_t *disp_indev = NULL;       // 指向触摸屏

五、组件配置与添加

5.1 添加必要组件

idf_component.yml文件中添加LVGL相关组件:

## IDF Component Manager Manifest File
dependencies:# espressif/esp32-camera: "^2.0.10"      # 注释掉不需要的摄像头组件lvgl/lvgl: '~8.3.0'                      # LVGL核心库espressif/esp_lvgl_port: '~1.4.0'        # LVGL接口espressif/esp_lcd_touch_ft5x06: '~1.0.6' # 触摸屏驱动

版本号前的~^符号有不同含义:

  • ~8.3.0表示下载8.3.*系列的最高版本(例如8.3.11)
  • ^8.3.0表示下载8.*.*系列的最高版本(例如8.9.7)
  • 如果不加符号直接写版本号,则下载指定版本

5.2 摄像头模块条件编译

为了处理不需要摄像头功能的情况,在头文件中添加条件编译:

#define CAMERA_EN    0  // 设为1开启摄像头功能,设为0关闭#if CAMERA_EN
#include "esp_camera.h"
// 摄像头相关代码...
#endif

六、主程序实现

6.1 主函数编写

#include "demos/lv_demos.h"  // 包含LVGL示例头文件void app_main(void)
{bsp_i2c_init();          // I2C初始化pca9557_init();          // IO扩展芯片初始化bsp_lvgl_start();        // 初始化LVGL显示/* 下面5个demos只打开1个运行 */lv_demo_benchmark();     // 性能测试演示// lv_demo_keypad_encoder();  // 键盘编码器演示// lv_demo_music();           // 音乐播放器演示// lv_demo_stress();          // 压力测试演示// lv_demo_widgets();         // 控件演示
}

七、LVGL配置

7.1 menuconfig配置

编译前需要通过menuconfig进行LVGL配置:

  1. 先选择目标芯片(ESP32-S3)
  2. 打开menuconfig配置界面
  3. 进行LVGL相关配置:
7.1.1 颜色配置

在LVGL配置中启用色彩交换(Color Swap):

7.1.2 字体配置

启用12像素和16像素大小字体:

7.1.3 Demo配置

启用需要的Demo演示程序:

注意:只需勾选主选项,子选项不需要勾选。

7.2 配置保存

配置完成后,使用以下命令保存配置:

idf.py save-defconfig

这将生成sdkconfig.defaults文件,保存了在menuconfig中的配置(不包括默认配置)。

八、编译与下载

8.1 编译项目

执行编译命令:

idf.py build

8.2 下载到开发板

选择正确的串口后下载:

idf.py -p COM口号 flash

九、运行效果分析

成功运行后,开发板会显示LVGL的演示程序。其中:

  • Benchmark演示:显示LVGL各种组件的性能测试
  • Widgets演示:展示LVGL所有控件
  • Stress演示:进行压力测试
  • Music演示:显示音乐播放器界面(注意:在320×240分辨率下显示效果不佳)
  • Keypad演示:展示键盘和编码器交互

十、常见问题与解决方法

10.1 编译错误

问题:缺少组件导致的编译错误。
解决:检查idf_component.yml文件,确保所有依赖组件正确添加。

10.2 显示异常

问题:屏幕方向或触摸坐标不正确。
解决:检查rotation配置中的swap_xymirror_xmirror_y设置是否正确。

10.3 内存不足

问题:运行LVGL时内存不足。
解决:减小buffer_size或启用外部SPIRAM存储缓冲区。

十一、总结

通过本教程,我们学习了如何在ESP32-S3开发板上集成LVGL图形库,并运行多个演示程序。从液晶屏初始化、触摸屏配置到LVGL接口实现,每一步都进行了详细讲解。这为开发自己的图形界面应用打下了坚实基础。

希望本文对你有所帮助!如有任何问题,欢迎在评论区留言交流。


参考资料

  1. LVGL官方文档
  2. ESP-IDF编程指南
  3. ESP-BSP开发文档
http://www.lryc.cn/news/578903.html

相关文章:

  • React 学习(2)
  • 【python】pdf拆成图片,加中文,再合成pdf
  • Spark流水线数据探查组件
  • 跨平台开发的抉择:Flutter vs 原生安卓(Kotlin)的优劣对比与选型建议​​
  • vscode vim插件示例json意义
  • STM32模拟I2C获取AP3216C光学接近传感器数据
  • Linux-修改线上MariaDB服务端口号
  • 【网工|知识升华版|实验】1 登录华为设备并配置
  • IDEA2025 Version Control 窗口 local changes显示
  • Adobe高阶技巧与设计师创意思维的进阶指南
  • 免Mac上架实战:全平台iOS App上架流程的工具协作经验
  • 开源计算机视觉的基石:OpenCV 全方位解析
  • 同一水平的 RISC-V 架构的 MCU,和 ARM 架构的 MCU 相比,运行速度如何?
  • containerd 项目主要目录简要说明
  • 多模态进化论:GPT-5V图文推理能力在工业质检中的颠覆性应用
  • AI智能体时代来临:数据分析的变革与自动化之路
  • Linux缓存调优指南:提升服务器性能的关键策略
  • Android Native 之 init初始化selinux机制
  • 【.NET Framework 窗体应用程序项目结构介绍】
  • day046-tomcat与部署war包、jar包
  • java实现日志记录-注解方式
  • 使用哪种语言的人更容易通过面试?
  • 【Web前端】优化轮播图展示(源代码)
  • (一)大语言模型的关键技术<-AI大模型构建
  • 360安全卫士占用5037端口(ADB端口)解决方案
  • Wps开放平台v5升级v7上传实体文件踩坑(Java使用restTemplate)
  • 基于开源链动2+1模式AI智能名片S2B2C商城小程序的场景零售创新研究
  • Mac电脑 卸载工具 App Cleaner
  • Java 大视界 -- Java 大数据在智能医疗健康管理中的慢性病风险预测与个性化干预(330)
  • 带GPU启动 Docker 容器