当前位置: 首页 > news >正文

STM32进行LVGL裸机移植

本文的移植参考的是正点原子的课程《手把手教你学LVGL图形界面编程》

基于该课程和《LVGL开发指南_V1.3》“第二章 LVGL 无操作系统移植”,然后结合自身的实际情况进行整理。

先根据自己的习惯,创建基础的单片机工程,然后在APP业务层和DRIVER驱动层之间加上MIDDLEWARE层,在这一层中加入lvgl。

另外,这里还有句话:

所以如果用到lvgl,尽可能使用裸机开发。

基于LVGL版本V8.2。

先看下移植要求

这个图形缓冲区的意义是,不会来一个点就刷新一次,而是至少缓冲到一行之后再刷新,防止画面不断闪烁卡顿,效率更高。所以才要求>水平分辨率像素。缓冲区其实就是个数组,数组大小,至少是一行像素所占用字节的大小,假如屏幕大小是300*240,所用的颜色是16位的,也就是一个像素点占两个字节,那么数组大小就要求至少是300*2=600字节大小。

如果想要更流畅,就建议大于1/10屏幕总像素。也就是300*240/10*2=14400字节,也就是15k字节左右。(貌似对内存要求有点高,那么点内存好像不够用呀???待解决。)

另外注意要勾选C99,要不然编译时会报很多错误。

优化LVGL运行效果的方法

关键点其实就是:缩短图像刷新所需要的时间。

注意:内部SRAM会比外部SRAM快很多,原则上只有内部SRAM不够用的情况下才会使用外部的SRAM。

接下来开始移植……

1、获取处理好的源码

不要重复造轮子,无需自己精简文件。

直接下载正点原子的A盘里的“程序源码”,打开“扩展例程”里的“LVGL例程”,打开以下路径:LVGL例程1 无操作系统移植\Middlewares,将内部的LVGL拿过来放在自己所建的基础工程的MIDDLEWARE目录下,并且,删除LVGL中的GUI_APP,因为我们实际开发中不必使用例程来查看效果。

2、添加到工程

直接查看《LVGL开发指南_V1.3》“第二章 LVGL 无操作系统移植”这里开始的一段内容:

第31页,搜索关键字:3. 添加工程分组、 LVGL 源文件
只需到这里即可结束。
注意,keil只有两级目录,新建分组时可以直接输入全路径
最后的结果显示如下:
这里写下来,后面直接拿来复制即可。
Middlewares/lvgl/example/porting
Middlewares/lvgl/src/core
Middlewares/lvgl/src/draw
Middlewares/lvgl/src/extra
Middlewares/lvgl/src/font
Middlewares/lvgl/src/gpu
Middlewares/lvgl/src/hal
Middlewares/lvgl/src/misc
Middlewares/lvgl/src/widgets

3、配置显示屏驱动

该部分配置步骤如下:

注意,因为上面使用的是正点原子整理过后的文件,所以,很多地方已经是现成的,我们要做的就是在调用我们自己函数的地方给替换掉即可。

不过,为了加深印象,还是做个简单的过程记录吧。

第一步(现成的):

修改条件编译指令,对应的头文件也要改

第二步(需要我们操作):

将lcd的驱动头文件包含到刚才的lvgl显示文件lv_port_disp_template.c中

第三步(需要我们操作):

在lv_port_disp_template.c里找到lv_port_disp_init函数,里面调用了disp_init函数,跳转到disp_init函数中,写入我们自己的屏幕初始化函数,并设置为横屏(可选)

第四步(需要修改分辨率大小):

配置图形单缓冲、双缓冲(要用DMA)或者全缓冲;

单缓冲为最常用的,V8.2版本双缓冲相对单缓冲提升效果不明显,全缓冲对内存要求太高。

缓冲策略是:缓冲区大小是屏幕横向分辨率*10,也就是一次刷新10行。如果效果不太理想,可以尝试增大一次刷新的行数,也就是修改10这个参数。

注意,这里的MY_DISP_HOR_RES宏定义表示水平分辨率大小,有的版本没有给我们定义,所以需要我们在该文件前面自行定义一下。

比如:

#define MY_DISP_HOR_RES 320

另外还有个垂直分辨率的宏MY_DISP_VER_RES,也可以一并定义了。

