一、前言


LVGL是一款轻量、多功能的开源嵌入式图形库,内置丰富控件与图形资源,还支持模拟器仿真。本文以STM32CubeMX生成的HAL库代码为基础,介绍LVGL图形库的添加方法,并对比不同控制方式、缓冲模式及刷新频率下的显示效果

在这里插入图片描述


二、LVGL资源网站


● LVGL官网:https://lvgl.io

● LVGL文档:https://docs.lvgl.io/

● LVGL论坛:https://forum.lvgl.io

● LVGL例程:https://docs.lvgl.io/master/examples.html

● LVGL源码、模拟器及其他资源下载:https://github.com/lvgl/

● 百问网(LVGL中文翻译版本):https://lvgl.100ask.net/master/index.html



三、LVGL移植前准备


1、硬件要求


可根据官网最低配置要求及项目实际需求,自主选型适配的MCU与显示屏。本项目选用STM32F103RCT6作为MCU,搭配2.8英寸ILI9341驱动的彩色TFT显示屏,该屏采用4线SPI通信,分辨率为320×240。

2、生成项目代码


使用STM32CubeMX生成HAL库代码,具体详细操作流程可参考文章《【STM32CubeMX】生成HAL库的Keil工程》。本文仅针对硬件SPI与DMA模块的配置步骤进行说明。

(1)硬件SPI:配置SPI需依据ILI9341驱动芯片的时序要求进行参数设置,因本项目仅需处理数据发送,故可按如下图参数配置。所有参数均需严格匹配实际显示屏驱动的时序规范。

在这里插入图片描述

在这里插入图片描述

(2)硬件SPI+DMA:配置DMA时,将发送通道的方向设置为“内存到外设”。由于驱动芯片采用8位数据发送模式,因此需将数据宽度配置为Byte类型。

在这里插入图片描述

NVIC配置使能,且需要DMA的优先级高于SPI。

在这里插入图片描述

3、添加显示函数


打开代码,在生成的初始化函数后添加屏显初始化函数,并根据驱动芯片型号完成对应配置。

在这里插入图片描述

使用HAL库函数修改显示屏写命令和写数据函数。

在这里插入图片描述

函数分析:
(1)显示屏复位完成后,可将片选信号引脚(CS)持续拉低,让驱动芯片保持使能状态,此后无需在每次写入命令和数据前后重复控制片选信号。

(2)同时可在发送写命令前发送写命令前将数据/命令选择引脚(DC/RS)拉低,命令传输完成后直接拉高该引脚并保持状态,后续写入数据前无需再对该引脚做时序切换。

该优化方法通过减少GPIO电平翻转次数提升显示刷新速度,适合对显示速率有要求的场景,若对通信稳定性要求更高,则仍需严格遵循驱动芯片规范,在每次操作前后完整控制各信号引脚的时序。

建议在初始化流程结束后,调用全屏填充函数将屏幕填充为单一颜色,或执行其他基础显示操作,以此直观验证驱动代码的有效性及硬件通信的正常性。



四、LVGL移植步骤


1、LVGL源码下载


LVGL源码可从GitHub获取,建议选用8.3版本。最新版本具备更多控件,但会带来更高的资源占用,需结合项目实际资源情况选择版本。

2、LVGL源码裁剪


源码下载解压后,仅保留下图中的5项内容,其余文件可直接删除。

在这里插入图片描述

同时清理examples文件夹多余文件,仅保留porting子文件夹。

在这里插入图片描述

3、LVGL源码修改


将配置文件重新命名为“lv_conf.h”,打开该文件,将宏定义“#if 0”修改为“#if 1”,开启功能。

在这里插入图片描述

同样修改porting文件夹中的接口代码,找到.h头文件内对应功能的宏定义,将其值修改为1,即可开启该功能模块。


4、LVGL源码添加至工程代码


(1)将以上修改好的LVGL源码添加至工程代码文件夹中。
APPS:存放用户自己编写的UI代码。将LVGL源码中的demos文件夹放入该文件夹。
BSP:存放硬件相关的外设驱动代码。
LVGL:存放LVGL源码。将examples、src文件夹和lv_conf.h、lvgl.h文件放入该文件夹中。
Middlewares:存放中间件代码,如FreeRTOS等。

在这里插入图片描述

根据自己的习惯命名文件夹和放置位置。但需要注意,Middlewares文件夹是STM32CubeMX自动生成的,在每次重新生成工程时被清空或覆盖,导致用户添加的第三方库丢失。为确保代码不丢失,可以将LVGL源码独立放置于STM32CubeMX生成的文件夹外。


(2)打开Keil工程后进入“Manage Project Items”界面,依次新建3个分组(Groups)并添加对应文件。

在这里插入图片描述

其中将lv_conf.h文件放在“LVGL/Porting”路径下,只是方便查看管理,可以不用特意添加到工程分组中。

在这里插入图片描述

修改后的LVGL源码src文件夹内的所有C代码文件都需要添加至“LVGL/Scr”分组,这是因为LVGL有些控件存在相互依赖关系,虽然添加了全部文件,但具体是否参与编译可通过lv_conf.h中的配置选项自行选择


(3)添加完所有C文件后,需要打开Keil的“Options for Target”窗口添加LVGL对应的头文件路径,同时因为LVGL用到了C99标准引入的关键语法和特性,还需要在窗口中勾选开启“C99 Mode”编译选项。

