LVGL 优化帧率技巧

2023-05-16

目录标题

  • 前文
  • 未优化版本
  • LVGL帧率限制
  • 刷屏方法效率
  • 代码优化等级
  • 编译器版本
  • LVGL显存
    • 单buffer
    • 非全尺寸双buffer
    • 全尺寸双buffer

本文只针对当时的LVGL v7,LVGL迭代过程中变化较大,部分接口有可能做调整。本文仅供参考

前文

LVGL——PC模拟器仿真模拟+VS2017
f429 discovery开发版 LVGL移植(带操作系统)
在F429平台上尝试LVGL过程中,总结出几种优化提高帧率的方法
这里我们直接用官方测试例程 benchmark做直观的帧率展示。

未优化版本

这里我以f429 discovery开发版 LVGL移植(带操作系统)这里的源代码做初始版本。

LVGL帧率限制

首先,LVGL是有一个帧率刷新周期的宏定义,LVGL会通过LVGL内部的tick,定时去刷屏幕,也就是说该宏定义限定了LVGL刷屏帧率的上限,默认满帧33帧。

#define LV_DISP_DEF_REFR_PERIOD 30 /[ms]/

这里我们直接设10ms刷新一次,满帧100帧。

刷屏方法效率

尽量使用dma之类的刷屏,不要使用画点函数,例如以下,效率很低。

    for(y = area->y1; y <= area->y2; y++) {
        for(x = area->x1; x <= area->x2; x++) {
            put_px(x, y, *color_p)
            color_p++;
        }
    }

我们初始版本使用DMA2D刷屏。

代码优化等级

CUBEMX生成的项目默认是arm compiler v5 + -O3 ,是性能较好的配置,不过大家自己移植lvgl未使用cubemx等代码生成工具,可能为了调试方便使用了O0优化等级,这个影响很大,429平台上帧率提升高达33%,-o3需要注意一下代码优化问题,善用volatile关键字。

arm compiler v5 + -O0 权重 FPS 332
在这里插入图片描述
arm compiler v5 + -O3 权重 FPS 446

在这里插入图片描述
帧率提升很明显!

编译器版本

本人试过arm compiler V6 + lvgl + freertos(freertos 需要改用 gcc的 port文件),效果很差。

  • LVGL栈使用设置需要比V5大,V5给2k就差不多了,v6只2k会栈溢出
  • 帧率拙计,同样benchmark测试帧率,权重FPS只有100出头

arm compiler v6 + -O3 权重 FPS 181
在这里插入图片描述
尽量用arm compiler5 吧,帧率损失有点大。

LVGL显存

LVGL其实提供了三种显存类型。三种分别对应不同环境吧,都可以试试 。

单buffer

画面会被拆分成buffer的size大小,分块刷新,当只有局部刷新时,比如说点击了一个按钮按钮变高亮,那么他就只会刷局部画面。

官方推荐大小 1/10 screen size,拆分太小,刷屏接口又慢的话,不仅帧率低,还会有感人的拉窗帘。

static lv_disp_buf_t disp_buf;
static lv_color_t buf[LV_HOR_RES_MAX * LV_VER_RES_MAX / 10];                     /*Declare a buffer for 1/10 screen size*/
lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * LV_VER_RES_MAX / 10);    /*Initialize the display buffer*/

当然buffer全屏大小最好。
arm compiler v5 + -O3 + 全屏显存 权重 FPS 500在这里插入图片描述

非全尺寸双buffer

顾名思义,两个buffer,实际上就是PING-PONG模式,这种情况适合有dma或者其他显存加速设备的芯片,在一块buffer使用dma等外设后台刷屏时,lvgl可以再前台渲染显示进另一块显存,也就是说渲染和刷屏并发执行,理论是比单显存要好的,不过跟硬件和屏幕大小有关,具体要实测。

      static lv_disp_buf_t draw_buf_dsc_2;  //两个半屏缓存
      static lv_color_t draw_buf_2_1[LV_HOR_RES_MAX * LV_VER_RES_MAX/2];                        /*A buffer for 10 rows*/
      static lv_color_t draw_buf_2_2[LV_HOR_RES_MAX * LV_VER_RES_MAX/2];                        /*An other buffer for 10 rows*/
      lv_disp_buf_init(&draw_buf_dsc_2,draw_buf_2_2, draw_buf_2_1, LV_HOR_RES_MAX *LV_VER_RES_MAX/2);   /*Initialize the display buffer*/