第五步(需要我们操作):

将刚才的那个函数再往下拉就能找到分辨率设置的地方

分别对应水平分辨率和垂直分辨率,直接填入即可。

第六步,配置打点函数

在刚才的文件中,找到函数disp_flush,在里面调用我们自己的打点函数。

打点函数通常有5个参数,也就是起始坐标,结束坐标,要打点的颜色。

从disp_flush的形参中获取当前的参数值即可,如下所示:

lcd_color_fill(area->x1, area->y1, area->x2, area->y2, (uint16_t *)color_p);

最后,在main函数中初始化时调用函数lv_port_disp_init进行初始化即可。

4、配置输入设备(可选)

如果不需要输入设备,直接保持条件编译指令为#if 0即可。

如果需要,则按步骤配置即可。

本人因开发工程时暂不需要输入设备,所以此步骤暂且略过。

5、 为LVGL提供任务处理的时基

在自己的定时器驱动中创建一个1ms的定时器,然后在自己的app_timer的中断处理函数中,调用LVGL的 lv_tick_inc 函数:lv_tick_inc(1); /* lvgl 1ms 心跳 */

该函数需要包含如下头文件:#include "lvgl.h"

直接调用即可,无需其他内容。

6、main函数中需要的内容

包含必要的头文件。

#include "lvgl.h"
#include "lv_port_indev_template.h"(可选)
#include "lv_port_disp_template.h"

在main函数中初始化时对lvgl进行初始化;

lv_init();                          /* lvgl系统初始化 */
lv_port_disp_init();         /* lvgl显示接口初始化,放在lv_init()的后面 */
lv_port_indev_init();       /* lvgl输入接口初始化,放在lv_init()的后面 */

定时处理 LVGL 任务。用户需要每隔几毫秒调用一次 lv_timer_handler 函数,以处理 LVGL 相关的任务,该函数可以放在 while 循环中,但延时不宜过大,需要确保 5 毫秒以内。

这里有个问题,那就是正点原子教程中直接delay延时了5ms,我们实际使用时,不可能直接在主循环里面进行延时的,所以我们就直接调用即可。

7、编写测试代码

lv_obj_t *switch_obj = lv_switch_create(lv_src_act());

lv_obj_set_size(switch_obj, 120, 60);

lv_obj_align(switch_obj, LV_ALIGN_CENTER, 0, 0);

如果没问题,可以看到界面中会有个切换按钮。

注意:

编译时,如果提示内存问题,可以尝试调整LVGL管理的内存空间。

因为LVGL默认管理的内存空间是48K字节,这其实是蛮大的,如果你单片机的内存都没有48K,那LVGL就肯定会报错。

如何调整?

在lv_conf.h中可以找到MEMORY SETTINGS部分的内容,将48的值改小一些,至少保证自己的单片机能提供这么多内存空间。

配置文件lv_conf.h

lv_conf.h 是一个用户级别的文件,它不属于内核的部分,因此,在不同的工程中,该文件有可能存在差异。

lv_conf.h 文件具有两大功能:

(1) 配置功能:内存、屏幕刷新周期、输入设备的读取周期,等等;
(2) 裁剪功能:使能 / 失能某些功能,有效地优化 Flash 的分配。
lv_conf.h 文件的内容可划分为 10 个板块,如下表所示:
配置项还是蛮多的,这里记录下常用的配置项
总开关
#if 1 /*Set it to "1" to enable content*/
颜色设置
/* 颜色深度: 1(每像素1字节), 8(RGB332), 16(RGB565), 32(ARGB8888) */
#define LV_COLOR_DEPTH                      16
内存设置
/* 0: 使用内置的 `lv_mem_alloc()` 和 `lv_mem_free()`*/
#define LV_MEM_CUSTOM                       0
HAL设置
/* 输入设备的读取周期(以毫秒为单位) */
#define LV_INDEV_DEF_READ_PERIOD            4     /*[ms]*/
字库设置
/* 始终设置默认字体 */
#define LV_FONT_DEFAULT                     &lv_font_montserrat_14
后续控件和特别功能等等,如果不需要就置0.
这几部分正点原子为了教学方便,好多都开了,实际中可选择性关闭。
更多详细内容直接参考《LVGL开发指南_V1.3》“ 第五章 LVGL 移植的相关知识

