LVGL8.3 集成 ST7789V 显示驱动和 CTS816S 触摸屏驱动
- 起因
- 效果(正常显示,触摸屏可调换X,Y轴)
- 使用方式
- 前提
- 操作步骤
- 最后
- 参考
起因
LVGL的ESP32 Drivers库中已经包含了大多数显示和触摸芯片的驱动,基本上只需要在MenuConfig中选择即可,大大方便了屏幕适配工作。最近在一个项目中,屏幕总成使用的屏幕是ST7789V芯片和CST816T芯片。虽然给了对应Ardunio的驱动,但是在使用ESP-IDF进行开发时,还是需要进行一些简单的移植工作的。
效果(正常显示,触摸屏可调换X,Y轴)
使用方式
前提
- 已经掌握了ESP-IDF的点灯编程技能
- 已经可以集成LVGL并正常显示demo。
操作步骤
那么,与集成LVGL_ESP32_Drivers 的方式相同。
GITEE: https://gitee.com/exp-pi/lvgl_esp32_drivers
-
从以上Git仓库 Clone代码到 ESP-IDF 项目中的 components文件夹下。
-
修改 lvgl_esp32_drivers/lvgl_helpers.h 文件。定义最大的宽度和高度,如我使用的屏幕是240x280。
#define LV_HOR_RES_MAX 240
#define LV_VER_RES_MAX 280
- TFT屏幕的设置
- 打开MenuConfig。在LVGL configuration 中的 “Color Settings”,Color depth 选择 RGB565
- 勾选 Swap the 2 bytes of RGB565 color. Useful if the display has an 8-bit interface (e.g. SPI).
- 在 LVGL TFT Display controller 中 “Select a display controller model.” 选择 “ST7789V”
- 勾选 “Invert colors in display”
注意:如果没有勾选“Swap the 2 bytes of RGB565 color. Useful if the display has an 8-bit interface (e.g. SPI).” 和 “Invert colors in display”,会导致色彩不对,如:偏色、反色,重影
- 触摸屏的设置
- 在“LVGL Touch controller” 选择 “CTS816T”
- Touchpanel Configuration (CST816T) 下 对调 X、Y轴,或单一翻转X、Y轴的设置可根据自己需求选择。
- 测试验证,以下代码保存为 main.c 文件,编译、烧录。如果接线正确的话,应该就可以看到效果了。
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "lvgl.h"
#include "freertos/semphr.h"
#include "esp_system.h"
#include "lvgl_helpers.h"
#include <esp_log.h>
/*********************
* DEFINES
*********************/
#define LV_TICK_PERIOD_MS 1
/**********************
* STATIC PROTOTYPES
**********************/
static void lv_tick_task(void *arg);
static void guiTask(void *pvParameter);
static void create_demo_application(void);
/**********************
* APPLICATION MAIN
**********************/
void app_main(void)
{
// xTaskCreate(guiTask, "gui", 4096*2, NULL, 1, NULL);
// xTaskCreatePinnedToCore(guiTask, "gui", 4096*2, NULL, 1, NULL, 1);
/* NOTE: When not using Wi-Fi nor Bluetooth you can pin the guiTask to core 0 */
xTaskCreatePinnedToCore(guiTask, "gui", 4096*2, NULL, 0, NULL, 1);
}
/* Creates a semaphore to handle concurrent call to lvgl stuff
* If you wish to call *any* lvgl function from other threads/tasks
* you should lock on the very same semaphore! */
SemaphoreHandle_t xGuiSemaphore;
static void guiTask(void *pvParameter)
{
(void) pvParameter;
xGuiSemaphore = xSemaphoreCreateMutex();
lv_init();
/* Initialize SPI or I2C bus used by the drivers */
lvgl_driver_init();
lv_color_t *buf1 = heap_caps_malloc(DISP_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);
assert(buf1 != NULL);
/* Use double buffered when not working with monochrome displays */
lv_color_t* buf2 = heap_caps_malloc(DISP_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);
assert(buf2 != NULL);
static lv_disp_draw_buf_t disp_buf;
uint32_t size_in_px = DISP_BUF_SIZE;
/* Initialize the working buffer depending on the selected display. */
lv_disp_draw_buf_init(&disp_buf, buf1, buf2, size_in_px);
lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.hor_res = LV_HOR_RES_MAX;
disp_drv.ver_res = LV_VER_RES_MAX;
disp_drv.flush_cb = disp_driver_flush;
disp_drv.draw_buf = &disp_buf;
lv_disp_drv_register(&disp_drv);
#if CONFIG_LV_TOUCH_CONTROLLER != TOUCH_CONTROLLER_NONE
ESP_LOGI("LVGL","TOUCH INIT");
lv_indev_drv_t indev_drv;
lv_indev_drv_init(&indev_drv);
indev_drv.read_cb = touch_driver_read;
indev_drv.type = LV_INDEV_TYPE_POINTER;
lv_indev_drv_register(&indev_drv);
# endif
/* Create and start a periodic timer interrupt to call lv_tick_inc */
const esp_timer_create_args_t periodic_timer_args = {
.callback = &lv_tick_task,
.name = "periodic_gui"
};
esp_timer_handle_t periodic_timer;
ESP_ERROR_CHECK(esp_timer_create(&periodic_timer_args, &periodic_timer));
ESP_ERROR_CHECK(esp_timer_start_periodic(periodic_timer, LV_TICK_PERIOD_MS * 1000));
/* Create the demo application */
create_demo_application();
while (1)
{
/* Delay 1 tick (assumes FreeRTOS tick is 10ms */
vTaskDelay(pdMS_TO_TICKS(10));
lv_task_handler();
/* Try to take the semaphore, call lvgl related function on success */
if (pdTRUE == xSemaphoreTake(xGuiSemaphore, portMAX_DELAY)) {
lv_task_handler();
xSemaphoreGive(xGuiSemaphore);
}
}
}
static void event_handler(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
if(code == LV_EVENT_CLICKED) {
LV_LOG_USER("Clicked");
ESP_LOGI("Main","Clicked");
}
else if(code == LV_EVENT_VALUE_CHANGED) {
LV_LOG_USER("Toggled");
ESP_LOGI("Main","Toggled");
}
}
static void create_demo_application(void)
{
/* Get the current screen */
// lv_obj_t * scr = lv_disp_get_scr_act(NULL);
/*Create a Label on the currently active screen*/
lv_obj_t * scr = lv_scr_act(); //创建scr
// lv_obj_set_pos(scr,0,0);
// lv_obj_set_style_bg_color(scr, lv_color_hex(0x000000), 0);
// lv_scr_load(scr);
lv_obj_t * label1 = lv_label_create(scr);
/*Modify the Label's text*/
lv_label_set_text(label1, "Hello\nworld");
lv_obj_t * label2 = lv_label_create(scr);
lv_label_set_recolor(label2, true);
lv_label_set_text_fmt(label2, "Good Day #FF0000 best#");
/* Align the Label to the center
* NULL means align on parent (which is the screen now)
* 0, 0 at the end means an x, y offset after alignment*/
lv_obj_align(label1, LV_ALIGN_CENTER, -50, 0);
lv_obj_align(label2, LV_ALIGN_CENTER, 50, 0);
lv_obj_t * label;
lv_obj_t * btn1 = lv_btn_create(lv_scr_act());
lv_obj_add_event_cb(btn1, event_handler, LV_EVENT_ALL, NULL);
lv_obj_align(btn1, LV_ALIGN_CENTER, 0, 0);
label = lv_label_create(btn1);
lv_label_set_text(label, "Button");
lv_obj_center(label);
lv_obj_t * label3 = lv_label_create(lv_scr_act());
lv_label_set_long_mode(label3, LV_LABEL_LONG_SCROLL_CIRCULAR); /*Circular scroll*/
lv_obj_set_width(label3, 150);
lv_label_set_text(label3, "It is a circularly scrolling text. ");
lv_obj_align(label3, LV_ALIGN_CENTER, 0, 40);
}
static void lv_tick_task(void *arg) {
(void) arg;
lv_tick_inc(LV_TICK_PERIOD_MS);
}
最后
- TFT的驱动代码: “lvgl_esp32_drivers/lvgl_tft/st7789v.h”和“lvgl_esp32_drivers/lvgl_tft/st7789v.c”。
- 触摸屏的驱动代码在“lvgl_esp32_drivers/touch/cst816t.h”和“lvgl_esp32_drivers/touch/cst816t.c”
并非相关领域专家,仅对找到的驱动代码进行了“搬运”、“整理”。如有挖坑,多多包涵。
参考
- idf lvgl8显示触摸移植,st7789v+cst816
- ESP32 ESP-IDF LVGL8.3.3移植