另外disp_flush刷屏接口也要改成中断回调的形式,如果poll死等dma1传输结束,那就没有dma不占cpu的意义了。

static void disp_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p)
{
    /*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/
    int16_t w = (area->x2 - area->x1 + 1);
    int16_t h = (area->y2 - area->y1 + 1);
    uint32_t size = w * h;
   disp_drv_p = disp_drv;
  /*##-1- Configure the DMA2D Mode, Color Mode and output offset #############*/ 
   hdma2d.Init.Mode         = DMA2D_M2M;
   hdma2d.Init.ColorMode    = DMA2D_OUTPUT_RGB565;
   hdma2d.Init.OutputOffset = (LV_HOR_RES_MAX-w);     
  
   /*##-3- Foreground Configuration ###########################################*/
   hdma2d.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
   hdma2d.LayerCfg[1].InputAlpha = 0xFF;
   hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB565 ;
   hdma2d.LayerCfg[1].InputOffset = 0;

   hdma2d.Instance          = DMA2D; 
  
   /*##-4- DMA2D Initialization ###############################################*/
   if(HAL_DMA2D_Init(&hdma2d) != HAL_OK) 
   {
     /* Initialization Error */
     Error_Handler(); 
   }
  
     if(HAL_DMA2D_ConfigLayer(&hdma2d, 1) != HAL_OK) 
   {
     /* Initialization Error */
     Error_Handler(); 
   }
  
   /*##-5- Start DMA2D transfer ###############################################*/  
  
   if(HAL_DMA2D_Start_IT(&hdma2d, (uint32_t)color_p, (uint32_t) (hltdc.LayerCfg[0].FBStartAdress) + 2*(LV_HOR_RES_MAX *area->y1 + area->x1), w, h) != HAL_OK)
   {
     /* Initialization Error */
     Error_Handler(); 
   }
//	HAL_DMA2D_PollForTransfer(&hdma2d,100);
//    lv_disp_flush_ready( disp_drv_p);

}
void DMA2D_IRQHandler(void)
{
  /* USER CODE BEGIN DMA2D_IRQn 0 */
  lv_disp_flush_ready( disp_drv_p);
  /* USER CODE END DMA2D_IRQn 0 */
  HAL_DMA2D_IRQHandler(&hdma2d);
  /* USER CODE BEGIN DMA2D_IRQn 1 */

  /* USER CODE END DMA2D_IRQn 1 */
}

arm compiler v5 + -O3 + 双半屏显存 权重 FPS 502 对于429开发版的屏幕而言和单全屏显存区别不大。
在这里插入图片描述

全尺寸双buffer

两个全尺寸buffer,虽然直觉看上去和非全尺寸双buffer应该区别不大,但实际上,这个是专门为带TFT驱动的MCU准备的。双全尺寸与前两种不同,在任何时候,给出的buffer都是全屏大小的buffer,而不是局部刷新只提供刷新部分的buffer窗口,这么做的的好处是刷屏,只需要更改TFT驱动的显存地址,而不需要将LVGL的buffer再搬运到TFT驱动的显存,就可完成刷屏动作。

F429带LTDC,也就是TFT驱动,理论上应当使用该类型。
不过实测帧没有提升反而大幅下降。。。。有点奇怪。

刷屏修改LTDC的显存地址, 当LTDC刷到最后一行,中断回调提示LVGL屏幕刷完。代码如下

      static lv_disp_buf_t draw_buf_dsc_2;  //两个全屏缓存
      static lv_color_t draw_buf_2_1[LV_HOR_RES_MAX * LV_VER_RES_MAX];                        /*A buffer for 10 rows*/
      static lv_color_t draw_buf_2_2[LV_HOR_RES_MAX * LV_VER_RES_MAX];                        /*An other buffer for 10 rows*/
      lv_disp_buf_init(&draw_buf_dsc_2,draw_buf_2_2, draw_buf_2_1, LV_HOR_RES_MAX *LV_VER_RES_MAX);   /*Initialize the display buffer*/