在这里插入图片描述

(4)打开Keil工程中lv_port_disp_template.c文件,添加自行编写的显示屏驱动头文件。

在这里插入图片描述

接着修改显示屏的宽度和高度尺寸。

在这里插入图片描述

LVGL提供了三种不同的缓冲区方案用于控件绘制,使用时只需选择其中一种方案,将另外两种屏蔽,同时根据所选方案对应修改缓冲区的类型配置。

>提升绘制流畅度:</font若单片机RAM空间足够,可以适当增加显示缓冲区的行数;若使用DMA传输,则可以选用双缓冲模式。

在这里插入图片描述

由于显示设备已经在工程初始位置已经完成了初始化,因此disp_init函数无需修改。修改LVGL负责刷新缓冲区内容的disp_flush函数,官方模板提供的打点刷新方式效率较低,需要自行实现一个可以在指定区域批量填充颜色块的函数来完成优化。

在这里插入图片描述

采用硬件SPI传输方案,则可按以下函数填充颜色。

在这里插入图片描述

采用DMA+硬件SPI的传输方案,则需要用到SPI发送完成回调函数;HAL_SPI_TxCpltCallback是HAL库自带的弱定义函数,需要用户自行重写实现该函数功能,DMA传输完成后会进入中断触发该回调,即可在回调中标记传输完成,允许开启下一轮数据传输。如果想要进一步提升CPU的使用率,还可以搭配实时操作系统RTOS运行。

在这里插入图片描述

(5)如果需要使用触摸屏、鼠标、键盘等这类输入设备,则需打开Keil工程中的lv_port_indev_template.c文件,添加自行编写的输入设备驱动头文件,本次移植以触摸屏作为输入设备进行配置。

在这里插入图片描述

在lv_port_indev_init输入设备初始化函数中,仅保留与触摸屏相关的代码,将其余输入设备的代码块全部屏蔽。

在这里插入图片描述

在触摸屏初始化touchpad_init函数中,调用自行编写的触摸屏初始化代码,如果需要做触摸坐标矫正,也可以将相关的代码添加到此处。

在这里插入图片描述

触摸屏读取坐标的touchpad_read函数无需修改,而负责检测触摸状态的touchpad_is_pressed函数,需要添加自行编写的代码,用于判断当前是否存在触摸操作。

在这里插入图片描述

再将读取触摸屏按下时的坐标touchpad_get_xy函数修改。

在这里插入图片描述

(6)打开Keil工程中lv_conf.h文件,根据显示屏修改颜色字节数。颜色显示数据传输的16位数据高八位和低八位的顺序,可以通过宏定义LV_COLOR_16_SWAP是否翻转高低位

在这里插入图片描述

(7)需要添加LVGL心跳时基信号:LVGL需要通过计时感知任务的时间流逝,因此需要每隔合适的间隔在main函数中调用一次lv_task_handler时基函数。间隔时间要设置合适,间隔过大会导致画面停顿、触摸无响应,间隔过小则会不必要地提升CPU占用率。

在这里插入图片描述

(8)最后可以添加官方提供的LVGL示例Demo函数,确认工程编译成功后,将固件下载到开发硬件中查看实际运行效果。



五、LVGL移植补充说明


1、STM32芯片的Flash或RAM资源占用修改


(1)堆栈空间修改,在启动文件中找到Stack_Size修改为LVGL推荐大小。

在这里插入图片描述

(2)LVGL内存池修改,在lv_conf.h文件中找到宏定义LV_MEM_SIZE修改。

在这里插入图片描述

(3)LVGL缓冲区行数修改,上文已经有提过。如果单片机有足够的RAM空间可以适当增加行数,以此减轻屏幕刷新时的“拉窗帘”现象。


2、配置LVGL功能


以下功能都在配置文件lv_conf.h中找到对于宏定义控制LVGL功能启动。

(1)显示CPU使用率和FPS帧数:宏定义LV_USE_PERF_MONITOR

在这里插入图片描述

(2)显示使用内存和内存碎片:宏定义LV_USE_MEM_MONITOR

(3)修改显示刷新周期:宏定义LV_DISP_DEF_REFR_PERIOD

在这里插入图片描述

(4)修改输入设备周期:宏定义LV_INDEV_DEF_READ_PERIOD

(5)光模式与黑暗模式切换:宏定义LV_THEME_DEFAULT_DARK修改,前提是要开启该主题功能。

在这里插入图片描述

3、自定义字库


LVGL官方提供字库生成,根据需要填写内容。
官方链接:https://lvgl.io/tools/fontconverter

在这里插入图片描述


六、测试对比


接下来将针对相同的显示内容,测试对比不同显示控制方式不同LVGL缓冲区配置以及不同刷新频率下的屏幕刷新速度差异。


测试对比: 视频

在这里插入图片描述

运用LVGL图形库进行一个按钮的显示测试。

在这里插入图片描述



七、总结


在STM32上无操作系统移植LVGL图形库的过程中,可能会遇到各类问题,也需使用多种控件,建议多查阅官网资料,其中包含详尽的解释与示例展示,能为移植和控件使用提供有用的参考。





在这里插入图片描述

搜索关注「YouziTech」 ,获取更多内容!

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