FREERTOS+LVGL v9.1+LCD示例教程
在液晶屏幕上利用lvglv9.1显示动画
本教程省略stm32cubemx的配置过程,单片机是stm32f303retx,液晶屏是柯达科电子的KD023-C1,该液晶屏的数据线是16根(D0~D15)。整个工程文件见下载链接。
按照原理图配置cubemx
略。。。如图配置即可,注意液晶屏的RD,WR,DC,CS,RESET引脚及16根数据线D0~D15。
需要在FREERTOS中使能USE_TICK_HOOK
安装lvgl pack
相对于通过源代码移植lvgl,本人更倾向于使用lvgl pack直接安装后在Keil内简单配置即可,节省大部分复制粘贴时间。
1.直接 下载lvglpack安装,github链接如果打不开,可以考虑加梯子或者用第二种方法尝试
2.打开MDK的Pack-Installer进行直接安装
在Keil中依次点击
在LVGL中勾选Essential,并在Porting中勾选Display选项,需要增加触摸屏及按键,需要勾选Input,点击OK退出。
即可在工程文件中看到LVGL pack,展开后双击打开lv_port_disp_template.c
代码调试
安装好lvgl pack并不能直接使用,不仅需要添加lcd驱动文件,还需要修改一些内容,比如:
1.把0变成1,打开lv_port_disp_template.c和lv_port_disp_template.h把#if 0改为#if 1启用当前文件参与编译
2.添加lcd驱动文件,略,详见下方工程文件
3.在lv_port_disp_template.c中增加屏幕分辨率宏定义
#define MY_DISP_HOR_RES 320 //add this line
#define MY_DISP_VER_RES 240 //add this line
#ifndef MY_DISP_HOR_RES
#warning Please define or replace the macro MY_DISP_HOR_RES with the actual screen width, default value 320 is used for now.
#define MY_DISP_HOR_RES 320
#endif
#ifndef MY_DISP_VER_RES
#warning Please define or replace the macro MY_DISP_VER_RES with the actual screen height, default value 240 is used for now.
#define MY_DISP_VER_RES 240
#endif
4.增加类似disp_flush的函数,改变最后一个入参,因为这个屏幕支持16位传输,所以入参需要修改为16bit。增加函数声明和函数定义。
void my_disp_flush(lv_display_t * disp, const lv_area_t * area, uint16_t * px_map);
5.在my_disp_flush内增加代码LCD_Fast_DrawPoint(x, y, *px_map);
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, *px_map)*/
LCD_Fast_DrawPoint(x, y, *px_map);
px_map++;
}
}
6.增加lvgl心跳函数,放在tick钩子函数内vApplicationTickHook
lv_tick_inc(1); //lvgl heart beat
7.增加画图示例代码
LCD_Init(); //LCD引脚初始化
//GUI init
lv_init();
lv_display_t *display = lv_display_create(320, 240); /*Create the display*/
lv_display_set_flush_cb(display, my_disp_flush); /*Set a flush callback to draw to the display*/
lv_display_set_buffers(display, buf_1, buf_2, sizeof(buf_1), LV_DISPLAY_RENDER_MODE_PARTIAL); /*Set an initialized buffer*/
// Change the active screen's background color
lv_obj_set_style_bg_color(lv_screen_active(), lv_color_hex(0x003a57), LV_PART_MAIN);
lv_obj_set_style_text_color(lv_screen_active(), lv_color_hex(0xffffff), LV_PART_MAIN);
/*Create a spinner*/
lv_obj_t * spinner = lv_spinner_create(lv_screen_active());
lv_obj_set_size(spinner, 100, 100);
//lv_obj_align(spinner, LV_ALIGN_TOP_MID, 0, 0);
lv_obj_center(spinner);
lv_spinner_set_anim_params(spinner, 10000, 200);
增加函数声明及数组定义
#define DISPLAY_WIDTH 480
/*Static or global buffer(s). The second buffer is optional*/
#define BYTE_PER_PIXEL 2//(LV_COLOR_FORMAT_GET_SIZE(LV_COLOR_FORMAT_RGB565)) /*will be 2 for RGB565 */
//TODO: Declare your own BUFF_SIZE appropriate to your system.
#define BUFF_SIZE (DISPLAY_WIDTH * 10 * BYTE_PER_PIXEL)
static uint8_t buf_1[BUFF_SIZE];
static uint8_t buf_2[BUFF_SIZE];
8.循环内增加lvgl事件处理函数
for(;;)
{
lv_task_handler();
osDelay(10);
}
9.处理报错信息,此时编译代码出现
Error: L6406E: No space in execution regions with .ANY selector matching lv_mem_core_builtin.o(.bss).
Error: L6407E: Sections of aggregate size 0x20000 bytes could not fit into .ANY selector(s).
lvgl生成的代码超出了单片机ram空间,需要缩减lvgl的LV_MEM_SIZE从128K改为32K,找到lv_conf_cmsis.h,该文件隐藏两行代码
#ifndef LV_CONF_H
...
#endif /*LV_CONF_H*/
更改默认LV_MEM_SIZE
#define LV_MEM_SIZE (32 * 1024U) /*[bytes]*/
10.线程的栈改为128*40
const osThreadAttr_t defaultTask_attributes = {
.name = "defaultTask",
.stack_size = 128 * 40,
.priority = (osPriority_t) osPriorityNormal,
};
效果展示
推荐个视频转gif网站,非常好用
ps:针对stm32f303retx这个芯片,我的非正版Jlink如果勾选Download Function里面的Verify,总是提示下载失败Cortex-M4,所以工程的Options for Target不再勾选Verify,这样做有时候能仿真但是会进入HardFault中断,重新全片擦除flash再下载一次即可。
示例工程文件下载,提取码:nguy