extern LTDC_HandleTypeDef hltdc;
static void disp_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p)
{

   disp_drv_p = disp_drv;
  HAL_LTDC_SetAddress(&hltdc,(uint32_t)color_p,0);
  HAL_LTDC_ProgramLineEvent(&hltdc,LV_VER_RES_MAX -1);
}
void LTDC_IRQHandler(void)
{
  /* USER CODE BEGIN LTDC_IRQn 0 */
  lv_disp_flush_ready(disp_drv_p); /* tell lvgl that flushing is done */
  /* USER CODE END LTDC_IRQn 0 */
  HAL_LTDC_IRQHandler(&hltdc);
  /* USER CODE BEGIN LTDC_IRQn 1 */
 __HAL_LTDC_DISABLE_IT(&hltdc, LTDC_IT_LI);
  /* USER CODE END LTDC_IRQn 1 */
}

总之以上在项目中三种显存模式都试一试。不同平台,帧率表现可能不太一样。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

LVGL 优化帧率技巧 的相关文章

  • lvgl 2048 sample

    64 file simple test c INCLUDES include 34 simple test h 34 if LV 100ASK 2048 SIMPLE TEST 61 0 DEFINES TYPEDEFS
  • LVGL 8.2 菜单

    定义及声明 span class token keyword enum span span class token punctuation span LV MENU ITEM BUILDER VARIANT 1 span class tok
  • stm32f407 FreeRTOS+LVGL移植

    参考资料 xff1a 正点原子 littleVGL 开发指南 正点原子 STM32F407 FreeRTOS 开发指南 硬件平台 xff1a stm32f407开发板 xff08 或最小系统 xff09 4 3寸TFTLCD 以正点原子的例
  • LVGL——PC模拟器仿真模拟+VS2017

    目录 LVGL介绍移植说明资源下载环境搭建编译运行 本文只针对当时的LVGL v7 xff0c LVGL迭代过程中变化较大 xff0c 部分接口有可能做调整 本文仅供参考 LVGL介绍 官网 xff1a https lvgl io 官方在线
  • LVGL V8

    本文适用于LVGL V8版本 LVGL simulator vs2019 官方工程 lv sim visual studio 使用注意事项 1 将官方工程从github上下载下来 最好使用git 将整个工程clone下来 因为工程内部有依赖
  • LVGL视频课程更新啦,基于lvgl v8.2版本,课程适配多个平台、多款板子

    视频教程观看 百问网LVGL v8 系列课程 韦东山 监制 教程基于lvgl v8 2版本 课程适配多个平台 多款板子 百问网LVGL v8 视频课程 韦东山 监制 教程基于lvgl v8 2版本 课程适配多个平台 多款板子 视频学习地址
  • lvgl 自定义控制表格行高、颜色和外框样式

    lvgl 自定义控制表格行高 颜色和外框样式 lvgl版本 8 3 7 lvgl自带表格控件能够指定列宽 但是表格行高是根据内容动态渲染的 表格自带样式如图 带有蓝色的外框和白底 如果想要手动控制表格行高 颜色和外框等属性 需要监听表格绘制
  • arduino-esp32:LVGL中文字库(通用)

    导航 概述 系统自带中文字库 使用自带中文字库 制作专属字库 使用专属字库 VS模拟器 效果 arduino esp32 效果 小结 概述 标题是arduino esp32只是因为平台是这个 LVGL默认的字库是英文的 当然其字库文件里也有
  • 图形库LVGL v8.2版本移植

    图形库LVGL v8 2版本移植 环境 硬件 前提准备 下载图形库代码 图形开发中的字体转换 图片转换 GUI GUIDER 图形化开发lvgl 移植 加入相关源代码到工程中 提供时钟信号给lvgl 使用GUI Guider 生成代码 并加
  • LVGL8制作简易时钟

    通过这两天对LVGL8的部分控件和样式的学习 自己制作了一个简易时钟 可显示时间 日期 星期 用到的主要有样式 布局等对象 还是通过codeblock来模拟代码的运行 代码如下 typedef struct lv clock lv obj
  • 【LVGL 学习】COLOR 常用接口函数说明

    COLOR 接口常用函数说明 通常跟样式 style 接口函数搭配使用 文件位置 src misc lv color c lv palette t 枚举包含以下18种 LV PALETTE RED LV PALETTE PINK LV PA
  • 【LVGL】ANIM(动画)时间线学习

    时间线 timeline 有时候需要同时播放较多动画 此时如果逐个播放的话 需要逐个为动画设计延时 不方便安排 此时 可以使用 LVGL 提供的时间线 timeline 统一安排各个动画 时间线的创建非常简单 首先 创建一系列动画 但先不调
  • lvgl实现动态切换横竖屏

    有两种方式 一种是通过lvgl自带的软件选择 但是这个效率很慢 而且只支持90度 180度 270度的旋转 不一定达到想要的效果 我需要实现的是这种效果 软件旋转没有办法实现 旋转后会镜像过去 而且如果你的屏幕不是等比例的 比如240 24
  • LVGL入门 常用的几个命令(个人笔记)

    前言 学习LVGL的过程中 常常知道有这个命令 也知道大概怎么用 但总想不起来命令叫什么 在整个库中找也显得麻烦 搞得每次写程序还要翻之前的Demo 所以在这里将学习过程中用到的命令 存放在这里 方便再使用的时候方便的找到命令名字 lv o
  • lvgl8.2 img 图片显示

    1 lvgl 图片显示源 为了提供良好的图片显示灵活性 所以显示图像的来源可以是以下三种 代码中的一个变量 一个带有像素颜色数据的 C 数组 存储在外部的文件 比如 SD 卡 带有符号的文本 2 内部图片 对于源码内部图片 将图片转换为图片
  • 【LVGL学习笔记】image图像相关接口

    数据结构如下 Data of image typedef struct lv obj t obj const void src 图像源 指向数组 文件或符号的指针 lv point t offset lv coord t w 宽度 lv c
  • LVGL学习(4):输入设备的四种类型及物理按键的实现

    在有一些场合中 如野外情况 可能我们会选择使用物理按键来控制LVGL 而不是使用触摸屏 所以本篇文章就以物理键盘为例来介绍一下如何自定义输入设备与LVGL进行交互 文章目录 1 输入设备类型 2 物理键盘实现 2 1 输入设备驱动注册 2
  • 【LVGL 学习】样式(style)风格学习

    概述 在 LVGL 中 样式都是以对象的方式存在 一个对象可以描述一种样式 每个控件都可以独立添加样式 创建的样式之间互不影响 可以使用 lv style t 类型创建一个样式并初始化 static lv style t style lv
  • microPython环境下的lvgl开发心得

    microPython环境下的lvgl是c代码通过pycparser转换成python代码的 因此没有python环境下的源文件 发开需依靠REPL 交互式控制台 调出文档配合c源码进行 以变换内置主题为例 记录下开发思路 打开REPL 输
  • LVGL V8学习之键盘按键样式重绘(二)

    这一篇继续研究一下基于btnmatrix的键盘按键重绘 是对上一篇LVGL V8学习之键盘按键样式重绘 一 的代码的优化 还是通过codeblock来模拟代码的运行 代码如下 按键矩阵的事件回调函数 static void btnmatri

