重庆网站建设川娃子企业网站建设费用怎么记账
LVGL移植说明
移植LVGL版本:8.3.6
主控:STM32F407ZGT6
github链接:https://github.com/lvgl/lvgl.git
文章目录
- LVGL移植说明
 - STM32移植LVGL
 - ①需要的依赖文件
 - ②移植显示驱动文件
 - ③将文件加入工程当中
 - ④配置心跳
 - ④修改栈堆的空间
 - ⑤编译链接
 
STM32移植LVGL
步骤说明:
- 下载lvgl的数据包
 - 将lvgl的依赖文件加入工程当中
 - 修改LVGL的配置文件,主要就是lv_port_disp_template文件和lv_conf文件的配置。
 - 配置心跳
 - 修改栈堆空间配置
 
注意事项:
在官方的文档说明当中有这样的一个说明:
基本上,每个能够驱动显示器的现代控制器都适合运行 LVGL。最低要求是:
-  
16、32 或 64 位微控制器或处理器
 -  
> 推荐 16 MHz 时钟速度
 -  
闪存/ROM:> 64 kB 用于非常重要的组件(建议 > 180 kB)
 -  
内存:
静态 RAM 使用:~2 kB,具体取决于使用的功能和对象类型堆栈:> 2kB(建议> 8 kB)动态数据(堆):> 2 KB(如果使用多个对象,建议> 48 kB)。
LV_MEM_SIZE在lv_conf.h中设置。显示缓冲区:> *“水平分辨率”*像素(建议>10 *“水平分辨率” )*MCU 或外部显示控制器中的一个帧缓冲器 -  
C99 或更新的编译器
 
①需要的依赖文件

还有examples里面的porting文件,里面有三个.c文件和.h文件
其中lv_port_indev文件是对接触摸事件的
lv_port_disp对接显示事件
lv_port_fs对接文件管理事件
另外,里面的三个文件的.c和.h都有一个开关,需要用到哪个文件需得把相对应的开关打开。
除此之外,还有一个lv_conf_template.h文件,默认是把文件关闭的,需要打开。除此之外 LVGL 的核心实现中,都是使用 #include “lv_conf.h”,所以 lv_conf_template.h 文件改名为 lv_conf.h 是必须要做的;
②移植显示驱动文件
在这一个部分当中主要的就是lv_port_disp文件。要对屏幕的显示驱动进行对接。在这个文件当中,主要配置两个函数。即:disp_flush、lv_port_disp_init。主要对这两个文件进行配置。
首先要定义一下屏幕的分辨率大小
#define MY_DISP_HOR_RES    240
#define MY_DISP_VER_RES    320
 
lv_port_disp_init函数:
void lv_port_disp_init(void)
{/*-------------------------* Initialize your display* -----------------------*/disp_init();/*-----------------------------* Create a buffer for drawing*----------------------------*//*** LVGL requires a buffer where it internally draws the widgets.* Later this buffer will passed to your display driver's `flush_cb` to copy its content to your display.* The buffer has to be greater than 1 display row** There are 3 buffering configurations:* 1. Create ONE buffer:*      LVGL will draw the display's content here and writes it to your display** 2. Create TWO buffer:*      LVGL will draw the display's content to a buffer and writes it your display.*      You should use DMA to write the buffer's content to the display.*      It will enable LVGL to draw the next part of the screen to the other buffer while*      the data is being sent form the first buffer. It makes rendering and flushing parallel.** 3. Double buffering*      Set 2 screens sized buffers and set disp_drv.full_refresh = 1.*      This way LVGL will always provide the whole rendered screen in `flush_cb`*      and you only need to change the frame buffer's address.*//* Example for 1) */static lv_disp_draw_buf_t draw_buf_dsc_1;static lv_color_t buf_1[MY_DISP_HOR_RES * MY_DISP_VER_RES/4];                          /*A buffer for 10 rows*/lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, MY_DISP_HOR_RES * MY_DISP_VER_RES/4);   /*Initialize the display buffer*//* Example for 2) */
//    static lv_disp_draw_buf_t draw_buf_dsc_2;
//    static lv_color_t buf_2_1[MY_DISP_HOR_RES * 10];                        /*A buffer for 10 rows*/
//    static lv_color_t buf_2_2[MY_DISP_HOR_RES * 10];                        /*An other buffer for 10 rows*/
//    lv_disp_draw_buf_init(&draw_buf_dsc_2, buf_2_1, buf_2_2, MY_DISP_HOR_RES * 10);   /*Initialize the display buffer*///    /* 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 * LV_VER_RES_MAX);   /*Initialize the display buffer*//*-----------------------------------* Register the display in LVGL*----------------------------------*/static lv_disp_drv_t disp_drv;                         /*Descriptor of a display driver*/lv_disp_drv_init(&disp_drv);                    /*Basic initialization*//*Set up the functions to access to your display*//*Set the resolution of the display*/disp_drv.hor_res = MY_DISP_HOR_RES;disp_drv.ver_res = MY_DISP_VER_RES;/*Used to copy the buffer's content to the display*/disp_drv.flush_cb = disp_flush;/*Set a display buffer*/disp_drv.draw_buf = &draw_buf_dsc_1;/*Required for Example 3)*///disp_drv.full_refresh = 1;/* Fill a memory array with a color if you have GPU.* Note that, in lv_conf.h you can enable GPUs that has built-in support in LVGL.* But if you have a different GPU you can use with this callback.*///disp_drv.gpu_fill_cb = gpu_fill;/*Finally register the driver*/lv_disp_drv_register(&disp_drv);
}
 
