跳到主要内容

docs 第 08 节 移植 LVGL

本节使用示例包中的 LVGL v8 示例,通过 ESP32_Display_Panel 库驱动屏幕和触摸面板,并显示 LVGL 官方示例。

硬件连接​

为了将对应的代码上传到 ESP32-S3,需要用 Type-C 转 Type-A 的线将 ESP32-S3-Touch-LCD-7 的 USB 口接到电脑的 USB 口:

ESP32-S3-Touch-LCD-7 USB 连接示意

示例代码​

请先从以下地址获取示例程序:ESP32-S3-Touch-LCD-7 示例程序 (如果先前已经下载,直接打开对应文件夹即可)

下载或克隆仓库后,打开对应的 examples\Arduino\examples\09_lvgl_v8_demo 文件夹。

双击打开 09_lvgl_v8_demo.ino。

在 Arduino IDE 中选择串口和开发板型号 Waveshare ESP32-S3-Touch-LCD-7。

设置对应的开发板参数:

ESP32-S3-Touch-LCD-7 Arduino IDE 开发板参数配置

然后点击上传按钮,等待程序上传完成。

运行结果​

重新给屏幕上电,可以看到屏幕开始显示 LVGL v8 示例。带有触摸面板的版本还可以通过滑动屏幕测试触摸功能。

ESP32-S3-Touch-LCD-7 LVGL v8 示例运行结果

代码回顾​

1. 显示和触摸面板的驱动​

本例程使用示例目录中的 esp_panel_board_custom_conf.h 配置屏幕、触摸面板、背光和 I/O 扩展芯片。关于该文件的配置方法,请参考 ESP32_Display_Panel 官方文档。

下面介绍本例程使用的主要配置。

开启自定义 LCD 面板

#define ESP_PANEL_BOARD_DEFAULT_USE_CUSTOM (1)

首先要将 ESP_PANEL_BOARD_DEFAULT_USE_CUSTOM 宏定义由 0 改为 1,表示打开自定义配置,将会启用 #if ESP_PANEL_BOARD_DEFAULT_USE_CUSTOM 下的配置参数。

#define ESP_PANEL_BOARD_NAME "Waveshare:ESP32-S3-Touch-LCD-7"
#define ESP_PANEL_BOARD_WIDTH (800) // Panel width (horizontal, in pixels)
#define ESP_PANEL_BOARD_HEIGHT (480) // Panel height (vertical, in pixels)

自定义板子的名字和定义屏幕的分辨率。

设置 LCD 的各项参数

#define ESP_PANEL_BOARD_USE_LCD (1)

将 ESP_PANEL_BOARD_USE_LCD 的宏定义从 0 修改成 1,表示打开 LCD panel,将会启用 #if ESP_PANEL_BOARD_USE_LCD 下面的配置参数。

#define ESP_PANEL_BOARD_LCD_CONTROLLER ST7262
#define ESP_PANEL_BOARD_LCD_BUS_TYPE (ESP_PANEL_BUS_TYPE_RGB)

定义 LCD 控制器 IC 和通信方式,选择 RGB bus 的通信方式。

#if ESP_PANEL_BOARD_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_RGB
#define ESP_PANEL_BOARD_LCD_RGB_USE_CONTROL_PANEL (0) // 0/1. Typically set to 1

#define ESP_PANEL_BOARD_LCD_RGB_CLK_HZ (16 * 1000 * 1000)
...
#define ESP_PANEL_BOARD_LCD_RGB_IO_DATA15 (40)

#endif

ESP_PANEL_BOARD_LCD_RGB_USE_CONTROL_PANEL 设置为 0,表示使用的是没有三线 SPI 的 RGB 接口,接着就是按照 LCD 的参数进行各项的配置,跟之前的 RGB 条纹例程是一样的。

设置触摸面板的参数

#define ESP_OPEN_TOUCH 1

设置触摸开启的宏定义,用于选择是否打开触摸功能,值为 0 对应 关闭触摸,值为 1 对应 打开触摸,可依购买型号选择。

#define ESP_PANEL_BOARD_USE_TOUCH (ESP_OPEN_TOUCH)

在开头我们已经将 ESP_OPEN_TOUCH 设置成了 1,因此这里将会开启触摸 #if ESP_PANEL_BOARD_USE_TOUCH 以下的配置。如果是购买的不带触摸的版本,需将 ESP_OPEN_TOUCH 设置为 0,则不启用以下的触摸面板参数。

#define ESP_PANEL_BOARD_TOUCH_CONTROLLER GT911
#define ESP_PANEL_BOARD_TOUCH_BUS_TYPE (ESP_PANEL_BUS_TYPE_I2C)