随机推荐

  • PX4:【启动流程】

  • 线程池和多线程的区别

    线程池的概念 线程池大类总共分为4种 fixThreadPool 正规线程 xff08 传统线程池 xff09 cacheThreadPool 缓存线程池singleThreadPoll 单线程线程池 xff08 单例线程池 xff09 S
  • C++ libcurl Digest Auth

    C 43 43 libcurl Digest Auth postman操作如下 xff1a 附认证原理如下 xff1a MD5 md5 span class token punctuation span string HA1 span cl
  • 如何安装postman(超简单)

    方法一 xff1a xff08 官网下载 xff09 1 打开https www crx4chrome com crx 1058 2 稍微往下微微一拉就出现 Download crx file from Crx4Chrome gt 的选择
  • 转 curl 参数大全

    curl是一个非常实用的 用来与服务器之间传输数据的工具 xff1b 支持的协议包括 DICT FILE FTP FTPS GOPHER HTTP HTTPS IMAP IMAPS LDAP LDAPS POP3 POP3S RTMP RT
  • DataX mysql同步到mysql

    使用Datax web 创建同步任务 准备工作 创建数据源 配置数据库相关信息 创建执行器 配置执行器执行地址相关信息 1 构建reade 1 1 SQL语句 xff08 querySql xff09 在json文件中此部分配置就是 que
  • MQTT协议简介

    目录 MQTT协议简介一 MQTT协议特点1 1 发布和订阅1 2 QoS Quality of Service levels 二 MQTT数据包结构2 1 MQTT固定头2 2 MQTT可变长 Variable header 2 3 消息
  • vins位姿图优化

    我们 的滑动窗口和边缘化方案限制了计算的复杂性 xff0c 但也给系统带来了累积漂移 更确切地说 xff0c 漂移发生在全局三维位置 x y z 和围绕重力方向的旋转 yaw 为了消除漂移 xff0c 提出了一种与单目VIO无缝集成的紧耦合
  • 基于STM32开发板实现温湿度传感数据采集

    一 实验要求 本实验将选用STM32F407ZGT6开发板进行项目开发 xff0c 选用的传感器为DHT11温湿度传感器 传感器将采集到的数据传输到STM32 xff08 MCU xff09 主控进行数据处理 xff0c 最后通过串口打印出
  • 相机成像模型、内参矩阵、外参矩阵

    相机针孔成像模型 基本的小孔成像过程 xff1a X坐标系是针孔所在坐标系 xff0c Y坐标系为成像平面坐标系 xff0c P为空间一点 xff0c 小孔成像使得P点在图像平面上呈现了一个倒立的像 xff0c 俯视图如下 xff1a 由三
  • 韦东山学习笔记——UART(串口)的使用

    基于jz2440的串口使用 搬砖的文章概述UART的发送和接收串口之间的数据传输UART的用途串口的数据帧参数说明起始位数据位奇偶校验位停止位波特率 怎么发送一字节数据 xff0c 比如 A UART的优缺点优点缺点 UART相关配置寄存器
  • C++源文件的编译流程简介

    概述 C 43 43 C源文件 xff0c 包含 c h cpp hpp等格式的文件 xff0c 经过预处理 编译 汇编 链接后 xff0c 形成可执行文件 xff0c 也就是 exe文件 以一个简单项目MyProject为例 xff0c
  • 无法修正错误,因为您要求某些软件包保持现状,就是它们破坏了软件包间的依赖关系

    使用 sudo apt get install 安装软件时 xff0c 出现错误 无法修正错误 xff0c 因为您要求某些软件包保持现状 xff0c 就是它们破坏了软件包间的依赖关系 错误的主要原因是 xff0c 系统中已经安装了被依赖的包
  • kalibr工具的编译与安装

    安装 kalibr提供了两种安装使用的方法 一 直接使用打包好的程序 下载地址 xff0c 选择CDE packages下载 xff08 需要访问Google xff09 使用注意事项 xff1a 只有64位系统可以使用 二 源码编译 安装
  • TCP/IP协议栈协议头

    目录 OSI与TCP IP模型UDP发送数据过程以太网协议头IP协议头UDP协议头UDP包 OSI与TCP IP模型 UDP发送数据过程 以太网协议头 把上面的以太网头用一个结构体表示如下 xff1a span class token ma
  • VLAN标签

    大家好呀 xff0c 我是请假君 xff0c 今天又来和大家一起学习数通了 xff0c 今天要分享的知识是VLAN标签 我们知道 xff0c 以太网交换机根据MAC地址表来转发数据帧 MAC地址表中包含了端口和端口所连接终端主机MAC地址的
  • fastjson的一些用法

    一般情况下 xff0c 在进行redis集群写入时 xff0c 使用jedisCluster set key value value为String类型 xff0c 那么就用到了fastjson进行序列化 以下是一些要点 xff1a 1 序列
  • 【视觉SLAM十四讲】第12讲 回环检测

    12 1 回环检测概述 前面已经介绍过了前端和后端 xff0c 前端用于特征点的提取以及轨迹 地图的初始值 xff0c 而后端负责对这部分数据进行优化 考虑到误差的存在 xff0c 每一个时刻存在的误差会不断累积 xff0c 从而产生累积误
  • LVGL——PC模拟器仿真模拟+VS2017

    目录 LVGL介绍移植说明资源下载环境搭建编译运行 本文只针对当时的LVGL v7 xff0c LVGL迭代过程中变化较大 xff0c 部分接口有可能做调整 本文仅供参考 LVGL介绍 官网 xff1a https lvgl io 官方在线
  • LVGL 优化帧率技巧

    目录标题 前文未优化版本LVGL帧率限制刷屏方法效率代码优化等级编译器版本LVGL显存单buffer非全尺寸双buffer全尺寸双buffer 本文只针对当时的LVGL v7 xff0c LVGL迭代过程中变化较大 xff0c 部分接口有可