打印
[STM32U5]

【NUCLEO-U575ZI-Q测评】移植LVGL8.2 到ILI9488显示部分

[复制链接]
307|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lulugl|  楼主 | 2023-3-6 16:16 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
STM32U575有点150MHz的运行频率,今天试用ILI9488移植LVGL8.2
1、硬件准备:NUCLEO-U575ZI开发板、ILI9488SPILCD屏。
2、软件准备:原子lvgl8.2源码、MDK5、stm32cubeMX
【移植过程】
1、配置spi1,打开stm32cubeMX配置spi如下:


2、配置TIM6定时器

3、时钟等其他配置不在这里着重描述。然后生成mdk工程。
4、用中mdk打开工程,添加ili9488驱动,程序见附件:5、该工程目录下新建 LVGL 文件夹,并在该文件夹下新建 GUI 文件夹和 GUI_APP 文件夹,最后在 GUI 文件夹下新建 lvgl 文件夹。具体的文件夹结构如下图所示:

6、复制 LVGL 源码到工程中/GUI/lvgl 路径下
7、添加如下图所示的分组

8、往/lvgl/src/core 分组中添加 core 文件夹下的全部.c 文件9、往/lvgl/src/draw 组中添加 draw 文件夹下除 nxp_pxpnxp_vglitesdl stm32_dma2d 文件夹之外的全部.c 文件。
10、往lvgl/src/extra 组中添加 extra 文件夹下除了 lib 文件夹之外的全部.c 文件
11、lvgl/src/font 组中添加 font 文件夹下的全部.c 文件
12、/lvgl/src/gpu 组中添加 draw/stm32_dma2d draw/sdl文件夹下的全部.c文件。
13、/lvgl/src/hal 组中添加 hal 文件夹下的全部.c 文件。
14、lvgl/src/misc 组中添加 misc 文件夹下的全部.c 文件。
15、lvgl/src/widgets 组中添加 widgets 文件夹下的全部.c 文件。
16、往lvgl/examples/porting 组添加 /lvgl/examples/porting目录下的 lv_port_disp_template.c lv_port_indev_template.c 文件。
17、添加头文件路径移植 LVGL 只需要添加关键的头文件路径即可,因为 lvgl.h 文件已经为我们省去了很多包含头文件的操作,添加的头文件路径如下图所示

18、添加定时器
在Timer6的回调函数中添回如下:
/* USER CODE BEGIN 1 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
        if(htim->Instance==TIM6)
                {
       lv_tick_inc(1); /* lvgl 1ms时基*/
                }

}
/* USER CODE END 1 */
19、配置显示屏驱动
/lvgl/examples/porting 分组中的 lv_port_disp_template.c/h(显示屏相关)2 个文件中的条件编译指令#if 0
修改成#if 1,如下源码所示:
修改前:
#if 0 /* lv_port_disp_template.c/h
修改后:
#if 1 /* 把#if 0 修改成#if 1 */
修改 lv_port_disp_template.c 文件
该文件用于配置显示屏,它可以将用户的底层显示驱动与 LVGL的显示驱动衔接起来。我们打开官方提供的 lv_port_disp_template.c 文件
添加ili9488驱动头文件引用:
#include "ILI9488.h"
设置屏分辨率
#define MY_DISP_HOR_RES (320) /* 宽 */
#define MY_DISP_VER_RES (480) /* 高 */

设置注释掉lv_disp_draw_buf_t draw_buf_dsc_1、lv_disp_draw_buf_t draw_buf_dsc_2,保留
    /* Example for 3) also set disp_drv.full_refresh = 1 below*/
    static lv_disp_draw_buf_t draw_buf_dsc_3;
    static lv_color_t buf_3_1[MY_DISP_HOR_RES * MY_DISP_VER_RES];            /*A screen sized buffer*/
    static lv_color_t buf_3_2[MY_DISP_HOR_RES * MY_DISP_VER_RES];            /*Another screen sized buffer*/
    lv_disp_draw_buf_init(&draw_buf_dsc_3, buf_3_1, buf_3_2, MY_DISP_VER_RES * 480);   /*Initialize the display buffer*/

修改块显示函数如下:
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
    /*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/

    int32_t x;
    int32_t y;
                uint16_t width=320;
                uint16_t height=480;
                uint32_t i, n, cnt, buf_size,h,w;
                uint8_t r,g,b;
                w = area->x2- area->x1;
                h = area->y2- area->y1;
                setAddrWindow(area->x1, area->y1, area->x2, area->y2); //设置显示块大小
                n = w*h*3;
                n = w*h*3;
       //割分发送给屏
        if (n <= 65535){
                cnt = 1;
                buf_size = n;
        }
        else {
                cnt = n/3;
                buf_size = 3;
                uint8_t min_cnt = n/(65535)+1;
                for (i=min_cnt; i < n/3; i++){
                        if(n%i == 0){
                                cnt = i;
                                buf_size = n/i;
                                break;
                        }
                }
        }
        
        DC_DATA();
        CS_A();
                while(cnt>0)
                {
                        uint8_t frm_buf[buf_size];
                        for (i=0; i < buf_size/3; i++)
                        {
                                r = (((color_p->full & 0xF800) >> 11) * 255) / 31;
                                g = (((color_p->full & 0x07E0) >> 5) * 255) / 63;
                                b = (color_p->full & 0x001F * 255) / 31;
                                frm_buf[i*3] = r;
                                frm_buf[i*3+1] = g;
                                frm_buf[i*3+2] = b;
                                 color_p++;
                        }
                        //HAL_SPI_Transmit(&hspi1, frm_buf, buf_size, HAL_MAX_DELAY);
                        HAL_SPI_Transmit(&hspi1, frm_buf, buf_size, 10);
                        cnt -= 1;
                }
                CS_D();
               
        
    /*IMPORTANT!!!
     *Inform the graphics library that you are ready with the flushing*/
    lv_disp_flush_ready(disp_drv);
}

20、添加官方demo中的lv_demo_widgets();
把demo中的widgets拷贝到GUI_APP目录下,增加demo/widgets目录,把widgets目录下的C文件全部添时来:

然后添加头文件的文件夹的路径。
21、修改main.c添回用户代码,实现功能:
 ILI9488_Init();

        lv_init(); /* lvgl ????? */
lv_port_disp_init(); /* lvgl ???????,?? lv_init()??? */

lv_obj_t *label = lv_label_create(lv_scr_act());
lv_label_set_text(label,"Hello STM32U575!!!\n HELLO 21ic!!!");
lv_obj_center(label);
lv_demo_widgets();
  /* USER CODE END 2 */
        
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
                lv_timer_handler(); /* LVGL ??????? RTOS ???????? */
                HAL_Delay(5);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */


实现效果如图

到这里lvgl的显示屏的移植就告一段落。还差触摸没有完成。
【注】所有的移植均学习正点原子的《LVGL开发指南》。

使用特权

评论回复
沙发
Jacquetry| | 2024-1-12 16:01 | 只看该作者
一直想学一下lvgl的

使用特权

评论回复
板凳
MessageRing| | 2024-1-12 16:10 | 只看该作者
用的spi吗

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

135

主题

666

帖子

6

粉丝