定义触摸芯片为 GT911 以及 通信接口为 I2C bus。

#define ESP_PANEL_BOARD_TOUCH_I2C_IO_SCL (9)
#define ESP_PANEL_BOARD_TOUCH_I2C_IO_SDA (8)
#define ESP_PANEL_BOARD_TOUCH_INT_IO (4)

这里分别设置触摸的 SCL, SDA, 和 中断引脚。

设置背光参数

#define ESP_PANEL_BOARD_USE_BACKLIGHT (1)

将 ESP_PANEL_BOARD_USE_BACKLIGHT 设置为 1,表示开启背光的控制,将会使能 #if ESP_PANEL_BOARD_USE_BACKLIGHT 以下的配置。

#define ESP_PANEL_BOARD_BACKLIGHT_TYPE (ESP_PANEL_BACKLIGHT_TYPE_SWITCH_EXPANDER)

#if (ESP_PANEL_BOARD_BACKLIGHT_TYPE == ESP_PANEL_BACKLIGHT_TYPE_SWITCH_GPIO) || \
(ESP_PANEL_BOARD_BACKLIGHT_TYPE == ESP_PANEL_BACKLIGHT_TYPE_SWITCH_EXPANDER) || \
(ESP_PANEL_BOARD_BACKLIGHT_TYPE == ESP_PANEL_BACKLIGHT_TYPE_PWM_LEDC)

#define ESP_PANEL_BOARD_BACKLIGHT_IO (2) // Output GPIO pin number
#define ESP_PANEL_BOARD_BACKLIGHT_ON_LEVEL (1) // Active level, 0: low, 1: high

#endif

这里是将背光类型设置为 IO 扩展芯片进行控制,并且设置控制 IO 引脚为 EXIO2。

#define ESP_PANEL_BOARD_BACKLIGHT_IDLE_OFF (0)

设置初始化后开启背光。

设置 IO 扩展芯片的参数

#define ESP_PANEL_BOARD_USE_EXPANDER (1)

将 ESP_PANEL_BOARD_USE_EXPANDER 宏定义设置为 1,表示开始 IO 扩展芯片,将会使能 #if ESP_PANEL_BOARD_USE_EXPANDER 下的各项参数。

#define ESP_PANEL_BOARD_EXPANDER_CHIP CH422G

IO 扩展芯片名字设置成 CH422G。

#define ESP_PANEL_BOARD_EXPANDER_I2C_CLK_HZ (400 * 1000)
// Typically set to 400K
#define ESP_PANEL_BOARD_EXPANDER_I2C_SCL_PULLUP (1) // 0/1. Typically set to 1
#define ESP_PANEL_BOARD_EXPANDER_I2C_SDA_PULLUP (1) // 0/1. Typically set to 1
#define ESP_PANEL_BOARD_EXPANDER_I2C_IO_SCL (9)
#define ESP_PANEL_BOARD_EXPANDER_I2C_IO_SDA (8)

#define ESP_PANEL_BOARD_EXPANDER_I2C_ADDRESS (0x20)

设置 IO 扩展芯片 I2C 通信的相关参数:时钟频率、SDA 和 SCL 引脚等。

配置完以上这些参数之后,即可在程序当中初始化屏幕并进行显示。

2. 初始化 LVGL​

头文件部分

#include <Arduino.h>
#include <esp_display_panel.hpp>
#include <esp_err.h>
#include <lvgl.h>
#include <demos/lv_demos.h>

#include "esp_lv_adapter_arduino.h"

using namespace esp_panel::drivers;
using namespace esp_panel::board;
  • 这里引入 Arduino、ESP32_Display_Panel、LVGL 和 LVGL 示例组件,并引入示例目录中的 esp_lv_adapter_arduino.h。

  • using namespace :为了简化后面写法,不用 esp_panel::board::Board ,直接写 Board 。

    esp_lv_adapter_arduino.h 的作用

    这个文件是示例目录中的 Arduino 适配层,负责注册显示设备和触摸输入设备,并提供 LVGL 的初始化、任务启动、互斥锁和解锁接口:

    • esp_lv_adapter_init():初始化 LVGL、定时器和互斥锁。
    • esp_lv_adapter_register_display():注册显示设备。
    • esp_lv_adapter_register_touch():注册触摸输入设备。
    • esp_lv_adapter_start():启动 LVGL 任务。

    当前示例不再使用 lvgl_v8_port.h、lvgl_port_init() 或 lvgl_port_lock()。

初始化开发板

Serial.begin(115200);
Serial.println("LVGL v8 demo start");

