如何一步一步地优化LVGL的丝滑度

经过一番周折将LVGL移植到了STM32F407单片机上,底层驱动的LCD是st7789,移植时的条件和环境如下:

●LVGL用的是单缓冲,一次刷新10行;

●刷新函数用的是最原始的一个一个打点的方式;

●ST7789底层发送数据用的是软件spi;

在这些环境下,刷屏就是在拉窗帘,特别慢。

接下来,一步一步地进行优化。

软件SPI→硬件SPI

将硬件SPI改成软件SPI,其实效果并没有什么提升,甚至可以说毫无改进。

注意,这里SPI虽然只用发送,但是接收的代码也不能省略,要不然没效果,千万注意。

虽然硬件SPI相比软件SPI没什么改善,但是硬件SPI可以结合DMA使用。

硬件SPI+DMA

结合LCD屏幕的指针自增进行区域批量赋值,不再一个一个地打点了,而是一次性填充整个区域。

Lvgl的打点调用如下

刷屏函数如下

使用DMA之后,效果提升比较明显,页面切换几乎是瞬间完成,但是还是有闪烁的感觉。

这里有一些问题需要注意下。

不知道为什么,DMA操作8位时能用,操作16位时就不好用了,虽然也把spi和DMA都改成了操作16位,还是不行,所以暂时使用8位;

理论上来说SPI的位数和DMA的位数应该是独立的,一个是发送的字节单位,一个是搬运的字节单位;暂时没搞明白,就统一使用8位吧。

另外,spi的时钟不能太低

估计是太慢的话,spi发送的速度跟不上DMA搬运数据的速度,spi的数据会被冲掉;

再就是SPI的发送和DMA的发送是可以共存的。

ST7789的驱动里涉及到发送指令和发送数据,如果是一次性的数据发送,可以使用DMA,也可以使用SPI

使用spi发送

使用dma发送

考虑到使用DMA来刷新屏幕数据可以结合lvgl的缓冲,所以上面选用spi的发送方式,然后DMA专门用来刷数据;

前面我是独立于lvgl,在LCD的驱动里给DMA专门又开了个内存空间

但其实,可以直接使用lvgl开辟的显存空间,重复申请就浪费了加倍的空间了,也省去了数据复制的步骤了。

但这样又有个问题,那就是颜色像素是个16位的数组,我DMA操作的是8位的数据,前面说了,DMA操作16位的不知道为啥不好使,所以这里面肯定要有些转化,或者解决DMA不能搬运16位数据的原因。怎么办呢?

继续往下看。

SPI+DMA+LVGL双缓冲

参考:LVGL非全尺寸双显存—SPI+DMA(中断刷新) - 哔哩哔哩

配置lvgl为双缓冲

注意下面的别忘了同步修改。

然后将上面三个静态变量的声明放到外面去,因为这里是在函数内部,属于局部静态变量,后面需要全局使用,就会识别不到,因此要上升成全局变量。

在使用LVGL的双缓冲时,DMA初始化时的发送地址可以先设置为双缓存的第一个空间,此时,将LCD的初始化函数直接放在lv_port_disp_template.c中,并且传递进入第一个缓冲区的地址。

之前单独为DMA开辟的发送空间可以去掉。

接下来开始改造刷新函数

Lvgl双缓冲的切换是lvgl自动进行的,我们不用去处理指针切换和数据交替填充的操作,只需要在刷新函数里获取对应的颜色数据的地址,就是当前要发送的数据地址,是lvgl已经帮我们切换好了双缓冲的指针。

在disp_flush函数里我们直接填充数据,接口不变。

同时有一个考虑:DMA发送数据时,之前是强行死循环等待DMA发送完成

我们现在将其改成DMA传输完成中断的方式来进行,然后在DMA传输完成中断里通知lvgl进行下一次刷新,也就是将lv_disp_flush_ready(disp_drv);函数放到DMA中断里去,这样就又有了问题,那就是这个通知函数里的disp_drv是个局部变量,想要挪到外部,就得借助一个中间的全局变量,因此,再定义一个全局的变量,类型和disp_drv的类型一致

同时,考虑到DMA一次只能发送一个字节的数据,因此我们将color_p强行转换成8位数据类型的指针。

于是,刷新函数disp_flush如下:

接下来,就要继续改造打点函数了

