一、什么是lvgl?
LVGL(Light and Versatile Graphics Library)是一个开源的嵌入式图形界面库,用来在 MCU、MPU、RTOS 或裸机系统上做 GUI 界面。
在 STM32 项目里,LVGL 通常负责“画界面”,它本身不直接去控制屏幕硬件。
二、如何移植LVGL?
1、放入 LVGL 源码和配置文件
Github链接:github.com
下载对应的lvgl源码。创建一个lvgl文件夹,然后文件结构目录如下:
2、写一个显示驱动
LVGL在需要刷新的时候,把一块区域的像素数据交给你。所以说需要写一个显示回调。
我使用的是2.4寸的TFT屏幕。在我使用的这个原来的LCD驱动中,原驱动提供了如下几个函数:
LCD_Init();//初始化LCD屏幕
LCD_SetCursor(Xpos, Ypos);//设置LCD要写入的显存位置
LCD_WriteRAM_Prepare();//准备往显存RAM中写入数据
LCD_WriteRAM(color);//往显存RAM中写入颜色
把一块区域的像素数据交给你:
如上面所说,LVGL只会把一块区域的像素交给你,具体来说就类似:
从 (x1, y1) 到 (x2, y2) 这一块矩形区域需要刷新。同时LVGL也会给你一个颜色数组让你进行写入。
所以说我们要实现的函数的功能就是:把颜色数组写入到LCD对应的位置中去。
这里实现一个函数:
void LCD_FlushRect(u16 x1, u16 y1, u16 x2, u16 y2, const u16 *color_p)
也就是把color_p这个数组,写入到(x1,y1)和(x2,y2)包围起来的矩形区域中。
for (y = y1; y <= y2; y++)
{
LCD_SetCursor(...);
LCD_WriteRAM_Prepare();
for (x = x1; x <= x2; x++)
{
LCD_WriteRAM(*color_p++);
}
}
具体的x和y坐标需要根据个人的LCD屏幕的方向来决定,这里只是一个参考。
显示回调:
static void lv_port_disp_flush(lv_disp_drv_t *disp_drv,
const lv_area_t *area,
lv_color_t *color_p)
这个回调函数需要完成如下几个任务:
①取出 LVGL 要刷新的区域:
因为area被封装到了一个结构体里(LVGL提供)
typedef struct {
lv_coord_t x1;
lv_coord_t y1;
lv_coord_t x2;
lv_coord_t y2;
} lv_area_t;
所以说我们要把区域给取出来
int32_t x1 = area->x1;
int32_t y1 = area->y1;
int32_t x2 = area->x2;
int32_t y2 = area->y2;
②判断区域有没有超出屏幕范围:
如果区域有一部分超出屏幕,就把超出的部分裁剪;
③调用刚刚完成的 LCD在一块空间内写入颜色数组的函数LCD_FlushRect;
④刷新完后告诉 LVGL:
lv_disp_flush_ready(disp_drv);(LVGL自带)
这样LVGL就可以继续进行刷新了。
具体函数如下:
3、提供时基,也就是LVGL运行的节拍
LVGL需要一个1ms的节拍
也就是在一个1ms在中断中,调用一次lv_tick_inc(1);(LVGL提供)
一般我们放在:SysTick 中断;定时器中断或者RTOS 的tick钩子。
4、准备显示缓冲区并注册显示设备
LVGL 不是每画一个点就立刻写 LCD,它通常会先画到 buffer 里,再通过 flush_cb 发出去。
初始化函数如下:
这个函数实际上就是在告诉 LVGL:我的屏幕多大、缓存在哪、刷屏函数是谁。
其中:
disp_drv.hor_res = LCD_HOR_RES;//屏幕多大
disp_drv.ver_res = LCD_VER_RES; //屏幕多大
disp_drv.flush_cb = lv_port_disp_flush;// 刷屏函数是谁
disp_drv.draw_buf = &disp_buf;// 缓存在哪(disp_buf是管理buf_1的结构体,buf_1是真正存像素颜色的数组。
这几个都是基于自己显示屏的参数进行配置的。
5、初始化相关函数
lv_init();//初始化LVGL 框架内部
lv_port_disp_init();//初始化我的LCD显示层
6、主循环里持续调用 lv_timer_handler()
这个lv_timer_handler()的调用间隔一般设为5ms。
7、进行显示的测试
lv_obj_t * label = lv_label_create(lv_scr_act());
lv_label_set_text(label, "Hello LVGL");
lv_obj_center(label);
如果说屏幕中心显示Hello LVGL字样就说明移植成功了。