LVGL

lvgl是目前比较流行的嵌入式开源GUI库,界面简约,占用内存小,响应式布局等优点。
lvgl官网地址https://lvgl.io/
lvgl的github仓库地址https://github.com/lvgl
上面的网站可能需要"科学上网"

材料

  1. STM32F103ZET6精英开发版
  2. 电容触摸屏800x480
  3. keil5
  4. Notepad++或vscode(任意一种代码查看软件)

移植底层显示驱动

需要把官方文件目录下lvgl先解压,之后在lvgl\porting目录下把lv_port_indev_template.c lv_port_indev_template.h lv_port_disp_template.h lv_port_disp_template.c复制到自己的例程文件夹下的lvgl驱动文件夹里。disp文件和触摸驱动有关,indev和显示驱动有关。
之后修改驱动代码

lv_port_disp_template.h

#if 1 #默认数值0改为1
#ifndef LV_PORT_DISP_H
#define LV_PORT_DISP_H
#ifdef __cplusplus
extern "C" {
#endif
#include "lvgl/lvgl.h"
void lv_port_disp_init(void);
#增添上述语句
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /*LV_PORT_DISP_H*/
#endif /*Disable/Enable content*/

lv_port_disp_template.c

这里给出修改之后的代码。

#if 1

#include "lv_port_disp.h"
#include "lcd.h"

static void disp_init(void);//声明函数

static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p);
#if LV_USE_GPU
static void gpu_blend(lv_color_t * dest, const lv_color_t * src, uint32_t length, lv_opa_t opa);
static void gpu_fill(lv_color_t * dest, uint32_t length, lv_color_t color);
#endif

void lv_port_disp_init(void)
{
    /*-------------------------
     * Initialize your display
     * -----------------------*/
    disp_init();

    /*-----------------------------
     * Create a buffer for drawing
     *----------------------------*/
    /* Example for 1) */
    static lv_disp_buf_t disp_buf_1;
    static lv_color_t buf1_1[LV_HOR_RES_MAX * 10];                      /*A buffer for 10 rows*/
    lv_disp_buf_init(&disp_buf_1, buf1_1, NULL, LV_HOR_RES_MAX * 10);   /*Initialize the display buffer*/

    /*-----------------------------------
     * Register the display in LittlevGL
     *----------------------------------*/

    lv_disp_drv_t disp_drv;                         /*Descriptor of a display driver*/
    lv_disp_drv_init(&disp_drv);                    /*Basic initialization*/

    /*Set up the functions to access to your display*/
    /*Set the resolution of the display*/
    disp_drv.hor_res = lcddev.width;
    disp_drv.ver_res = lcddev.height;
   //动态获取屏幕大小(可以不用设置)
    disp_drv.flush_cb = disp_flush;

    /*Set a display buffer*/
    disp_drv.buffer = &disp_buf_1;

#if LV_USE_GPU
    /*Optionally add functions to access the GPU. (Only in buffered mode, LV_VDB_SIZE != 0)*/

    /*Blend two color array using opacity*/
    disp_drv.gpu_blend = gpu_blend;

    /*Fill a memory array with a color*/
    disp_drv.gpu_fill = gpu_fill;
#endif

    /*Finally register the driver*/
    lv_disp_drv_register(&disp_drv);
}

/**********************
 *   STATIC FUNCTIONS
 **********************/

/* Initialize your display and the required peripherals. */
static void disp_init(void)
{
    /*You code here*/
}

/* Flush the content of the internal buffer the specific area on the display
 * You can use DMA or any hardware acceleration to do this operation in the background but
 * 'lv_disp_flush_ready()' has to be called when finished. */
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
		LCD_Color_Fill(area->x1,area->y1,area->x2,area->y2,(u16*)color_p);
    /* IMPORTANT!!!
     * Inform the graphics library that you are ready with the flushing*/
    lv_disp_flush_ready(disp_drv);
}


/*OPTIONAL: GPU INTERFACE*/
#if LV_USE_GPU

/* If your MCU has hardware accelerator (GPU) then you can use it to blend to memories using opacity
 * It can be used only in buffered mode (LV_VDB_SIZE != 0 in lv_conf.h)*/
static void gpu_blend(lv_disp_drv_t * disp_drv, lv_color_t * dest, const lv_color_t * src, uint32_t length, lv_opa_t opa)
{
    /*It's an example code which should be done by your GPU*/
    uint32_t i;
    for(i = 0; i < length; i++) {
        dest[i] = lv_color_mix(dest[i], src[i], opa);
    }
}

/* If your MCU has hardware accelerator (GPU) then you can use it to fill a memory with a color
 * It can be used only in buffered mode (LV_VDB_SIZE != 0 in lv_conf.h)*/
static void gpu_fill_cb(lv_disp_drv_t * disp_drv, lv_color_t * dest_buf, lv_coord_t dest_width,
                    const lv_area_t * fill_area, lv_color_t color);
{
    /*It's an example code which should be done by your GPU*/
    uint32_t x, y;
    dest_buf += dest_width * fill_area->y1; /*Go to the first line*/

    for(y = fill_area->y1; y < fill_area->y2; y++) {
        for(x = fill_area->x1; x < fill_area->x2; x++) {
            dest_buf[x] = color;
        }
        dest_buf+=dest_width;    /*Go to the next line*/
    }
}

#endif  /*LV_USE_GPU*/

#else /* Enable this file at the top */

/* This dummy typedef exists purely to silence -Wpedantic. */
typedef int keep_pedantic_happy;
#endif

上面的触摸驱动代码没有设置GPU接口,可根据开发板的硬件支持进行选择。目标在LV_USE_GPU

移植底层触摸驱动

lv_port_indev_template.h

#if 1 #默认数值0改为1
#ifndef LV_PORT_INDEV_H
#define LV_PORT_INDEV_H
#ifdef __cplusplus
extern "C" {
#endif
#include "lvgl/lvgl.h"
void lv_port_indev_init(void);
#增添以上语句
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /*LV_PORT_INDEV_TEMPL_H*/
#endif /*Disable/Enable content*/

lv_port_indev_template.c

修改之后的代码如下。

#if 1
#include "lv_port_indev.h"
#include "touch.h"
static bool touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
void lv_port_indev_init(void)
{
    lv_indev_drv_t indev_drv;

    /*------------------
     * Touchpad
     * -----------------*/

    /*Register a touchpad input device*/
    lv_indev_drv_init(&indev_drv);
    indev_drv.type = LV_INDEV_TYPE_POINTER;
    indev_drv.read_cb = touchpad_read;
    lv_indev_drv_register(&indev_drv);
}
static bool touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{
		static uint16_t last_x = 0;
		static uint16_t last_y = 0;
		if(tp_dev.sta&TP_PRES_DOWN)//´¥Ãþ°´ÏÂÁË
		{
			last_x = tp_dev.x[0];
			last_y = tp_dev.y[0];
			data->point.x = last_x;
			data->point.y = last_y;
			data->state = LV_INDEV_STATE_PR;
		}
                else{
			data->point.x = last_x;
			data->point.y = last_y;
			data->state = LV_INDEV_STATE_REL;
		}
    /*Return `false` because we are not buffering and no more data to read*/
    return false;
}
#else /* Enable this file at the top */
typedef int keep_pedantic_happy;
#endif

Q.E.D.


C程序员永远不会灭亡,他们只是cast成了void