我们先计算下,DMA一次最多能发送65535个数据,我配置的是8位的,也就是一次最多能发送65535个字节,一个像素2个字节,那么就是说一次最多能发送32767个像素,如果屏幕是320*240的,那么一次最多能发送102行,所以,设置双缓冲时,我们的缓冲大小不要超过102行,我们这里先将缓冲设置成20行,也就是每次刷新,可以直接使用DMA发完,不必让DMA也分次发送。

DMA使能函数调整

另外,别忘了配置DMA的传输完成中断

然后按照上面说过的思路在lv_port_disp_template.c文件中写上DMA的传输完成中断,并在里面放置通知函数。

在这一过程中,其实有个隐含的答案,那就是上面提过的,关于像素是16位的,但是DMA只能处理8位数据的问题。

其实,DMA所识别的起始地址,就是个32位的地址,不管目标数据本身是什么类型,只要把首地址传给DMA即可,DMA从首地址开始,按照DMA配置的位数来搬运数据,DMA并不关心这个地址原来本身是什么类型的数据。

所以,LVGL传过来的是地址,我们只要把地址转成uint32_t然后传递给DMA,DMA就会按照初始化时配置的位数来搬运,它才不管你原来的数据是多少位的。

至此,DMA+LVGL双缓冲已完成,编译下载运行看看效果。

运行后,发现颜色不大对,原来是红绿蓝,现在变成了青紫黄,这种情况,就想到了一个颜色配置项LV_COLOR_16_SWAP,把它改成1。

再编译下载运行

颜色正常,速度也还挺好。

当然,如果想要再快,可以使用全屏幕双缓冲,此时,SRAM空间不够的话就可以将其放在外部SRAM中,用空间来换时间。我这个项目到这里帧率为35,已经够用了,就不再优化了。后续有特别的需要再说吧。

更多优化参考

LVGL显示优化—基本优化 - 哔哩哔哩

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2815616.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

抖音橱窗怎么关闭?

路径:【抖音APP-我-电商带货-全部工具-账号管理-权限与账户-关闭电商权限】关闭橱窗带货权限。 0保、原0粉达人关闭电商权限后,后续均需要满足页面提示要求才可以进行电商权限的开通,建议慎重操作。

2024年阿里云优惠券领取及使用教程_无门槛优惠券

阿里云优惠代金券领取入口,阿里云服务器优惠代金券、域名代金券,在领券中心可以领取当前最新可用的满减代金券,阿里云百科aliyunbaike.com分享阿里云服务器代金券、领券中心、域名代金券领取、代金券查询及使用方法: 阿里云优惠券…

Xinstall助力社交产品,轻松实现用户关系链归因

在如今的社交网络时代,人与人之间的联系变得越来越紧密。社交产品作为连接人与人之间的桥梁,其重要性不言而喻。然而,如何让用户在使用社交产品时更快速地建立起社交联系,一直是社交产品开发者们关注的焦点。 Xinstall作为一款专…

智能销售数据大屏:决胜市场的数字利器

在数字化浪潮席卷全球的今天,数据已经成为企业决策的核心要素。尤其对于销售团队来说,如何快速、准确地把握市场动态,分析客户行为,成为决定胜负的关键。而智能销售数据大屏,正是这样一款能够帮助企业洞察市场脉络、决…

如何用GPT高效地处理文本、文献查阅、PPT编辑、编程、绘图和论文写作?

原文链接:如何用GPT高效地处理文本、文献查阅、PPT编辑、编程、绘图和论文写作?https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247594986&idx4&sn970f9ba75998f2dd9fa5707d1611a6cc&chksmfa82320dcdf5bb1bdf58c20686d4eb209770e68253ed90d…

StarRocks实战——滴滴OLAP的技术实践与发展方向

原文大佬的这篇StarRocks实践文章整体写的很深入,介绍了StarRocks数仓架构设计、物化视图加速实时看板、全局字典精确去重等内容,这里直接摘抄下来用作学习和知识沉淀。 目录 一、背景介绍 1.1 滴滴OLAP的发展历程 1.2 OLAP引擎存在的痛点 1.2.1 运维…

高通 AI Hub 上手指南

文章介绍 2月26日,高通在2024年世界移动通信大会(MWC2024)上发布高通AI Hub, AI Hub 简化了AI 模型部署到边缘设备的过程。可以利用AI-hub云端托管 Qualcomm 设备上,在几分钟内完成模型的优化、验证和部署。本文以Pyto…

