STM32移植LVGL8.3
演示视频
你需要提前准备好,LCD的相关函数、电容触摸的相关函数和一个可以跑的工程(当前工程为APGC_V1_0)
1.准备LVGL8.3的包(下载传送门)
2.修改lv_conf_template.h为lv_conf.h,进入lv_conf.h,修改第15行#if 0为#if 1
3.将lvgl整个包放至工程该目录下:APGC_V1_0\Middlewares\LVGL\GUI\
当前目录结构如下图所示:
其中demos文件夹已被拷贝至APGC_V1_0\Middlewares\LVGL\GUI_APP,如下图所示
在Keil中的Manage Project Items中添加如下item
之后进入APGC_V1_0\Middlewares\LVGL\GUI\lvgl\examples\porting修改文件名称,将所有的_template都删掉,如下图所示:
在Application/LVGL_Port中添加APGC_V1_0\Middlewares\LVGL\GUI\lvgl\examples\porting中的显示与输入文件:
在Application/LVGL中添加的较多
APGC_V1_0\Middlewares\LVGL\GUI\lvgl\src\core中的全部.c文件
APGC_V1_0\Middlewares\LVGL\GUI\lvgl\src\draw中除了arm2d、nxp、外的所有.c文件
APGC_V1_0\Middlewares\LVGL\GUI\lvgl\src\extra中的全部.c文件,包括子文件夹中的
APGC_V1_0\Middlewares\LVGL\GUI\lvgl\src\font中的全部.c文件
APGC_V1_0\Middlewares\LVGL\GUI\lvgl\src\hal中的全部.c文件
APGC_V1_0\Middlewares\LVGL\GUI\lvgl\src\misc中的全部.c文件
APGC_V1_0\Middlewares\LVGL\GUI\lvgl\src\widgets中的全部.c文件
在魔术棒中添加头文件目录:
在此页也勾选C99模式,在Misc栏输入:--diag_suppress=188,546,68,111屏蔽错误
添加如下四个头文件路径:
之后编译,应该是"APGC_V1_0\APGC_V1_0.axf" - 0 Error(s), 0 Warning(s).
打开lv_port_disp.c之后将#if 0改为#if 1、#include "lv_port_disp_template.h"改为include "lv_port_disp.h"
打开lv_port_disp.h之后将#if 0改为#if 1
打开lv_port_disp.c添加头文件#include "ST7796S.h"屏幕驱动
在disp_init函数中添加你自己的屏幕初始化函数如下图
之后注释掉BUFF缓存的2和3
修改屏幕像素为自己的屏幕像素
在刷屏函数中修改为自己的刷新函数
此处的屏幕刷新函数QF_LCD_Fill贴出来供参考:
/** * @Function name LCD_SetRegion * @Introduce 设置LCD显示区域 * @attention 在此区域填充颜色自动换行 * x_start x_end 0~479 * y_start y_end 0~319 * @Return Null */ void QF_LCD_SetRegion(uint16_t x_start,uint16_t y_start,uint16_t x_end,uint16_t y_end){ LCD_WriteCmd(0x2a); LCD_WriteData((x_start >> 8) & 0xff); LCD_WriteData( x_start & 0xff); LCD_WriteData((x_end >> 8) & 0xff); LCD_WriteData( x_end & 0xff); LCD_WriteCmd(0x2b); LCD_WriteData((y_start >> 8) & 0xff); LCD_WriteData( y_start & 0xff); LCD_WriteData((y_end >> 8) & 0xff); LCD_WriteData( y_end & 0xff); LCD_WriteCmd(0x2c); } /** * @Function name QF_LCD_Fill * @Introduce 向LED某个区域填充Color数组颜色 * @attention x_start x_end 0~479 * y_start y_end 0~319 * @Return Null */ void QF_LCD_Fill(uint16_t xsta,uint16_t ysta,uint16_t xend,uint16_t yend,uint16_t* Color){ uint16_t width = xend - xsta+1; uint16_t height = yend - ysta+1; for (uint16_t i = 0; i < height; i++){ QF_LCD_SetRegion(xsta,ysta+i,xend,yend); for (uint16_t j = 0; j < width; j++){ LCD_WriteData(Color[i * width + j]); } } }
在FreeRTOS.c中添加头文件
#include "lvgl.h" #include "lv_port_disp.h"
在主线程中写如下代码测试:
/* USER CODE END Header_StartDefaultTask */ void StartDefaultTask(void *argument) { /* USER CODE BEGIN StartDefaultTask */ /* Infinite loop */ lv_init(); lv_port_disp_init(); lv_obj_t* switch_obj = lv_switch_create(lv_scr_act()); lv_obj_set_size(switch_obj,120,60); lv_obj_align(switch_obj,LV_ALIGN_CENTER,0,0); for(;;) { lv_timer_handler(); osDelay(50); } /* USER CODE END StartDefaultTask */ }
有看过别人移植的人会问:其他人移植都有另外一个函数lv_tick_inc();函数卸载定时器回调中,但此处没有,这是因为开了FreeRTOS,可以有其他方法来写,打开lv_conf.h文件,找到LV_TICK_CUSTOM这个宏,修改如下
/*Use a custom tick source that tells the elapsed time in milliseconds. *It removes the need to manually update the tick with `lv_tick_inc()`)*/ #define LV_TICK_CUSTOM 1 #if LV_TICK_CUSTOM #define LV_TICK_CUSTOM_INCLUDE "FreeRTOS.h" /*Header for the system time function*/ #define LV_TICK_CUSTOM_SYS_TIME_EXPR (xTaskGetTickCount()) /*Expression evaluating to current system time in ms*/ #endif /*LV_TICK_CUSTOM*/
此时下载代码即可观察到屏幕上有一个SWITCH,如下:
之后便是触摸的移植。
打开lv_port_indev.c之后将#if 0改为#if 1、#include "lv_port_indev_template.h"改为include "lv_port_disp.h"
打开lv_port_indev.h之后将#if 0改为#if 1
打开lv_port_indev.c添加头文件#include "GT911.h"触摸驱动
在lv_port_indev.c文件中将除了触摸屏之外的注释掉:
从这里开始注释
一直注释到最后一个花括号停下
同理从这里继续开始注释
一直注释到最后一个#else停止
这样就把多余的输入设备删掉了
之后在初始化函数中添加自己的触摸屏初始化代码,如下:
/*Initialize your touchpad*/ static void touchpad_init(void) { QF_CTP_Init(); /*Your code comes here*/ }
定义当前触摸屏是否按下函数:
/*Return true is the touchpad is pressed*/ static bool touchpad_is_pressed(void) { /*Your code comes here*/ return QF_CTP_GetEnable();; }
QF_CTP_GetEnable这个函数如果屏幕有按下则返回true,否则返回false,此处将QF_CTP_GetEnable的详细代码贴出来如下:
/** * @Function name QF_CTP_GetEnable * @Introduce CTP触摸状态 * @Return 触摸状态 */ uint8_t QF_CTP_GetEnable(void){ uint8_t _temp; CTP_ReadData(GT_GSTID_REG,&_temp,1);//读取触摸点的状态 if((_temp&0XF)&&((_temp&0XF)<6)){ return 1; }else{ _temp = 0; CTP_WriteData(GT_GSTID_REG,&_temp,1);//清标志 return 0; } }
之后再定义获取坐标函数:
/*Get the x and y coordinates if the touchpad is pressed*/ static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y) { /*Your code comes here*/ uint16_t PosX,PosY; QF_CTP_GetPos(&PosX,&PosY); (*x) = PosX; (*y) = PosY; }
同样,获取坐标函数QF_CTP_GetPos也贴出来,如下:
/** * @Function name QF_CTP_GetPos * @Introduce CTP触摸获取坐标 * @Return 坐标 */ void QF_CTP_GetPos(uint16_t *x,uint16_t *y){ uint8_t _temp; CTP_ReadData(GT_TP1_REG,PosData,4); //读取XY坐标值 *y=(((uint16_t)PosData[1]<<8)+PosData[0]); *x=(480-(((uint16_t)PosData[3]<<8)+PosData[2])); QF_DebugPrintf("x:%d,y:%d\r\n",*x,*y);//串口打印坐标,用于调试 _temp=0; CTP_WriteData(GT_GSTID_REG,&_temp,1);//清标志 }
之后如同显示部分一样将触摸的头文件#include "lv_port_indev.h"也加到FreeRTOS.c中,此时的主线程变成了如下
/* USER CODE END Header_StartDefaultTask */ void StartDefaultTask(void *argument) { /* USER CODE BEGIN StartDefaultTask */ /* Infinite loop */ lv_init(); lv_port_disp_init(); lv_port_indev_init(); lv_obj_t* switch_obj = lv_switch_create(lv_scr_act()); lv_obj_set_size(switch_obj,120,60); lv_obj_align(switch_obj,LV_ALIGN_CENTER,0,0); for(;;) { lv_timer_handler(); osDelay(50); } /* USER CODE END StartDefaultTask */ }
此时编译,应该也是"APGC_V1_0\APGC_V1_0.axf" - 0 Error(s), 0 Warning(s).
下载到开发板,点击SWITCH即可发现可以切换状态了,切换之后如下图:
至此LVGL已完成移植,之后就是相关demo的测试。
此处只演示一个music的demo测试,在Keil中的Manage Project Items中新建Application/LVGL_APP,并且将APGC_V1_0\Middlewares\LVGL\GUI_APP\demos\music目录底下的lv_demo_music.c、lv_demo_music_list.c、lv_demo_music_main.c添加进来,还有assets目录下的所有.c文件。
之后在魔术棒中添加头文件路径:
APGC_V1_0\Middlewares\LVGL\GUI_APP\demos
APGC_V1_0\Middlewares\LVGL\GUI_APP\demos\music
打开lv_conf.h文件,找到如下部分并改为:
/*Music player demo*/ #define LV_USE_DEMO_MUSIC 1 #if LV_USE_DEMO_MUSIC #define LV_DEMO_MUSIC_SQUARE 0 #define LV_DEMO_MUSIC_LANDSCAPE 0 #define LV_DEMO_MUSIC_ROUND 0 #define LV_DEMO_MUSIC_LARGE 0 #define LV_DEMO_MUSIC_AUTO_PLAY 0 #endif
之后在FreeRTOS.c中添加头文件#include "lv_demo_music.h",此时主函数变为如下:
/* USER CODE END Header_StartDefaultTask */ void StartDefaultTask(void *argument) { /* USER CODE BEGIN StartDefaultTask */ /* Infinite loop */ lv_init(); lv_port_disp_init(); lv_port_indev_init(); lv_demo_music(); for(;;) { lv_timer_handler(); osDelay(50); } /* USER CODE END StartDefaultTask */ }
此时编译应该会报错,提示某些字体找不到,
此时打开lv_conf.h文件找到如下代码
将#define LV_FONT_MONTSERRAT_12、#define LV_FONT_MONTSERRAT_16后面的0都改为1,再次编译。
注意,如果使用FreeRTOS,注意默认线程的大小,否则跑MUSIC这个DEMO的时候会出现进入HardFault_Handler的错误
最后的效果如下:
如果要问右下角的帧率怎么打开,那就去lv_conf.h中寻找#define LV_USE_PERF_MONITOR这句话吧
文件系统等到之后再移植
本文作者:lesterbor
本文链接:https://www.cnblogs.com/lesterbor/p/17953045
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
转载请注明出处
改编代码请注明原作者
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步