STM32移植LVGL8.3

发布时间 2024-01-08 21:52:29作者: 千樊

你需要提前准备好,LCD的相关函数、电容触摸的相关函数和一个可以跑的工程

1.准备LVGL8.3的包

2.修改lv_conf_template.hlv_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

修改屏幕像素为自己的屏幕像素

 在刷屏函数中修改为自己的刷新函数

 在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(5);
  }
  /* 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*/

此时下载代码即可观察到屏幕上有一个按钮,如下:

 

之后便是触摸的移植。

打开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();;
}

之后再定义获取坐标函数:

/*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;
}

之后如同显示部分一样将触摸的头文件#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(5);
  }
  /* USER CODE END StartDefaultTask */
}

此时编译,应该也是"APGC_V1_0\APGC_V1_0.axf" - 0 Error(s), 0 Warning(s).

下载到开发板,点击开关即可发现可以切换开关状态了,切换之后如下图:

 至此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(5);
  }
  /* 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这句话吧

 演示视频

 文件系统等到之后再移植