前言
我们在上篇中已经实现了模拟器环境下可变字体字重的设置.
是时候掏出你吃灰已久的ESP32了.
本文会使用PlatformIO创建一个全新的项目,直到显示出现上篇文章末尾的动图为止.
如遇到问题,可参考常见问题内解答.
准备工作
软件准备
为了后续内容顺利进行下去,这里需要你安装好VSCode,并在VSCode上安装PlatformIO插件.
硬件准备
名称 | 数量 | 备注 | 图例 |
:-: | :-: | :-:
ESP32 开发板 | 1 | \ | 
1.54寸LCD | 1 | 驱动ST7789,分辨率240x240 | 
杜邦线若干 | N | \ | 
创建项目
使用PlatformIO创建一个名为lvgl_with_freetype的项目

创建完毕后目录结构如下:
1 2 3 4 5 6 7 8 9 10
| . ├── include │ └── README ├── lib │ └── README ├── platformio.ini ├── src │ └── main.cpp └── test └── README
|
点亮屏幕
由于已经写过一篇点亮屏幕的文章,故本文不做过多赘述,只说明一下区别.
之前的屏幕分辨率是135x240,这次的屏幕分辨率是240x240.
所以需要使用TFT_eSPI里面的Setup24_ST7789.h
同时接线变更为
ESP32引脚名称 |
液晶屏引脚名称 |
VCC |
VCC |
GND |
GND |
G23 |
SDA |
G18 |
SCL |
G2 |
DC |
G4 |
RES |
GND |
CS |
VCC |
BLK |
对应Setup24_ST7789.h
里面内容
Setup24_ST7789.h1 2 3 4 5 6
| #define TFT_MISO 19 #define TFT_MOSI 23 #define TFT_SCLK 18 #define TFT_CS -1 #define TFT_DC 2 #define TFT_RST 4
|
随便写点内容.测试下屏幕的点亮.
main.cpp1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| #include <Arduino.h> #include <TFT_eSPI.h> #include <SPI.h>
TFT_eSPI tft = TFT_eSPI();
void setup() { Serial.begin(115200);
tft.init(); tft.setRotation(0); tft.fillScreen(TFT_BLACK); }
void loop() { tft.print("Ready Perfectly"); }
|

改为
找到第30行,修改颜色顺序
1
| #define LV_COLOR_16_SWAP 0
|
改为
1
| #define LV_COLOR_16_SWAP 1
|
找到第49行,启用自定义内存管理
修改为
找到第88行,设置自定义周期函数
1
| #define LV_TICK_CUSTOM 0
|
修改为
1
| #define LV_TICK_CUSTOM 1
|
找到第174行,启用LVGL日志功能
修改为
对接LVGL和TFT_eSPI
按照目录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| . ├── include │ └── README ├── lib │ └── README │ └── lvgl │ └── TFT_eSPI ├── platformio.ini ├── src │ └── main.cpp │ └── Port │ └── lv_port_disp.cpp │ └── lv_port_disp.h └── test └── README
|
创建lv_port_disp.cpp
和lv_port_disp.h
lv_port_disp.h1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| #ifndef LV_PORT_DISP_H_ #define LV_PORT_DISP_H_
#include "TFT_eSPI.h" #include "lvgl.h"
#define DISP_HOR_RES 240 #define DISP_VER_RES 240 #define DISP_BUF_SIZE (DISP_HOR_RES*DISP_VER_RES/4)
extern TaskHandle_t handleTaskLvgl; void Port_Init(); void lv_port_disp_init(TFT_eSPI* scr);
#endif
|
lv_port_disp.cpp1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
| #include "lv_port_disp.h"
TaskHandle_t handleTaskLvgl;
static lv_disp_drv_t disp_drv;
void TaskLvglUpdate(void* parameter) { ulTaskNotifyTake(pdTRUE, portMAX_DELAY); for (;;) { lv_task_handler();
delay(5); } }
void Port_Init() { static TFT_eSPI screen;
screen.begin(); screen.initDMA(true); screen.setRotation(0); screen.fillScreen(TFT_BLACK);
lv_init(); lv_port_disp_init(&screen); printf("lvInitDone\n"); xTaskCreatePinnedToCore(TaskLvglUpdate, "LvglThread", 20480, nullptr, configMAX_PRIORITIES, &handleTaskLvgl, 1); }
void my_print(lv_log_level_t level, const char *file, uint32_t line, const char *fun, const char *dsc) { Serial.printf("%s@%d %s->%s\r\n", file, line, fun, dsc); Serial.flush(); }
static void disp_flush_cb(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) { TFT_eSPI *screen = (TFT_eSPI *)disp->user_data;
int32_t w = (area->x2 - area->x1 + 1); int32_t h = (area->y2 - area->y1 + 1);
screen->startWrite(); screen->setAddrWindow(area->x1, area->y1, w, h); screen->pushPixelsDMA((uint16_t *)(&color_p->full), w * h); screen->endWrite();
lv_disp_flush_ready(disp); }
void lv_port_disp_init(TFT_eSPI* scr) { lv_log_register_print_cb(reinterpret_cast<lv_log_print_g_cb_t>( my_print)); DMA_ATTR static lv_color_t *lv_disp_buf = static_cast<lv_color_t *>(heap_caps_malloc( DISP_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA)); static lv_disp_draw_buf_t disp_buf; lv_disp_draw_buf_init(&disp_buf, lv_disp_buf, nullptr, DISP_BUF_SIZE);
lv_disp_drv_init(&disp_drv); disp_drv.hor_res = DISP_HOR_RES; disp_drv.ver_res = DISP_VER_RES; disp_drv.flush_cb = disp_flush_cb; disp_drv.draw_buf = &disp_buf; disp_drv.user_data = scr; lv_disp_drv_register(&disp_drv); }
|
再写个简单例子测试下LVGL能不能运行
main.cpp1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include <Arduino.h> #include "./Port/lv_port_disp.h"
void setup() { Serial.begin(115200); Port_Init();
lv_obj_t *label = lv_label_create(lv_scr_act()); lv_label_set_text(label, "Toou.\nAnata wa watashi no masuta ka?"); xTaskNotifyGive(handleTaskLvgl); }
void loop() {
}
|
Toou.Anata wa watashi no masuta ka?
 > ESP32 Pico Kit framework-arduinoespressif32 3.10006.210326 (1.0.6) tool-esptoolpy 1.30100.210531 (3.1.0) toolchain-xtensa32 2.50200.97 (5.2.0) <lvgl> 8.1.1-dev <TFT_eSPI> 2.3.89 esptool.py v3.1
|
参考资料