当前位置: 首页 > 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.dtcms.com/a/264620.html

相关文章:

  • 【实战指南】Ubuntu源码部署LNMP生产环境|企业级性能调优方案
  • STEP-BACK PROMPTING:退一步:通过抽象在大型语言模型中唤起推理能力
  • Ubuntu-18.04-bionic 的apt的/etc/apt/sources.list 更换国内镜像软件源 笔记250702
  • 【Note】《深入理解Linux内核》 Chapter 5 :内存地址的表示——Linux虚拟内存体系结构详解
  • Minio安装配置,桶权限设置,nginx代理 https minio
  • (nice!!!) (LeetCode 每日一题) 3333. 找到初始输入字符串 II (贪心+动态规划dp+前缀和)
  • 如何解决wordpress批量删除媒体库中的图片很慢甚至卡死问题
  • 音视频会议服务搭建(设计方案-两种集成方案对比)-03
  • U+平台配置免密登录、安装Hadoop配置集群、Spark配置
  • OpenLayers 入门指南【一】:WebGIS基础与OpenLayers概述
  • Chart.js 安装使用教程
  • AI自动化神器-DroidRun使用体验
  • OpenCASCADE学习|点云可视化深度优化指南
  • 【数字后端】- tcbn28hpcplusbwp30p140,标准单元库命名含义
  • 记一次事务中更新与查询数据不一致的问题分析
  • HTTP 协议深入理解
  • Git 分支与远程仓库基础教学总结
  • sudo本地提权漏洞(CVE-2025-32462)
  • S7-1200 PN与G120变频器控制起停及调速PROFINET实现详解
  • 微信小程序能不能获取物联网的上的设备数据
  • 在 proteus8或者proteus 9 中查看 micropython 的 print 输出
  • Redis搭建集群模式
  • 【WEB】Polar靶场 笔记
  • C++主流编辑器特点比较
  • 【HDMI CEC Menu Tunneling (菜单穿越) 功能详解
  • Stereolabs ZED系列与ZED X立体相机系列对比:如何根据项目需求选择?
  • AI大模型如何重塑软件开发流程?从自动化革命到人机共生范式
  • 小架构step系列01:小架构初衷
  • SQLMesh中的SQL模型:从基础定义到高级应用
  • 【网工|知识升华版|实验】1 登录华为设备并配置