这是一篇如何将LVGL移植到Arduino的教程(基于芯片ESP32 Pico D4);

软件版本

这次实验使用的lvgl版本是8.1.1,要先配置好tft_espi,确保显示正常;如果要使用触摸屏设备,在移植之前要确保能获取到触摸数据;

工程配置

库安装

添加lvgl库 ,最好也添加lv_examples库,自带的例子虽然内容完全一样,但是并不能直接使用;

库安装

然后复制为lv_conf_template.h为lv_conf.h:

lv_conf.h创建

然后复制为lv_demo_conf_template.h为lv_demo_conf.h:

lv_demo_conf.h创建

配置文件

lv_conf.h

修改这几个地方;

启动lv_conf.h:

启动lv_conf

设置色深,一般都是16:

设置色深

启动自定义时钟,不设置的话只会显示第一帧不动:

启动自定义时钟

LV_DPI_DEF 注意这里,虽然LVGL的作者说这个没这么重要,但他会严重影响到LVGL的动画效果,你应该进行DPI的手动计算,例如240x280分辨率1.69英寸的屏幕,那么 DPI为:

LV_DPI_DEF =\frac{\sqrt{240*280} }{1.69} ≈ 153

LV_DPI_DEF配置

也可以使能日志打印:

使能日志打印

lv_demo_conf.h

修改这几个地方;

启动lv_demo_conf.h:

启动Demo

配置要运行的Demo:

Demo选择

自定义显示接口和外部输入接口

文件添加

在src文件夹下添加以下两个文件:

自定义接口

代码内容

my_lv_ports.cpp

#include "my_lv_ports.h"
#include "CST816T.h"
// TFT_eSPI tft = TFT_eSPI(screenWidth, screenHeight); /* TFT instance */
TFT_eSPI tft = TFT_eSPI();     /* TFT instance */
CST816T touch(19, 21, -1, 22); // sda, scl, rst, irq

// /*Read the touchpad*/
void my_touchpad_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data)
{
    bool FingerNum = 0;
    uint8_t gesture;
    uint16_t touchX, touchY;
    FingerNum = touch.getTouch(&touchX, &touchY, &gesture);
    if (FingerNum)
    {
        data->state = LV_INDEV_STATE_REL;
        data->point.x = touchX;
        data->point.y = touchY;
#if LV_USE_LOG != 0
        Serial.printf("Touch: x=%d y=%d mode=%d\r\n", touchX, touchY, gesture);
#endif
        FingerNum = 0;
    }
    else
    {
        data->state = LV_INDEV_STATE_PR;
    }
}
/* Display flushing */
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area,
                   lv_color_t *color_p)
{
    uint32_t w = (area->x2 - area->x1 + 1);
    uint32_t h = (area->y2 - area->y1 + 1);

    tft.setSwapBytes(true);
    // tft.pushImageDMA(area->x1, area->y1, w, h, (uint16_t *)&color_p->full);
    tft.pushImage(area->x1, area->y1, w, h, (uint16_t *)&color_p->full);
    // tft.startWrite();
    // tft.setAddrWindow( area->x1, area->y1, w, h );
    // tft.pushColors( ( uint16_t * )&color_p->full, w * h, true );
    // tft.endWrite();

    lv_disp_flush_ready(disp);
}

#if LV_USE_LOG != 0
void my_print(const char *buf)
{
    Serial.printf("%s \r\n", buf);
}
#endif

void my_disp_init(void)
{
    // 绘图缓冲初始化
    //   static lv_disp_draw_buf_t draw_buf;
    //   static lv_color_t buf[screenWidth * 10];
    //   lv_disp_draw_buf_init(&draw_buf, buf, NULL, screenWidth * 10);

    static lv_disp_draw_buf_t draw_buf;
    static lv_color_t buf_2_1[screenWidth * 40]; /*A buffer for 10 rows*/
    static lv_color_t buf_2_2[screenWidth * 40]; /*An other buffer for 10
    rows*/
    lv_disp_draw_buf_init(&draw_buf, buf_2_1, buf_2_2,
                          screenWidth * 30); /*Initialize
                          the display buffer*/

    // TFT驱动初始化
    tft.begin(); /* TFT init */
    // tft.initDMA();
    tft.setRotation(0); /* Landscape orientation, flipped */

    // 设置LVGL显示设备
    static lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);
    /*Change the following line to your display resolution*/
    disp_drv.hor_res = screenWidth;
    disp_drv.ver_res = screenHeight;
    disp_drv.flush_cb = my_disp_flush;
    disp_drv.draw_buf = &draw_buf;
    lv_disp_drv_register(&disp_drv);
    touch.begin();
    // 设置LVGL输入设备(电阻屏)
    static lv_indev_drv_t indev_drv;
    lv_indev_drv_init(&indev_drv);
    indev_drv.type = LV_INDEV_TYPE_POINTER;
    indev_drv.read_cb = my_touchpad_read;
    lv_indev_drv_register(&indev_drv);

// 设置LVGL串口输出设备(调试用)
#if LV_USE_LOG != 0
    lv_log_register_print_cb(my_print);
#endif
}

my_lv_ports.h

#ifndef _MY_LV_PORTS
#define _MY_LV_PORTS
#include
#include

/*Change to your screen resolution*/
const uint16_t screenWidth = 240;
const uint16_t screenHeight = 280;
void my_disp_init(void); // 挂载lvgl接口,设置buffer
#endif

测试LVGL

benchmark测试

main.cpp

#include
#include
#include
#include
#include
#include "user.h"
#include
#include "CST816T.h"
void setup()
{
    Serial.begin(115200);
    LCD_Light_Set(50);//LCD亮度设置
    lv_init();//初始化LVGL
    my_disp_init();//初始化显示接口
    // lv_demo_widgets();
    lv_demo_benchmark();
    // lv_demo_keypad_encoder();
    // an encoder lv_demo_music();
    // lv_demo_printer();
    // lv_demo_stress();
    Serial.println("Setup done");
}
void loop()
{
    lv_timer_handler(); /* let the GUI do its work */
    delay(1);
}

运行结果;

运行结果

可以看到LVGL正常运行;