LVGL8.3 集成 ST7789V 显示驱动和 CST816T 触摸屏驱动

LVGL8.3 集成 ST7789V 显示驱动和 CTS816S 触摸屏驱动

  • 起因
  • 效果(正常显示,触摸屏可调换X,Y轴)
  • 使用方式
    • 前提
    • 操作步骤
    • 最后
    • 参考

起因

LVGLESP32 Drivers库中已经包含了大多数显示和触摸芯片的驱动,基本上只需要在MenuConfig中选择即可,大大方便了屏幕适配工作。最近在一个项目中,屏幕总成使用的屏幕是ST7789V芯片和CST816T芯片。虽然给了对应Ardunio的驱动,但是在使用ESP-IDF进行开发时,还是需要进行一些简单的移植工作的。

效果(正常显示,触摸屏可调换X,Y轴)

LVGL8.3 集成 ST7789V 显示驱动和 CST816T 触摸屏驱动_第1张图片

使用方式

前提

  • 已经掌握了ESP-IDF点灯编程技能
  • 已经可以集成LVGL并正常显示demo。

操作步骤

那么,与集成LVGL_ESP32_Drivers 的方式相同。
GITEE: https://gitee.com/exp-pi/lvgl_esp32_drivers

  1. 从以上Git仓库 Clone代码到 ESP-IDF 项目中的 components文件夹下。
    LVGL8.3 集成 ST7789V 显示驱动和 CST816T 触摸屏驱动_第2张图片

  2. 修改 lvgl_esp32_drivers/lvgl_helpers.h 文件。定义最大的宽度高度,如我使用的屏幕是240x280。
    LVGL8.3 集成 ST7789V 显示驱动和 CST816T 触摸屏驱动_第3张图片

#define LV_HOR_RES_MAX 240
#define LV_VER_RES_MAX 280
  1. 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”
      LVGL8.3 集成 ST7789V 显示驱动和 CST816T 触摸屏驱动_第4张图片
      LVGL8.3 集成 ST7789V 显示驱动和 CST816T 触摸屏驱动_第5张图片

注意:如果没有勾选“Swap the 2 bytes of RGB565 color. Useful if the display has an 8-bit interface (e.g. SPI).” 和 “Invert colors in display”,会导致色彩不对,如:偏色、反色,重影

  1. 触摸屏的设置
  • 在“LVGL Touch controller” 选择 “CTS816T”
  • Touchpanel Configuration (CST816T) 下 对调 X、Y轴,或单一翻转X、Y轴的设置可根据自己需求选择。
    LVGL8.3 集成 ST7789V 显示驱动和 CST816T 触摸屏驱动_第6张图片
  1. 测试验证,以下代码保存为 main.c 文件,编译、烧录。如果接线正确的话,应该就可以看到效果了。
#include 
#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 
 
/*********************
 *      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移植

你可能感兴趣的:(ESP32,ESP32,LVGL,TFT驱动)