在官方文档中有这么一个说明,要有一个显示缓冲区,帧缓冲区和至少 1/10 屏幕大小的缓冲区用于渲染。在这个函数里面官方给出了三种缓冲区模式,分别是单缓冲区,非全尺寸双缓冲区,全尺寸双缓冲区。
初始化了屏幕的宽和高。即分辨率:
	disp_drv.hor_res = MY_DISP_HOR_RES;disp_drv.ver_res = MY_DISP_VER_RES;	
 
还调用了一个回调函数,对接底层和芯片平台相关的刷图接口。
disp_drv.flush_cb = disp_flush;
 
这个接口主要就是要对一个区域进行绘制,并把颜色传入到里面。
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*///        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++;
//            }
//        }
//    }LCD_Color_Fill(area->x1,area->y1,area->x2,area->y2,(u16*)color_p);/*IMPORTANT!!!*Inform the graphics library that you are ready with the flushing*/lv_disp_flush_ready(disp_drv);
}
 
这样就把基本的显示接口对接完成。
另外,在配置lv_conf.h文件。
/*Color depth: 1 (1 byte per pixel), 8 (RGB332), 16 (RGB565), 32 (ARGB8888)*/
#define LV_COLOR_DEPTH 16/*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/#define LV_MEM_SIZE (48U * 1024U)          /*[bytes]*/
// 用于渲染和 LVGL 内部处理机制的 buffer 个数,如果配置不够的话,LVGL 会打印 ERROR 信息// 这个其实是一个 lv_mem_buf_arr_t[LV_MEM_BUF_MAX_NUM] 结构的数组个数;
#define LV_MEM_BUF_MAX_NUM 16// 这个参数决定了多久处理一起屏幕刷新,默认情况是 30ms
#define LV_DISP_DEF_REFR_PERIOD 30      /*[ms]*//*Input device read period in milliseconds*/
// 这个参数决定了多久处理一起input,默认情况是 30ms
#define LV_INDEV_DEF_READ_PERIOD 30     /*[ms]*//*1: Show CPU usage and FPS count*/
#define LV_USE_PERF_MONITOR 1/*1: Show the used memory and the memory fragmentation* Requires LV_MEM_CUSTOM = 0*/
#define LV_USE_MEM_MONITOR 0/*Default Dot Per Inch. Used to initialize default sizes such as widgets sized, style paddings.*(Not so important, you can adjust it to modify default sizes and spaces)*/
#define LV_DPI_DEF 130     /*[px/inch]*/
 
- LV_COLOR_DEPTH参数是设置颜色的深度。有三种模式可以供我们选择,RGB332,RGB565,ARGB8888。三种,根据自己屏幕进行选择即可。
 - LV_MEM_SIZE是用于 LVGL 的动态申请/释放内存,这里我们配置的 48KB 的全局数组给 LVGL 使用
 - LV_MEM_BUF_MAX_NUM用于渲染和 LVGL 内部处理机制的 buffer 个数
 - LV_DISP_DEF_REFR_PERIOD和LV_DISP_DEF_REFR_PERIOD用于处理屏幕的刷新周期,在默认当中处于30ms刷新一次,即满帧为33FPS。
 - LV_USE_PERF_MONITOR用于打开或者关闭帧率的监控管理。
 - LV_USE_MEM_MONITOR用于打开或者关闭内存的监控管理。
 
③将文件加入工程当中

将examples里面的porting文件加入工程、src里面的所有文件加入工程当中。
④配置心跳
LVGL 的任务都是基于时间的,包含绘制,响应触摸等等;所以呢,我们需要给它一个时间基准;
LVGL 提供了一个 lv_tick_inc 的函数,我们需要在系统中去周期性调用他,告诉 LVGL 的时间基准;可以用硬件 Timer,也可以使用 SystemTick;
 void TIM3_IRQHandler(void){/* USER CODE BEGIN TIM3_IRQn 0 *//* USER CODE END TIM3_IRQn 0 *//* USER CODE BEGIN TIM3_IRQn 1 *//* USER CODE END TIM3_IRQn 1 */if(LL_TIM_IsActiveFlag_UPDATE(TIM3) == SET){LL_TIM_ClearFlag_UPDATE(TIM3);lv_tick_inc(1);// LL_GPIO_TogglePin(GPIOF, LL_GPIO_PIN_9);}}
 
④修改栈堆的空间
在官方文档当中的最小配置文档说明,根据其要求进行对栈堆的大小进行修改。

⑤编译链接
在文档中说明使用C99的风格进行编码,因此,需要将KEIL配置中的C99选项进行勾选。
另外,编译当中会有一些无关紧要的warning,在 Options->C/C++ 的 Misc Controls 中加入以下命令即可。
--diag_suppress=188 --diag_suppress=111 --diag_suppress=550
