测试环境:ESP32S3R8N8 ST7789
一、首先要有个工程
这是我的PIO板子相关配置,满足R8N8(8MB PSRAM +8MB FLASH),这里可根据不同配置来敲定,能够连接上,能够下载烧录程序,就没问题;
cpp
platform = espressif32
board = esp32-s3-devkitc-1
framework = arduino
board_build.arduino.partitions = default_8MB.csv
board_build.arduino.memory_type = qio_opi
build_flags = -DBOARD_HAS_PSRAM
board_upload.flash_size = 8MB
二、屏幕要连接上
这里使用最为广泛使用的TFT_eSPI库进行配置,直接在PIO HOME搜索装上完事

然后打开资源管理器的User_Setup.h

选驱动

选分辨率

改引脚

在main.c开启背光,进行初始化烧录程序,
cpp
#include <SPI.h>
#include <TFT_eSPI.h>
#define BACKLIGHT_PIN 1 // 根据你的接线修改!
TFT_eSPI tft = TFT_eSPI(); // 创建TFT对象
void setup() {
// 初始化屏幕
pinMode(BACKLIGHT_PIN, OUTPUT);
digitalWrite(BACKLIGHT_PIN, HIGH); // 点亮背光
tft.init();
tft.setRotation(1); // 设置屏幕的方向 0, 1, 2 or 3
tft.fillScreen(TFT_BROWN); // 填充背景
}
然后你就会发现,屏幕怎么还是黑的???
这是因为arduino驱动库和tft_espi库有冲突。
我最终在这位大佬的帖子中找到了解决办法esp32c3使用tft-espi屏幕不断重启原因及解决方法 -- 爱上生活
对于ESP32S3 而言,直接在User_Setup.h把这个开了就没问题了
如果你的颜色还有问题,那就把RGB顺序调一下,应该就没问题了
三、启动LVGL
同样,这里直接安装最新的LVGL9.4

转到项目中的 LVGL 文件夹,找到"lv_conf_template.h"文件。将其重命名为"lv_conf.h"并将第一个定义改为if 1;
注意:在网上的很多移植教程里提到需要在 lv_conf.h 中,找到 #define LV_TICK_CUSTOM ,将其置1;而在LVGL9版本中,这个宏被移除了,不去管就可以了。
最后修改main函数,简单显示一下
cpp
#include <SPI.h>
#include <TFT_eSPI.h>
#include "lvgl.h"
#include <Arduino.h>
#define BACKLIGHT_PIN 1 // 根据你的接线修改!
TFT_eSPI tft = TFT_eSPI(); // 创建TFT对象
/* 显示刷新回调 - v9 写法略有不同 */
void disp_flush(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map) {
uint32_t w = lv_area_get_width(area);
uint32_t h = lv_area_get_height(area);
tft.startWrite();
tft.setAddrWindow(area->x1, area->y1, w, h);
tft.pushColors((uint16_t *)px_map, w * h, true);
tft.endWrite();
lv_display_flush_ready(disp);
}
void setup() {
pinMode(BACKLIGHT_PIN, OUTPUT);
digitalWrite(BACKLIGHT_PIN, HIGH); // 点亮背光
tft.init();
tft.setRotation(1); // 设置屏幕的方向 0, 1, 2 or 3
lv_init();
lv_display_t *disp = lv_display_create(320, 240);
lv_display_set_flush_cb(disp, disp_flush);
static lv_color_t buf1[320 * 20];
static lv_color_t buf2[320 * 20];
lv_display_set_buffers(disp, buf1, buf2, sizeof(buf1), LV_DISPLAY_RENDER_MODE_PARTIAL);
lv_obj_t *btn = lv_btn_create(lv_scr_act());
lv_obj_set_size(btn, 100, 50);
lv_obj_center(btn);
lv_obj_t *label = lv_label_create(btn);
lv_label_set_text(label, "LVGL v9");
}
void loop()
{
uint32_t time_till_next = lv_timer_handler(); // v9 返回下次调用间隔
delay(time_till_next > 5 ? 5 : time_till_next);
}
四、启动官方DEMO
首先需要在lv_conf.h使能

然后就可以在主程序中启动demo了,不过这时候大概会编译不通过

原因可能PIO只会去编译lgvl/src里的文件,demos里引用路径不支持再深一级
我也尝试在INI文件中修改路径,但都不太好使,最后把demos文件夹移动到lvgl的src目录就行了
然后调一下路径,删掉一个../
最后附上主程序
cpp
#include <SPI.h>
#include <TFT_eSPI.h>
#include <lvgl.h>
#include "demos/lv_demos.h"
#define BACKLIGHT_PIN 1
#define SCREEN_WIDTH 240
#define SCREEN_HEIGHT 320
#define BUFFER_SIZE (SCREEN_WIDTH * 20)
TFT_eSPI tft = TFT_eSPI();
lv_display_t *disp;
static lv_color_t *buf1;
static lv_color_t *buf2;
void disp_flush(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map) {
uint32_t w = lv_area_get_width(area);
uint32_t h = lv_area_get_height(area);
tft.startWrite();
tft.setAddrWindow(area->x1, area->y1, w, h);
tft.pushColors((uint16_t *)px_map, w * h, true);
tft.endWrite();
lv_display_flush_ready(disp);
}
void setup() {
Serial.begin(9600);
pinMode(BACKLIGHT_PIN, OUTPUT);
digitalWrite(BACKLIGHT_PIN, HIGH);
tft.init();
tft.setRotation(2);
lv_init();
buf1 = (lv_color_t *)heap_caps_malloc(BUFFER_SIZE * 2, MALLOC_CAP_DMA);
buf2 = (lv_color_t *)heap_caps_malloc(BUFFER_SIZE * 2, MALLOC_CAP_DMA);
disp = lv_display_create(SCREEN_WIDTH, SCREEN_HEIGHT);
lv_display_set_flush_cb(disp, disp_flush);
lv_display_set_buffers(disp, buf1, buf2, BUFFER_SIZE * 2, LV_DISPLAY_RENDER_MODE_PARTIAL);
lv_demo_widgets();
Serial.println("Widgets Demo 启动!");
}
void loop() {
lv_timer_handler();
delay(5);
}
