#申请原创#
@21小跑堂
LVGL,全称Light and Versatile Graphics Library,是一款免费的开源的轻量级多功能的嵌入式图形库,能够为任何MCU、MPU及显示设备创建优美的UI界面。 做HMI(人机交互界面)显示屏开发的行业会经常用到LVGL库,作者就通过本文与大家分享一下自己实操的关于LVGL的代码移植和操作,因初识LVGL,也参考了其他大佬的文章,不足之处,还望指正。 大家可以在github链接里下载合适的LVGL的SDK(软件开发套件)版本: https://github.com/lvgl/lvgl
其中v8.3版本是目前广泛使用的版本,当然其他版本也可以。 另外,可以通过CHANGELOG.md文件查看版本更新及修改的日志记录:
下载:
在根目录的lvgl.h头文件里可以查询到版本信息: 主版本号.次版本号.补丁版本号
SDK裁剪:lvgl-release-v8.3文件夹的根目录内容如下:其中需要用到的主要是 3个文件夹+2个头文件,如红色框所示:
查看lvgl.h文件,里面都是使用相对路径包含头文件的,为了使裁剪和移植后的文件能直接使用这些相对路径,我们复制文件时,按以下的目录结构来操作:新建文件夹“lvgl”,将用到的3个文件夹和2个h文件放到里面,如下:
其中:lvgl.h文件:包括所有LVGL用到的头文件,以及读取LVGL固件版本的接口; lv_conf_template.h文件:LVGL配置参数的重要文件,默认为关闭功能;使用时需将其名称更改为lv_conf.h,并开启功能;
修改后如下:
删除lvgl\examples目录下面不需要的文件夹, 只保留porting文件夹;
并将porting文件夹下面的6个文件的文件名上的_template去掉,修改如下:
至此,lvgl文件夹的构架基本完成,并且这个可以复制给各类工程使用。
接下来就可以将其移植到具体的MCU工程中去了。移植后的LVGL目录结构如下,红色方框为需要使用的文件/文件夹:
注册显示功能的相关代码操作1、启用lv_conf.h
2、启用lv_port_disp.h
3、启用lv_port_disp.c
4、添加LCD驱动的头文件在lv_port_disp.c文件里包含你的LCD驱动头文件,目的是让这个C文件可以调用LCD的画点函数,比如:#include “bsp_lcd.h”,查看你的显示屏参数,修改实际像素:
5、选择创建缓存的方式 在lv_port_disp.c文件中,LVGL提供了创建显示缓冲区的3种方式,必须3选1,;在绝大多数情况下,使用第1种方法,即只创建1个缓冲区:
6、关联画点函数 在lv_port_disp.c文件中,找到disp_flush()函数,并调用你的画点函数,比如:
LCD_DrawPoint( x, y, color_p->full) ;
这里给LVGL一个画点函数后,LVGL就能完成需要的显示操作了。至此,显示的注册已经完成。
注册触摸屏功能的相关代码操作1、启用lv_port_indev.h
2、启用lv_port_indev.c
3、添加触摸屏的驱动头文件 在lv_port_indev.c文件中包含触摸屏的驱动头文件,比如:
#include “bsp_touch.h”,这样这个C文件就可以调用触摸屏的触摸状态检测函数、坐标获取函数;
4、注释掉不需要的输入任务注册 在lv_port_indev.c文件中,包含了 5种输入方式的任务注册: 触摸屏
鼠标
键盘
编码器
物理按键
保留触摸屏输入的任务注册,其他4种可以先注释掉;即在lv_port_indev_init函数里,只保留与触摸屏注册任务相关的代码即可; 5、添加触摸检测函数在lv_port_indev.c文件中,找到触摸状态检测函数 touchpad_is_pressed,改成如下:
其中返回FALSE表示未触摸,TRUE表示触摸中。 6、添加坐标获取函数在lv_port_indev.c文件中,找到坐标获取函数 touchpad_get_xy,本函数可以使LVGL能够获取到触摸按下时的x和y坐标,可以改成如下:
至此,触摸屏的注册已经完成。
添加LVGL的文件引用到MCU工程在修改完成LVGL的显示、触摸注册后,即可正式应用LVGL。 1、添加LVGL头文件到工程 可以在main.c头部包含以下三个LVGL的头文件:#include "lvgl.h" // 它为整个LVGL提供了更完整的头文件引用#include "lv_port_disp.h" // LVGL的显示支持#include "lv_port_indev.h" // LVGL的触屏支持 2、初始化LCD、触摸屏比如按以下格式初始化:LCD_Init(); // 初始化 LCDLCD_SetDir(1); // 设置LCD的显示方向:横屏touch_Init(xLCD.width, xLCD.height, xLCD.dir); // 初始化触摸屏 注意:也可以在lv_port_disp.c文件的disp_init函数里填入LCD的初始化函数,在lv_port_indev.c文件的touchpad_init函数里填入触摸屏的初始化函数,两种方式均可,自己选择。
3、初始化LVGL、LCD和触摸屏在硬件的初始化代码之后,进行LVGL的初始化: lv_init(); // LVGL 初始化lv_port_disp_init(); // 注册LVGL的显示任务lv_port_indev_init(); // 注册LVGL的触屏检测任务4、显示按钮控件、文本控件在LVGL的初始化之后,可以添加LVGL控件,用来测试LVGL的显示:添加一个按钮;为按钮添加文本;添加一个独立的标签文本;代码如下:
LVGL的心跳和任务刷新LVGL需要处理两个时间任务:心跳和任务刷新1、心跳间隔1ms,精准的调用时基函数(心跳函数)lv_tick_inc(),让LVGL精确地知道时间的流逝,对于图形界面的流畅运行比较重要;如果心跳函数调用间隔不准确,可能会导致显示卡顿、任务处理不及时;建议使用MCU的外设定时器外设产生1ms中断,并设置其优先级为高,通过中断函数调用LVGL的心跳函数。心跳函数的定义如下:
被调用如下:
另外,其实你也可以在LVGL的官网https://lvgl.io查询到相关资料:
2、任务刷新间隔5ms左右,调用周期性函数 lv_timer_handler(),其作用是检查所有注册任务的时间戳,执行那些已经到期的任务,如屏显刷新、触控、定时器事件等。简单地理解,就是每隔5ms左右让LVGL刷新(活)一次,定期检查所有已注册任务的时间戳;可以在main.c的while(1)循环里每隔5ms调用一次周期性函数;由于该函数的执行时间有点长,为避免霸占中断资源,不要直接在定时器中断里调用它;在LVGL的8.1.0版本里,该函数还被封装了一层,在 lv_api_map.h文件中,如下所示:
因此,使用时直接调用lv_task_handler()函数即可,如下:
控件的事件添加、响应处理 LVGL的学习,其实可以分为两个部分: 1、界面绘制 LVGL的界面绘制,更常规的操作其实是先使用可视化工具进行设计,再把界面工程移植到MCU; 2、事件处理 这块逻辑在MCU代码里直接编写; 举例说明事件添加和响应处理:
在原来添加按钮的代码后面,增加一行,为控件添加事件: 参数解释: myBtn:要添加回调函数的控件的名称,不限于按钮; myBtn_event:事件响应时,LVGL调用的为对象分配的回调处理函数,需要自行手动编写; LV_EVENT_CLICKED:点击事件;不同的控件,有不同的事件类型(见lv_event_code_t); NULL:传递给回调函数的可选用户数据,这里暂时不用.
添加事件的函数简介如下: 手动编写的事件响应处理函数: 功能:按一次按钮,按钮上的文本数字加1后显示;
“Button 1” “Button2” ……“Button n” 删除事件:
可以通过以下两种方法对事件进行删除: 关于LVGL的SDK文件介绍,详细使用方法和具体应用操作等,可以在官网上学习,资料还是比较丰富的:
|