本帖最后由 dirty 于 2024-2-28 00:33 编辑
开发板 MCU 型号FM33FT056A,Code Flash 384KB,RAM32KB,移植lvgl RAM略偏小,移植时要注意些裁剪。
一.了解LVGL及库准备
1.了解LVGL
LVGL全称Light and Versatile Graphics Library,轻量化和多功能的图形库,遵循MIT开源许可协议,具有以下特性(what LVGL can do for you)。
(1)对硬件的要求
CPU:16、32、64位
主频:推荐16 MHz
Flash/ROM空间: > 64 kB (推荐180 kB)
RAM空间: 8 kB (推荐24 kB)
C99语法
(2)功能特性
控件:支持30多种控件
显示设备:支持任意分辨率屏幕
输入设备:在同一个屏幕上支持多个输入设备
2.lvgl代码库准备
在github上获取V8.3版本,https://github.com/lvgl/lvgl/tree/release/v8.3
二.LVGL移植与代码编写
1.使用到src、demo里的文件,example里的例子可以作为界面设计参考。下面是移植好后工程文件结构目录。
图1:文件结构
2.disp_init(void)里填上LCD驱动初始化。我这里用到硬件spi,速度较软件spi明显快
3.lv_port_disp_init里选择LVGL buffer,我这里选1单buffer,把另外两个屏蔽掉
4.更改disp_flush函数
/*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)
{
if(disp_flush_enabled)
{
/*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/
#if 0
//SDK自带
// int32_t x;
// int32_t y;
// for(y = area->y1; y <= area->y2; y++) {
// for(x = area->x1; x <= area->x2; x++) {
// /*Put a pixel to the display. For example:*/
// /*put_px(x, y, *color_p)*/
// color_p++;
// }
// }
#else
uint16_t x,y;
for(y = area->y1; y <= area->y2; y++)
{
for(x = area->x1; x <= area->x2; x++)
{
/*Put a pixel to the display. For example:*/
/*put_px(x, y, *color_p)*/
// Gui_DrawPoint(x,y,color_p->full);
Gui_DrawPoint(x,y,lv_color_to16(*color_p));
color_p++;
}
}
#endif
}
/*IMPORTANT!!!
*Inform the graphics library that you are ready with the flushing*/
lv_disp_flush_ready(disp_drv);
}
5.增加LVGL时间节拍。这里创建一个1ms定时器,在定时中断里加lv_tick_inc(1);
6.lv_port_disp.c里定义屏幕像素尺寸
#define MY_DISP_HOR_RES DISPLAY_HOR_PIXEL
#define MY_DISP_VER_RES DISPLAY_VER_PIXEL
7.在Gui\lv_conf.h定义lvgl内存分配大小,我这里定义12KB,整个工程编译用了28KB RAM
8.在main函数里初始化
int main(void)
{
/* 使能IWDT */
IWDT_Init(FL_IWDT_PERIOD_4000MS);
/* Initialize FL Driver Library */
/* SHOULD BE KEPT!!! */
FL_Init();
/* 使能SVD, 阈值4.157V(falling)~4.257V(rising) */
SVD_Init(SVD_MONTIOR_VDD, FL_SVD_WARNING_THRESHOLD_GROUP11, FL_SVD_REFERENCE_1P0V);
/* 确认SVD监测结果是否高于阈值,如否则持续等待 */
while(false == SVD_Result_Confirmed(SVD_HIGHER_THRESHOLD, 2000U/*us*/));
/* 使能BOR */
RMU_BOR_Init(FL_RMU_BOR_THRESHOLD_2P00V);
MF_Config_Init();
printf("All Peripher init finish\r\n");
//lvgl
LPTIM16_Init();
FL_IWDT_ReloadCounter(IWDT);
lv_init(); // lvgl初始化,如果这个没有初始化,那么下面的初始化会崩溃
lv_port_disp_init(); // 显示器初始化
//lv_port_indev_init(); // 输入设备初始化(如果没有实现就注释掉)
//lv_port_fs_init(); // 文件系统设备初始化(如果没有实现就注释掉)
lv_ex_label_1();
while(1)
{
/* 清狗 */
FL_IWDT_ReloadCounter(IWDT);
/* 电源掉电监测处理 */
PowerDownMonitoring();
lv_task_handler();
}
}
9.在lv_ex_label_1();添加界面.这里简单写个,对lvgl插件学习也是需要不断实践
void lv_ex_label_1(void)
{
lv_obj_t* btn = lv_btn_create(lv_scr_act());
lv_obj_set_pos(btn, 100, 60);
lv_obj_set_size(btn, 80, 40);
lv_obj_t* label = lv_label_create(btn);
lv_label_set_text(label, "Button");
lv_obj_center(label);
printf("Create gui\r\n");
}
当然,还有其他需要注意的地方,踩过些坑,通过实践得以解决,以此掌握lvgl的移植与初步界面设计。
三.编译烧录,查看效果
图2:界面显示效果
可以看到创建的按钮,以及自带的CPU使用及帧率情况,至此实现lvgl的移植与初步显示。