老卫带你学---leetcode刷题(103. 二叉树的锯齿形层序遍历)

103. 二叉树的锯齿形层序遍历 问题 给你二叉树的根节点 root ,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。 示例 1: 输入&a…

优先级队列介绍和模拟实现

个人主页:Lei宝啊 愿所有美好如期而遇 Container就是适配器,也就是说这个优先级队列的底层就使用vector,当然,我们也可以使用deque来适配,但是对于优先级队列来说,效率是低于vector的,因为优先…

【前端素材】推荐优质在线家具电商Bazu平台模板(附源码)

一、需求分析 1、系统定义 家具电商平台是指专门销售家具产品的在线电子商务平台。这些平台专注于家具类商品的销售和服务,为消费者提供方便快捷的购买体验。 2、功能需求 家具电商平台是指专门销售家具产品的在线电子商务平台。这些平台专注于家具类商品的销售…

从此告别手忙脚乱!职场高手管理多微信的技巧

在现在职场,微信已经成为了必不可少的沟通工具之一。然而,随着工作联系人的增多,管理多个微信账号可能会变得一团糟。今天,我们就来分享一些职场高手们管理多个微信账号的技巧,让你从此告别手忙脚乱的状态!…

搜维尔科技:OptiTrack 提供了性能最佳的动作捕捉平台

OptiTrack 动画 我们的 Prime 系列相机和 Motive 软件相结合,产生了世界上最大的捕获量、最精确的 3D 数据和有史以来最高的相机数量。OptiTrack 提供了性能最佳的动作捕捉平台,具有易于使用的制作工作流程以及运行世界上最大舞台所需的深度。 无与伦比…

Python 画 箱线图

Python 画 箱线图 flyfish 箱线图 其他名字 盒须图 / 箱形图 横向用正态分布看 垂直看 pandas画 import pandas as pdimport seaborn as sns import matplotlib.pyplot as plt import pandas as pddf pd.read_csv(sh300.csv) print("原始数据") print(df.he…

ARTS Week 17

Algorithm 本周的算法题为 989. 数组形式的整数加法 整数的 数组形式 num 是按照从左到右的顺序表示其数字的数组。 例如,对于 num 1321 ,数组形式是 [1,3,2,1] 。 给定 num ,整数的 数组形式 ,和整数 k ,返回 整数 n…

【算法历练】动态规划副本—路径问题

🎬慕斯主页:修仙—别有洞天 ♈️今日夜电波:宙でおやすみ 1:02━━━━━━️💟──────── 2:45 🔄 ◀️ ⏸ ▶️ ☰ &#…

在Node.js中如何实现用户身份验证和授权

当涉及到构建安全的应用程序时,用户身份验证和授权是至关重要的一环。在Node.js中,我们可以利用一些流行的库和技术来实现这些功能,确保我们的应用程序具有所需的安全性。本篇博客将介绍如何在Node.js中实现用户身份验证和授权。 用户身份验…

《真象还原》读书笔记——第八章 内存管理系统(字符串操作、位图定义与实现)

8.1 makefile 8.2 实现 assert 断言 8.2.1 实现开、关中断的函数 kernel/interrupt.c 补充了获取中断状态和设置中断的函数 #include "io.h" #include "interrupt.h" #include "stdint.h" #include "global.h" #include "prin…

Navicat Premium创建MySQL存储过程

1、点击“函数”,新建函数; 2、选择“过程”,输入存储过程名称,点击完成即可,可以跳过参数的设置; 3、编写存储过程的代码,保存; CREATE DEFINERrootlocalhost PROCEDURE insertuser…

【DDD】学习笔记-领域驱动设计对持久化的影响

资源库的实现 如何重用资源库的实现,以及如何隔离领域层与基础设施层的持久化实现机制,具体的实现还要取决于开发者对 ORM 框架的选择。Hibernate、MyBatis、jOOQ 或者 Spring Data JPA(当然也包括基于 .NET 的 Entity Framework、NHibernat…

​LeetCode解法汇总2673. 使二叉树所有路径值相等的最小代价

目录链接: 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目: https://github.com/September26/java-algorithms 原题链接:. - 力扣(LeetCode) 描述: 给你一个整数 n 表示一棵 满二叉树 里面节…