ESP32S3通过Arduino移植LVGL

发布时间 2023-10-28 19:32:49作者: MaxBruce
原文:https://www.jianshu.com/p/8306f948b854

LVGL展示

此lvgl开发板开源链接:


 

准备工作

  • 显示屏驱动,需要用到“画点”或者“画区域”函数
  • 触摸驱动,如果需要用到触摸功能,还需要准备触摸函数,该函数将会返回触摸坐标给lvgl

修改lvgl

下载下来的lvgl是不能直接使用的,需要根据实际修改配置文件

第一步:下载LVGL
在github选择版本下载,链接
第二步:解压文件
解压到Arduino的libraries,并将lvgl-8.3.5重命名为lvgl
 
 
第三步:配置文件名
1,将 lv_conf_template.h 更改为 lv_conf.h

 

2,将 lv_conf.h 移动到Arduino的libraries的根目录下
第四步:打开宏

打开“lv_conf.h”文件,将此处的 #if 0 变成 if 1即可

// 上略
/* clang-format off */
#if 0 /*Set it to "1" to enable content*/

#ifndef LV_CONF_H
#define LV_CONF_H

#include <stdint.h>
// 下略
第五步:配置心跳时钟
在 lv_conf.h 中,找到 #define LV_TICK_CUSTOM ,如下图第88行所示。将其置1即可,这样lvgl将时钟arduino的时钟
 

配置lvgl结束

配置工程

lvgl本身不提供屏幕驱动,只是一个gui库,说白了需要将屏幕驱动提供的画点或者画区域函数和触摸(如果有)函数与lvgl绑定,不然lvgl怎么显示东西

显示驱动

LCD的驱动用到的函数如下

void LCD_Init(void);
void LCD_Draw_Pixel(uint16_t x, uint16_t y, uint16_t *bitmap, uint16_t w, uint16_t h);

编写回调函数,注意这里的函数名不能变,因为这是lvgl的回调函数

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);
    
    LCD_Draw_Pixel(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);   // 替换你的

    lv_disp_flush_ready(disp);
}
触摸驱动

触摸的驱动用到的函数和变量如下

extern int touch_last_x;
extern int touch_last_y;
bool touch_touched();

编写回调函数,注意这里的函数名不能变,因为这是lvgl的回调函数,程序大概意思是lvgl会定时执行 my_touchpad_read ,如果有触摸按下,则会执行if语句,并将新的触摸坐标赋值给lvgl

void my_touchpad_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) {
    /* 替换成你的 */
    if (touch_touched()) {
        data->state = LV_INDEV_STATE_PR;
        /*Set the coordinates*/
        data->point.x = touch_last_x;
        data->point.y = touch_last_y;
    }
    else {
        data->state = LV_INDEV_STATE_REL;
    }
}
完整程序
  • gui.c
#include "gui.h"
#include "LCD.h"
#include "touch.h"
#include "lvgl.h"

lv_disp_draw_buf_t draw_buf;
lv_color_t *disp_draw_buf;
lv_disp_drv_t disp_drv;

void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p);
void my_touchpad_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data);

void Gui_Init()
{
    Touch_Init();   // 触摸初始化
    LCD_Init();     // 屏幕驱动初始化
    lv_init();      // LVGL初始化

    disp_draw_buf = (lv_color_t *)heap_caps_malloc(sizeof(lv_color_t) * screenWidth * 10, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);

    lv_disp_draw_buf_init(&draw_buf, disp_draw_buf, NULL, screenWidth * 10);

    /* Initialize the display */
    lv_disp_drv_init(&disp_drv);
    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);

    /* Initialize the (dummy) input device driver */
    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);
}



/* 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);
    
    LCD_Draw_Pixel(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);

    lv_disp_flush_ready(disp);
}

void my_touchpad_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) {
    if (touch_touched()) {
        data->state = LV_INDEV_STATE_PR;
        /*Set the coordinates*/
        data->point.x = touch_last_x;
        data->point.y = touch_last_y;
    }
    else {
        data->state = LV_INDEV_STATE_REL;
    }
}
  • gui.h
#ifndef GUI_H
#define GUI_H
void Gui_Init(void);
#endif
  • Arduino主程序
#include <Arduino.h>
#include "gui.h"
#include "lvgl.h"

void setup() {
    Gui_Init();
}

void loop()
{
    lv_timer_handler(); /* let the GUI do its work */
    delay(10);
}

移植结束



作者:南方的南边
链接:https://www.jianshu.com/p/8306f948b854
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。