Board *board = new Board();
if ((board == nullptr) || !board->init()) {
Serial.println("Board init failed");
while (true) {
delay(1000);
}
}

初始化串口和开发板。如果开发板初始化失败,程序输出错误信息并停留在循环中。

配置 RGB 显示缓存

const esp_lv_adapter_rotation_t rotation = ESP_LV_ADAPTER_ROTATE_0;
const esp_lv_adapter_tear_avoid_mode_t tear_mode = ESP_LV_ADAPTER_TEAR_AVOID_MODE_DEFAULT_RGB;
const uint8_t frame_buffer_count = esp_lv_adapter_get_required_frame_buffer_count(tear_mode, rotation);

LCD *lcd = board->getLCD();
if (lcd == nullptr) {
Serial.println("LCD device is not available");
while (true) {
delay(1000);
}
}
auto *lcd_bus = lcd->getBus();
if (lcd_bus->getBasicAttributes().type == ESP_PANEL_BUS_TYPE_RGB) {
lcd->configFrameBufferNumber(frame_buffer_count);
static_cast<BusRGB *>(lcd_bus)->configRGB_BounceBufferSize(lcd->getFrameWidth() * 10);
}

assert(board->begin());

示例使用 RGB 总线时,根据撕裂规避模式和旋转方向计算 frame buffer 数量,并配置 RGB bounce buffer。board->begin() 用于启动开发板上的显示和触摸设备。

注册 LVGL 显示设备和触摸输入

esp_lv_adapter_config_t adapter_config = ESP_LV_ADAPTER_DEFAULT_CONFIG();
adapter_config.task_stack_size = 12 * 1024;
adapter_config.task_priority = 2;
adapter_config.task_core_id = ARDUINO_RUNNING_CORE;
ESP_ERROR_CHECK(esp_lv_adapter_init(&adapter_config));

esp_lv_adapter_display_config_t disp_config = ESP_LV_ADAPTER_DISPLAY_RGB_DEFAULT_CONFIG(
lcd, lcd->getFrameWidth(), lcd->getFrameHeight(), rotation
);
disp_config.profile.use_psram = true;

lv_display_t *disp = esp_lv_adapter_register_display(&disp_config);
assert(disp != nullptr);

if (board->getTouch() != nullptr) {
esp_lv_adapter_touch_config_t touch_config = ESP_LV_ADAPTER_TOUCH_DEFAULT_CONFIG(disp, board->getTouch());
lv_indev_t *touch = esp_lv_adapter_register_touch(&touch_config);
assert(touch != nullptr);
}

esp_lv_adapter_init() 初始化 LVGL 适配层。随后使用显示配置注册 LCD;如果开发板检测到触摸设备,再注册触摸输入设备。无触摸版本不会执行触摸注册代码。

启动 LVGL 任务并创建界面

ESP_ERROR_CHECK(esp_lv_adapter_start());

ESP_ERROR_CHECK(esp_lv_adapter_lock(-1));
lv_demo_widgets();
esp_lv_adapter_unlock();

esp_lv_adapter_start() 启动 LVGL 任务。LVGL 不是线程安全的,调用 esp_lv_adapter_lock(-1) 后才能创建界面;参数 -1 表示持续等待,直到获得锁。lv_demo_widgets() 创建官方 Widgets 示例,完成后调用 esp_lv_adapter_unlock() 解锁。


LVGL v9 移植​

本节使用示例包中的 LVGL v9.5.0 示例,通过 ESP32_Display_Panel 库驱动屏幕和触摸面板,并显示 LVGL Widgets 示例。

硬件连接​

USB 连接方式与上文相同。使用 Type-C 转 Type-A 的线,将 ESP32-S3-Touch-LCD-7 的 USB 口连接到电脑的 USB 口。

示例代码​

请先从以下地址获取示例程序:ESP32-S3-Touch-LCD-7 示例程序 (如果先前已经下载,直接打开对应文件夹即可) 下载或克隆仓库后,打开对应的 examples\Arduino\examples\10_lvgl_v9_demo 文件夹:

在 Arduino IDE 中双击打开 10_lvgl_v9_demo.ino,然后选择串口和开发板型号 Waveshare ESP32-S3-Touch-LCD-7。

设置对应的开发板参数,然后点击上传按钮,等待程序上传完成。

运行结果​

重新给屏幕上电,可以看到屏幕开始显示 LVGL v9.5.0 Widgets 示例。带有触摸面板的版本还可以通过滑动屏幕测试触摸功能。

ESP32-S3-Touch-LCD-7 LVGL v9.5.0 示例运行结果