补充::::::::

外部SRAM、自定义的内存管理算法

需要时再来研究

第9讲 基础篇-LVGL移植(外部SRAM)_哔哩哔哩_bilibili

第10讲 基础篇-LVGL移植(内存管理)_哔哩哔哩_bilibili

DMA2D

DAM2D需要硬件支持,如果板子不支持DMA2D,则无法使用。

首先了解下什么是DMA2D:STM32的“GPU”——DMA2D实例详解 - 知乎

根据上面的文章可知,DMA2D可以理解成专门用来处理2D图像的DMA,类似于“GPU”。

因为STM32F103和STM32F407没有该外设,所以此处不赘述。

F429单片机就支持:STM32F429的图形加速器DMA2D的基础知识

以后有需要再研究。

第11讲 基础篇-LVGL移植(DMA2D)_哔哩哔哩_bilibili

相关文章:

STM32进行LVGL裸机移植

本文的移植参考的是正点原子的课程《手把手教你学LVGL图形界面编程》 基于该课程和《LVGL开发指南_V1.3》“第二章 LVGL 无操作系统移植”,然后结合自身的实际情况进行整理。 先根据自己的习惯,创建基础的单片机工程,然后在APP业务层和DRIVE…...

python解析robot framework的output.xml并生成html

一、用pyh模块解析stat结点数据(output.py) #codingutf-8import xml.dom.minidom import xml.etree.ElementTree#打开xml文档 dom xml.dom.minidom.parse(./ui/output.xml);root2 xml.etree.ElementTree.parse(./ui/output.xml) #得到文档元素对象 ro…...

【RuoYi移动端】uni-app中的单击和双击事件

1、单击事件: click"enterpriseSelect" 2、双击事件: touchend"userinfo"...

使用 conda 在 Ubuntu 16.04 上安装 Python 3.9 的步骤:和 VSCode配置

一、使用conda在 Ubuntu 16.04 上安装 Python 3.9 的步骤: 当然可以,conda 是一个非常强大的包管理器,它可以方便地管理不同版本的 Python 和各种库包。以下是使用 conda 在 Ubuntu 16.04 上安装 Python 3.9 的步骤: 1. 安装 Miniconda Miniconda 是 Anaconda 的轻量级版…...

spring6-国际化:i18n | 数据校验:Validation

文章目录 1、国际化:i18n1.1、i18n概述1.2、Java国际化1.3、Spring6国际化1.3.1、MessageSource接口1.3.2、使用Spring6国际化 2、数据校验:Validation2.1、Spring Validation概述2.2、实验一:通过Validator接口实现2.3、实验二:B…...

【MicroSoft Edge】格式化的显示JSON格式的数据

当我们没有进行任何操作的时候,默认浏览器给我们展示的JSON的数据是这样的: 看着十分不便。 解决方案: 首先点击 MicroSoft Edge 浏览器右上角的三点,如何选择扩展 点击 获取Microsoft Edge 扩展 搜索 JSONView,第一…...

【c++】跟webrtc学std array 2:TaskExecutorMap单例用法

D:\XTRANS\m98_rtc\ndrtc-webrtc\src\base\task\task_executor.ccstd array实现的map:TaskExecutorMap // Maps TaskTraits extension IDs to registered TaskExecutors. Index |n| // corresponds to id |n - 1|. using TaskExecutorMap =std::array<TaskExecutor*, Task…...

力扣每日一题59:螺旋矩阵||

题目描述&#xff1a; 给你一个正整数 n &#xff0c;生成一个包含 1 到 n2 所有元素&#xff0c;且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;[[1,2,3],[8,9,4],[7,6,5]]示例 2&#xff1a; 输入&am…...

codeforces (C++ In Love )

题目&#xff1a; 翻译&#xff1a; 思路&#xff1a; 1、在一个集合中有多组线段&#xff0c;如果有不相交的两组线段&#xff0c;则输出YES&#xff0c;否则输出NO。 2、每次操纵可以选择增加一组线段或者删除一组线段后&#xff0c;输出YES或者NO。 3、用flag标记该线段是否…...

【python】py文件全自动打包成spec文件

