STM32移植LVGL8.3

 演示视频

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

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

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

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

 此处的屏幕刷新函数QF_LCD_Fill贴出来供参考:

复制代码
copy
/**
  * @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中添加头文件

copy
#include "lvgl.h"
#include "lv_port_disp.h"

在主线程中写如下代码测试:

复制代码
copy
/* 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这个宏,修改如下

copy
/*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停止

 这样就把多余的输入设备删掉了

之后在初始化函数中添加自己的触摸屏初始化代码,如下:

copy
/*Initialize your touchpad*/
static void touchpad_init(void)
{
    QF_CTP_Init();
    /*Your code comes here*/
}

定义当前触摸屏是否按下函数:

copy
/*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的详细代码贴出来如下:

复制代码
copy
/**
  * @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;
        }
    }    
复制代码

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

复制代码
copy
/*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也贴出来,如下:

复制代码
copy
/**
  * @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中,此时的主线程变成了如下

复制代码
copy
/* 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文件,找到如下部分并改为:

复制代码
copy
/*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",此时主函数变为如下:

复制代码
copy
/* 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 中国大陆许可协议进行许可。

转载请注明出处

改编代码请注明原作者

posted @   千樊  阅读(1959)  评论(0编辑  收藏  举报
 
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起