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/portingMiddlewares/lvgl/src/coreMiddlewares/lvgl/src/drawMiddlewares/lvgl/src/extraMiddlewares/lvgl/src/fontMiddlewares/lvgl/src/gpuMiddlewares/lvgl/src/halMiddlewares/lvgl/src/miscMiddlewares/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 0HAL设置/* 输入设备的读取周期(以毫秒为单位) */
#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:螺旋矩阵||
题目描述: 给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 示例 1: 输入:n 3 输出:[[1,2,3],[8,9,4],[7,6,5]]示例 2: 输入&am…...
codeforces (C++ In Love )
题目: 翻译: 思路: 1、在一个集合中有多组线段,如果有不相交的两组线段,则输出YES,否则输出NO。 2、每次操纵可以选择增加一组线段或者删除一组线段后,输出YES或者NO。 3、用flag标记该线段是否…...
【python】py文件全自动打包成spec文件
说明: 自动获取当前根目录下所有py文件生成spec文件,直接运行pyinstaller进行打包即可。直接打包成单执行文件。 直接上代码 import ospathex []def recursion(path, main):if path[:1] ! /:path /listpath os.listdir(path)for item in listpath:if…...
YOLOv5-调用官方权重进行检验(目标检测)
🍨 本文为[🔗365天深度学习训练营学习记录博客 🍦 参考文章:365天深度学习训练营-第7周:咖啡豆识别(训练营内部成员可读) 🍖 原作者:[K同学啊 | 接辅导、项目定制](https…...
springMVC中统一异常处理@ControllerAdvice
1.在DispatcherServlet中初始化HandlerExceptionResolver 2.controller执行完成后执行processDispatchResult(processedRequest,response,mappedHandler,mv,dispatchException),有异常则处理异常 3.ExcepitonHandlerExceptionResolver中执行方法doResolveHandlerMethodExceptio…...
【Java】<泛型>,在编译阶段约束操作的数据结构,并进行检查。
个人简介:Java领域新星创作者;阿里云技术博主、星级博主、专家博主;正在Java学习的路上摸爬滚打,记录学习的过程~ 个人主页:.29.的博客 学习社区:进去逛一逛~ JAVA泛型 泛型介绍: ①泛型&#…...
解决谷歌学术bib信息不全的问题
在我们撰写学术论文时,经常需要引用参考文献。如果用latex撰写论文,势必会用到文献的bib信息,大部分的教程都会告诉我们去google scholar上去搜索。 一、问题描述 搜索一篇文章,然后选择cite,再选择bib。 很明显&…...
初始Redis 分布式结构的发展演变
目录 Redis的特点和使用场景 分布式系统的引入 单机系统 分布式系统 应用服务器的增多(处理更多的请求) 数据库读写分离(数据服务器的增多) 引入缓存 应对更大的数据量 业务拆分:微服务 Redis的特点和使用场景 我们先来…...
关于动态内存管理中的常见练习题
文章目录 前言练习1:练习2:练习3:练习4: 前言 学习完C语言中的动态内存管理,大家开始利用动态内存管理来去开辟空间,经过一顿狂敲代码后,发现了问题,程序要么崩掉,要么运…...
冒泡排序、插入排序、选择排序和快速排序的原理
下面是对冒泡排序、插入排序、选择排序和快速排序的原理的简要解释: 冒泡排序(Bubble Sort):冒泡排序是一种简单的排序算法。它通过多次迭代比较相邻的元素,并交换它们的位置,使得较大(或较小&…...
VB.NET之SqlCommand详解
目录 一.前言 二.SqlCommand的背景方法 1.构造函数 2.属性 3.方法 三.SqlCommand的使用实例 1.创建SqlCommand对象 2.执行SQL查询语句 3.执行存储过程 四.总结 一.前言 VB.NET的SqlCommand是ADO.NET的一部分,主要用于执行SQL语句并返回受影响的行数、查询…...
.NET主流的ORM框架 2023年
1. Entity Framework Entity Framework是Microsoft开发的一款强大的ORM框架。适用于.NET开发,支持多种数据库,并提供了广泛的文档和教程。Entity Framework基于面向对象的数据模型,使用LINQ进行查询。它的强大功能和易用性使得它成为.NET开发…...
第三节——Vue 基础语法
vue语法分为选项是API(Option api)和组合式api(Composition Api),我们以选项式Api入门 一、基本构成 template、script、style三部分构成。template可以理解成编写html的地方,script编写逻辑js的地方,sty…...
3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...
屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
莫兰迪高级灰总结计划简约商务通用PPT模版
莫兰迪高级灰总结计划简约商务通用PPT模版,莫兰迪调色板清新简约工作汇报PPT模版,莫兰迪时尚风极简设计PPT模版,大学生毕业论文答辩PPT模版,莫兰迪配色总结计划简约商务通用PPT模版,莫兰迪商务汇报PPT模版,…...
如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...














