目录
(3)移动 porting、keypad_encoder文件夹
完整代码,以及原理图下载地址:https://download.youkuaiyun.com/download/qq_26043945/90139281
STM32驱动显示屏
1.LVGL 简述
LVGL官网地址:https://github.com/lvgl/lvgl
备用源码下载地址:https://download.youkuaiyun.com/download/qq_26043945/90042554
- 丰富且强大的模块化图形组件:按钮 、图表 、列表、滑动条、图片等
- 高级的图形引擎:动画、抗锯齿、透明度、平滑滚动、图层混合等效果
- 支持多种输入设备:触摸屏、 键盘、编码器、按键等
- 不依赖特定的硬件平台
- 配置可裁剪,最低资源占用:64 kB Flash,20 kB RAM
- 基于UTF-8的多语种支持,例如中文、英文、阿拉伯文等
- 支持操作系统、外置内存、以及硬件加速(已内建支持STM32 DMA2D)
- 即便仅有单缓冲区(frame buffer)的情况下,也可保证渲染如丝般顺滑
支持模拟器仿真,可以无硬件依托进行开发
2.修改LVGL文件夹
只需要这5个文件即可,把他们复制到一个新创建的 LVGL文件夹 里面。
(1)文件夹 examples 改动
在 examples文件夹 里面,只需要保留 porting文件夹 下面的文件夹,其余删除。
在 porting文件夹 里面,只需要保留下面 4个文件,其余删除。然后对文件进行 改名 操作,如下所示。
(2)文件夹 demos 改动
在 demos文件夹 里面,只需要保留 keypad_encoder文件夹 和 lv_demos.h文件 ,其余删除。
然后把 v_demos.h文件 移动到 keypad_encoder文件夹 中,如下所示。
(3)移动 porting、keypad_encoder文件夹
把 demos里面的porting 和 examples里面的keypad_encoder 移动到 LVGL 目录下。
3.最终LVGL文件夹内容
对文件进行 改名 操作,如下所示。
4.软件Keil配置、添加头文件
(1)首先复制 LVGL 文件夹,粘贴到STM32工程目录下,然后在MDK中包括LVGL的头文件和设置c99模式。
(2)MDK里面创建4个新的文件
文件夹名称 (Groups) | 用于存放什么文件 |
LVGL_myGui | 用户自己的界面代码文件等 |
LVGL_conf | 用户配置文件等 |
LVGL_porting | LVGL 的接口文件, 如显示、触摸屏、键盘等 |
LVGL_src | LVGL 的所有底层c文件 |
重要:
每个文件夹(Group),需要添加的文件,如下表:
文件夹 | 需要添加的文件 |
---|---|
LVGL_myGui | 共3个文件: keypad_encoder文件夹下的:" lv_demos.h " 、" lv_demo_keypad_encoder.h " 、 " lv_demo_keypad_encoder.c " |
LVGL_conf | 共2个文件: LVGL文件夹下的:" lv_conf.h " 、" lvgl.h " |
LVGL_porting | 共4个文件: porting文件夹下的:" lv_port_disp.c " 、" lv_port_disp.h " 、 " lv_port_indev.c " 、" lv_port_indev.h " |
LVGL_src | 近200+的c文件:"LVGL/ src" 下的所有 c 文件(重点:包括src里所有子、子子文件夹的 c 文件. 不用添加h和mk文件) |
5.程序配置
5.1、启用 lv_conf.h
打开 lv_conf.h,对以下内容进行修改,以启用此文件。
- 第15行,原:#if 0,修改为:#if 1
完成后,是这个样子的:
5.2、启用 lv_port_disp.h
双击打开 lv_port_disp.h,修改以下内容,以启用此文件:
- 第7行,原:#if 0, 修改为:#if 1
- 第22行,原:“lvgl/lvgl.h", 修改为:”lvgl.h"
完成后,是这个样子的:
5.3、启用 lv_port_disp.c
双击打开 lv_port_disp.c,修改以下内容,以启用此文件:
- 第7行,原:#if 0, 修改为:#if 1
完成后,是这个样子的:
5.4、添加 LCD 驱动的头文件
在 lv_port_disp.c中:
- 第14行,插入你的LCD驱动文件,如:#include "bsp_LCD_ILI341.h",写上你的h文件。
- 第20行、第25行,是显示屏的宽、高度。查看你的显示屏参数,填写实际像素即可。
插入LCD的头文件,目的是为了让这个c文件,能调用LCD的: 画点函数;
注意一个:LVGL默认使用横屏的方式,这一点要注意,别写反了。
完成后,是这个样子的
5.5、选择创建缓存的方式,3选1
还是在 lv_port_disp.c 中,向下滚动,
(会出现很多错误提示,不用管。也可以先编译一次,让刚才启用的h文件生效,错误就会消失)
第86行到101行,LVGL 提供了创建显示缓冲区的3种方式,这里,必须3选1。
绝大多数情况下,使用第1种方法,即:只创建1个缓冲区;
- 注释掉第90~101行,即:不使用第2和第3种方法;
完成后,是这个样子的:
5.6、关联绘制函数
这里有两种方式,一种是一个点一个点的获取数据,然后调用画点函数进行绘制;另外一种则是通过绘制一块的地方,进行块绘制。
5.6.1、“点” 的绘制方式
还是在 lv_port_disp.c 中,向下滚动,找到disp_flush( )函数:
- 第173行,替换你的 LCD 的画点函数; 参数:x坐标、y坐标、16位颜色值。
- 小编用的画点函数:LCD_1IN69_DrawPoint(x,y,color_p->full);
完成后,是这个样子的:
这里给LVGL一个画点函数后, LVGL就能完成需要的显示操作了。
5.6.2、“块” 的绘制方式
还是在 lv_port_disp.c 中,向下滚动,找到disp_flush( )函数:
- 第173行,替换你的 LCD 的画块函数; 参数:开始x、开始y、结束x、结束y、16位颜色指针
- 小编用的画点函数:LCD_Color_Fill(area->x1,area->y1,area->x2,area->y2,&(color_p->full));
完成后,是这个样子的:
这里给LVGL一个画点函数后, LVGL就能完成需要的显示操作了。
5.7、关联触摸函数
5.7.1、修改lv_port_indev_init函数
还是在 lv_port_indev_init.c 中,向下滚动,找到lv_port_indev_init( )函数:
-
将lv_port_indev_init函数里的其他输入设备注释掉,留下触摸
-
注意!!! 注意!!! 注意!!! 注意!!!
-
一定注释掉没有用到的输入设备,不然有可能不能正常触发(遇到这样的坑,触摸没反应)
完成后,是这个样子的:
5.7.2、添加坐标获取函数
还是在 lv_port_indev_init.c 中,向下滚动,找到touchpad_read( )函数,在里面有touchpad_is_pressed函数(用于判断是否被按下),touchpad_is_pressed函数(用于获取按下的坐标)。对应的在里面添加你的触摸函数。
完成后,是这个样子的:
6.创建一个按钮的配置
这里编写一个创建一个按钮的函数,然后在main函数中调用。
void create_button(void) {
/* 创建一个按钮对象 */
lv_obj_t * btn = lv_btn_create(lv_scr_act()); // 在当前活动屏幕上创建按钮
/* 设置按钮的位置和大小 */
lv_obj_set_pos(btn, 20, 50);
lv_obj_set_size(btn, 100, 50); // 假设按钮的大小为100x50
/* 设置按钮的标签(显示的文本) */
lv_obj_t * label = lv_label_create(btn);
lv_label_set_text(label, "test");
}
7.LVGL 心跳、任务刷新
按目前的移植进度,我们只差两个时间任务要处理:
-
第1个时间任务:为LVGL提供准确的心跳。必须间隔精准地,调用时基函数:lv_tick_inc(),俗称心跳,让LVGL精准地知道时间的流逝;
-
第2个时间任务:间隔5ms左右,调用周期性任务函数: lv_timer_handler() ,它的作用是检查所有注册任务的时间戳,执行那些已经到期的任务,如:屏显更新、动画更新、触控、定时器事件等;
7.1、给LVGL一个心跳时基
LVGL心跳函数(时基函数):lv_tick_inc(),每隔1ms调用一次;
这个函数对于图形界面的流畅运行比较重要,它令 LVGL 知道执行任务时流逝的时间。
如果 lv_tick_inc() 调用间隔不准确,可能会导致显示卡顿、任务处理不及时。
建议使用TIM产生1ms中断,设置它的中断为高优先级,通过中断函数调用LVGL心跳时基。
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
//回调函数 1ms 触发一次
if(htim == &htim1){
lv_tick_inc(1);//lvgl的1ms中断
}
}
7.2、主函数main配置
在主函数中添加lvgl相关头文件。
#include "lvgl.h"
#include "lv_port_disp.h"
#include "lv_port_indev.h"
#include "lv_demo_keypad_encoder.h"
然后在主函数中添加初始化函数。
lv_init();
lv_port_disp_init(); // lvgl显示接口初始化,放在lv_init()的后面
lv_port_indev_init(); // lvgl输入接口初始化,放在lv_init()的后面
//示例1
//lv_demo_keypad_encoder();
//示例2 创建按钮
create_button();
HAL_TIM_Base_Start_IT(&htim1); // 启动1ms的定时器
然后在while循环里面 调用lvgl事务处理函数 lv_task_handler() 。
lv_task_handler(); // lvgl的事务处理
最后main函数的样式如下所示。
7.3、一个按钮效果展示
完成后,最终显示是这个样子的:
8.官方显示例程配置
打开 llv_demo_keypad_encoder.h文件 ,对以下内容进行修改,以启用此文件。
- 第16行,原:#include "../lv_demos.h",修改为:#include "lv_demos.h"
完成后,是这个样子的:
然后在 lv_conf文件 里,首先打开使能demo的宏,如下所示。
9.其它配置 参考链接
https://blog.youkuaiyun.com/mucherry/article/details/126685909?spm=1001.2014.3001.5501
https://openatomworkshop.youkuaiyun.com/6645ae51b12a9d168eb6c98d.html