LVGL
lvgl是目前比较流行的嵌入式开源GUI库,界面简约,占用内存小,响应式布局等优点。
lvgl官网地址https://lvgl.io/
lvgl的github仓库地址https://github.com/lvgl
上面的网站可能需要"科学上网"
材料
- STM32F103ZET6精英开发版
- 电容触摸屏800x480
- keil5
- 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.