说明&#xff1a; 自动获取当前根目录下所有py文件生成spec文件&#xff0c;直接运行pyinstaller进行打包即可。直接打包成单执行文件。 直接上代码 import ospathex []def recursion(path, main):if path[:1] ! /:path /listpath os.listdir(path)for item in listpath:if…...

YOLOv5-调用官方权重进行检验(目标检测)

&#x1f368; 本文为[&#x1f517;365天深度学习训练营学习记录博客 &#x1f366; 参考文章&#xff1a;365天深度学习训练营-第7周&#xff1a;咖啡豆识别&#xff08;训练营内部成员可读&#xff09; &#x1f356; 原作者&#xff1a;[K同学啊 | 接辅导、项目定制](https…...

springMVC中统一异常处理@ControllerAdvice

1.在DispatcherServlet中初始化HandlerExceptionResolver 2.controller执行完成后执行processDispatchResult(processedRequest,response,mappedHandler,mv,dispatchException),有异常则处理异常 3.ExcepitonHandlerExceptionResolver中执行方法doResolveHandlerMethodExceptio…...

【Java】<泛型>,在编译阶段约束操作的数据结构,并进行检查。

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ JAVA泛型 泛型介绍&#xff1a; ①泛型&#…...

解决谷歌学术bib信息不全的问题

在我们撰写学术论文时&#xff0c;经常需要引用参考文献。如果用latex撰写论文&#xff0c;势必会用到文献的bib信息&#xff0c;大部分的教程都会告诉我们去google scholar上去搜索。 一、问题描述 搜索一篇文章&#xff0c;然后选择cite&#xff0c;再选择bib。 很明显&…...

初始Redis 分布式结构的发展演变

目录 Redis的特点和使用场景 分布式系统的引入 单机系统 分布式系统 应用服务器的增多&#xff08;处理更多的请求&#xff09; 数据库读写分离&#xff08;数据服务器的增多) 引入缓存 应对更大的数据量 业务拆分&#xff1a;微服务 Redis的特点和使用场景 我们先来…...

关于动态内存管理中的常见练习题

文章目录 前言练习1&#xff1a;练习2&#xff1a;练习3&#xff1a;练习4&#xff1a; 前言 学习完C语言中的动态内存管理&#xff0c;大家开始利用动态内存管理来去开辟空间&#xff0c;经过一顿狂敲代码后&#xff0c;发现了问题&#xff0c;程序要么崩掉&#xff0c;要么运…...

冒泡排序、插入排序、选择排序和快速排序的原理

下面是对冒泡排序、插入排序、选择排序和快速排序的原理的简要解释&#xff1a; 冒泡排序&#xff08;Bubble Sort&#xff09;&#xff1a;冒泡排序是一种简单的排序算法。它通过多次迭代比较相邻的元素&#xff0c;并交换它们的位置&#xff0c;使得较大&#xff08;或较小&…...

VB.NET之SqlCommand详解

目录 一.前言 二.SqlCommand的背景方法 1.构造函数 2.属性 3.方法 三.SqlCommand的使用实例 1.创建SqlCommand对象 2.执行SQL查询语句 3.执行存储过程 四.总结 一.前言 VB.NET的SqlCommand是ADO.NET的一部分&#xff0c;主要用于执行SQL语句并返回受影响的行数、查询…...

.NET主流的ORM框架 2023年

1. Entity Framework Entity Framework是Microsoft开发的一款强大的ORM框架。适用于.NET开发&#xff0c;支持多种数据库&#xff0c;并提供了广泛的文档和教程。Entity Framework基于面向对象的数据模型&#xff0c;使用LINQ进行查询。它的强大功能和易用性使得它成为.NET开发…...

第三节——Vue 基础语法

vue语法分为选项是API&#xff08;Option api&#xff09;和组合式api&#xff08;Composition Api&#xff09;,我们以选项式Api入门 一、基本构成 template、script、style三部分构成。template可以理解成编写html的地方&#xff0c;script编写逻辑js的地方&#xff0c;sty…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架&#xff0c;它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用&#xff0c;和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 操作步…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

java 实现excel文件转pdf | 无水印 | 无限制

文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

AtCoder 第409​场初级竞赛 A~E题解

A Conflict 【题目链接】 原题链接&#xff1a;A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串&#xff0c;只有在同时为 o 时输出 Yes 并结束程序&#xff0c;否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...