我看了很多DMA2D教程都是用阻塞方式来刷新屏, 这样就消耗了性能 相当于没用DMA, 所以我使用DMA2D中断来传输数据

测试平台

stm32f429 + 正点原子7寸1024x600液晶屏 45MHZ刷新率 + LVGL

公有条件:

LTDC刷新率45MHZ, 开启SDRAM 突发传输, LVGL 2个全尺寸缓冲区

1 LVGL不使用DMA2D, 使用寄存器DMA2D传输

LVGL配置

#define LV_USE_GPU              1   /*Only enables `gpu_fill_cb` and `gpu_blend_cb` in the disp. drv- */
#define LV_USE_GPU_STM32_DMA2D  0
/*If enabling LV_USE_GPU_STM32_DMA2D, LV_GPU_DMA2D_CMSIS_INCLUDE must be defined to include path of CMSIS header of target processor
e.g. "stm32f769xx.h" or "stm32f429xx.h" */
#define LV_GPU_DMA2D_CMSIS_INCLUDE   "stm32f429xx.h"

LVGL port配置

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*///LTDC_Color_Fill(area->x1,area->y1,area->x2,area->y2,(uint16_t*)(color_p));uint32_t h = area->y2 - area->y1;uint32_t w = area->x2 - area->x1;uint32_t OffLineSrc = 1024 - (area->x2 - area->x1 +1);uint32_t addr = LCD_FRAME_BUF_ADDR + 2*(1024*area->y1 + area->x1);// --- 阻塞传输---// 模式DMA2D->CR      = 0x00000000UL | (1 << 9);// 源地址DMA2D->FGMAR   = (uint32_t)(uint16_t*)(color_p);// 目标地址DMA2D->OMAR    = (uint32_t)addr;// 输入偏移DMA2D->FGOR    = 0;// 输出偏移DMA2D->OOR     = OffLineSrc;/* 前景层和输出区域都采用的RGB565颜色格式 */DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_RGB565;DMA2D->OPFCCR  = LTDC_PIXEL_FORMAT_RGB565;DMA2D->NLR     = (area->y2-area->y1+1) | ((area->x2 -area->x1 +1) << 16);/* 启动传输 */DMA2D->CR   |= DMA2D_CR_START;   /* 等待DMA2D传输完成 */while (DMA2D->CR & DMA2D_CR_START) {} lv_disp_flush_ready(disp_drv);}

跑benckmark大概是11fps

2  LVGL使用DMA2D, 使用寄存器DMA2D传输

#define LV_USE_GPU              0   /*Only enables `gpu_fill_cb` and `gpu_blend_cb` in the disp. drv- */
#define LV_USE_GPU_STM32_DMA2D  1
/*If enabling LV_USE_GPU_STM32_DMA2D, LV_GPU_DMA2D_CMSIS_INCLUDE must be defined to include path of CMSIS header of target processor
e.g. "stm32f769xx.h" or "stm32f429xx.h" */
#define LV_GPU_DMA2D_CMSIS_INCLUDE   "stm32f429xx.h"

加入宏定义STM32F4

3  LVGL不使用DMA2D, 使用寄存器DMA2D中断传输

因为如果LVGL开启DMA2D之后, 会进入到DMA2D中断,所以要判断是LVGL内部中断,还是自己的刷图中断, 用volatile uint8_t g_gpu_state = 0; 这个来判断

#define LV_USE_GPU              1   /*Only enables `gpu_fill_cb` and `gpu_blend_cb` in the disp. drv- */
#define LV_USE_GPU_STM32_DMA2D  0
/*If enabling LV_USE_GPU_STM32_DMA2D, LV_GPU_DMA2D_CMSIS_INCLUDE must be defined to include path of CMSIS header of target processor
e.g. "stm32f769xx.h" or "stm32f429xx.h" */
#define LV_GPU_DMA2D_CMSIS_INCLUDE   "stm32f429xx.h"
volatile uint8_t g_gpu_state = 0;
// DMA2D传输完成回调
static void mDMA2Dcallvack(DMA2D_HandleTypeDef *hdma2d)
{if(g_gpu_state==1){g_gpu_state = 0;lv_disp_flush_ready(&g_disp_drv);}
}
// dma2D采用HAL初始化
static void dma2d_use_hal_init(void)
{hdma2d.Instance = DMA2D;hdma2d.XferCpltCallback = mDMA2Dcallvack;if (HAL_DMA2D_Init(&hdma2d) != HAL_OK){}
}/* Initialize your display and the required peripherals. */
static void disp_init(void)
{dma2d_use_reg_init();
}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*///LTDC_Color_Fill(area->x1,area->y1,area->x2,area->y2,(uint16_t*)(color_p));uint32_t h = area->y2 - area->y1;uint32_t w = area->x2 - area->x1;uint32_t OffLineSrc = 1024 - (area->x2 - area->x1 +1);uint32_t addr = LCD_FRAME_BUF_ADDR + 2*(1024*area->y1 + area->x1);// -- 中断传输// 模式DMA2D->CR      = 0x00000000UL | (1 << 9);// 源地址DMA2D->FGMAR   = (uint32_t)(uint16_t*)(color_p);// 目标地址DMA2D->OMAR    = (uint32_t)addr;// 输入偏移DMA2D->FGOR    = 0;// 输出偏移DMA2D->OOR     = OffLineSrc;/* 前景层和输出区域都采用的RGB565颜色格式 */DMA2D->FGPFCCR = DMA2D_OUTPUT_RGB565;DMA2D->OPFCCR  = DMA2D_OUTPUT_RGB565;// 多少行DMA2D->NLR     = (area->y2-area->y1+1) | ((area->x2 -area->x1 +1) << 16);// 开启中断DMA2D->CR |= DMA2D_IT_TC|DMA2D_IT_TE|DMA2D_IT_CE;/* 启动传输 */DMA2D->CR   |= DMA2D_CR_START;   g_gpu_state = 1;
}

4 3  LVGL使用DMA2D, 使用寄存器DMA2D中断传输

#define LV_USE_GPU              0   /*Only enables `gpu_fill_cb` and `gpu_blend_cb` in the disp. drv- */
#define LV_USE_GPU_STM32_DMA2D  1
/*If enabling LV_USE_GPU_STM32_DMA2D, LV_GPU_DMA2D_CMSIS_INCLUDE must be defined to include path of CMSIS header of target processor
e.g. "stm32f769xx.h" or "stm32f429xx.h" */
#define LV_GPU_DMA2D_CMSIS_INCLUDE   "stm32f429xx.h"
volatile uint8_t g_gpu_state = 0;
// DMA2D传输完成回调
static void mDMA2Dcallvack(DMA2D_HandleTypeDef *hdma2d)
{if(g_gpu_state==1){g_gpu_state = 0;lv_disp_flush_ready(&g_disp_drv);}
}
// dma2D采用HAL初始化
static void dma2d_use_hal_init(void)
{hdma2d.Instance = DMA2D;hdma2d.XferCpltCallback = mDMA2Dcallvack;if (HAL_DMA2D_Init(&hdma2d) != HAL_OK){}
}/* Initialize your display and the required peripherals. */
static void disp_init(void)
{dma2d_use_reg_init();
}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*///LTDC_Color_Fill(area->x1,area->y1,area->x2,area->y2,(uint16_t*)(color_p));uint32_t h = area->y2 - area->y1;uint32_t w = area->x2 - area->x1;uint32_t OffLineSrc = 1024 - (area->x2 - area->x1 +1);uint32_t addr = LCD_FRAME_BUF_ADDR + 2*(1024*area->y1 + area->x1);// -- 中断传输// 模式DMA2D->CR      = 0x00000000UL | (1 << 9);// 源地址DMA2D->FGMAR   = (uint32_t)(uint16_t*)(color_p);// 目标地址DMA2D->OMAR    = (uint32_t)addr;// 输入偏移DMA2D->FGOR    = 0;// 输出偏移DMA2D->OOR     = OffLineSrc;/* 前景层和输出区域都采用的RGB565颜色格式 */DMA2D->FGPFCCR = DMA2D_OUTPUT_RGB565;DMA2D->OPFCCR  = DMA2D_OUTPUT_RGB565;// 多少行DMA2D->NLR     = (area->y2-area->y1+1) | ((area->x2 -area->x1 +1) << 16);// 开启中断DMA2D->CR |= DMA2D_IT_TC|DMA2D_IT_TE|DMA2D_IT_CE;/* 启动传输 */DMA2D->CR   |= DMA2D_CR_START;   g_gpu_state = 1;
}

对比:

1 不使用GPU,使用寄存器DMA2D,11fps

2 使用GPU,使用寄存器DMA2D, 23fps

3 不使用GPU,使用寄存器DMA2D中断传输, 11fps

4 使用GPU,中断传输, 30fps

另外我发现开单缓冲比双缓冲快很多, 这个bug估计未来会优化

因为1和3, fps相等是因为在颜色转换消耗了太多时间, 所以中断和阻塞方式基本上差不

听说打开优化等级和编译器等级会更快, 可以试试这个

另外自己写DMA2D中断和采用HAL的回调基本参没什么差距, 所以建议直接采用HAL库的回调

void DMA2D_IRQHandler(void)
{if ((DMA2D->ISR & DMA2D_FLAG_TC) != 0U){if ((DMA2D->CR & DMA2D_IT_TC) != 0U){DMA2D->CR &= ~DMA2D_IT_TC;DMA2D->IFCR =DMA2D_FLAG_TC;if(g_gpu_state==1){g_gpu_state = 0;lv_disp_flush_ready(&g_disp_drv);}}}
}

stm32 DMA2D使用中断LVGL,提高LVGL帧率相关推荐

  1. 【LVGL应用开发--基于STM32】第1章 初识LVGL

    文章目录 前言 1.1 LVGL简介 1.2 LVGL移植要求 1.3 LVGL源码下载与介绍 前言 在实际应用中,我们时常需要制作 UI 界面来实现人机交互,简单的 UI 可以直接编写代码,但对于那 ...

  2. STM32的“外部中断”和“事件”区别和理解

    凡从事过ST MCU应用开发的人往往会遇到事件.中断事件 中断三个概念或术语.这三个概念彼此关联,有时会让人有点混淆或犯迷糊. 先拿一件生活中的事情打比方对上述三个概念做个基本的粗略理解,之后再分享一 ...

  3. STM32单片机外部中断配置讲解

    2019独角兽企业重金招聘Python工程师标准>>> 单片机外部中断简介 所谓外部中断,就是通过外部信号所引起的中断,如单片机引脚上的电平变化(高电平.低电平).边沿变化(上升沿. ...

  4. STM32网络之中断

    之前的推文已经将STM32网络的三大件讲完了 ①PHY接口,<STM32网络电路设计> ②MAC控制器,<STM32网络之MAC控制器> ③DMA控制器,<STM32网络 ...

  5. stm32: 串口空闲中断的实现(HAL库)

    STM32利用串口空闲中断来分包(HAL库) 文章目录 STM32利用串口空闲中断来分包(HAL库) 1. 开发环境 2. 串口中断接收的问题和解决办法 3. 串口空闲中断分包的原理 4. STM32 ...

  6. stm32入门——定时器中断和中断优先级简介

    stm32入门--定时器中断 产生定时中断是定时器的用法之一,与定时器用来进行PWM输出和输入捕获相比,定时器中断更容易理解.掌握. 原理简介 使用通用定时器进行中断的原理,其实和开发板Systick ...

  7. 深入浅出地理解STM32中的中断系统——从原理到简单工程示例——保姆级教程

    深入浅出地理解STM32中的中断系统 一.什么是中断?什么是异常? 二.如何管理中断? 三.NVIC 1 NVIC 特点 2 中断优先级 (1) 优先级分组 3 中断向量表 4 中断服务函数 (1)中 ...

  8. stm32学习笔记-中断系统

    文章目录 问题引入 1.中断系统概述. 1.1 为什么要中断(中断意义) 中断和轮询比较: 1.2 中断处理过程 1.3 中断笔试题 1.4 中断服务函数 2.STM32中断的体系结构. 2.1 结构 ...

  9. STM32系列 USART中断接收 注意事项 (USART_IT_ORE)

    ZHL学习笔记 STM32系列USART中断接受注意事项 之 USART_IT_ORE USART_IT_ORE含义:接收溢出,尚未处理上一拍就迎来了下一拍数据: USART_IT_ORE使能:该中断 ...

最新文章

  1. (完全解决)(numba)TypingError: Failed in nopython mode pipeline( Invalid use of Function)
  2. 传统数据中心穿上“云”外衣 任重而道远
  3. Unable to instantiate application
  4. 当前计算机无法连接,win7系统无法连接wifi提示此计算机当前已将连接限制为xxx的解决方法...
  5. 03-Flutter移动电商实战-底部导航栏制作
  6. 宾利为什么卖这么贵?
  7. 2019 PC 台式机垃圾佬 记录
  8. 12. 指针、句柄、引用的区别
  9. OCP大会 | 腾讯开放光网络平台(附PDF)
  10. 将《先生请出山》放到桌面上,聊聊如何将视频做成动态壁纸
  11. 嵌入式实践教程--Android HAL自定义HAL代码教程
  12. iOS开发工程师常见面试题及答案
  13. SFDC数据导出的几种方式
  14. 计算机内存容量影响游戏的吗,内存容量对整机游戏性能影响有多大?
  15. 《图解HTTP》摘录
  16. MPX200 ROM DIY指南[转]
  17. 汉诺塔问题——递归算法
  18. Scala class和case class的区别
  19. 三十行代码轻松破解山东理工大学教务系统的登录问题
  20. Windows Server 2012 R2 部署JavaWeb项目之环境、软件、配置

热门文章

  1. win10怎么连接android手机,如何将手机与Win10电脑关联以在电脑上继续任务?
  2. ggplot2画图——点图想要描边但是又需要去除边框
  3. 启动错误:Could not resolve placeholder 'spring.datasource.url' in value ${spring.datasource.url}
  4. 最详细的教程axure新手入门:Axure教程
  5. DW大学生网页作业制作设计 中华饮食文化(HTML+CSS+JavaScript) Web前端大作业
  6. 双连通图强连通图概念解释以及tarjan算法求解该类问题总结
  7. java计算机毕业设计社区生活超市管理系统源程序+mysql+系统+lw文档+远程调试
  8. 部署Kubernetes时出现ImagePullBackOff或ErrImagePull情况
  9. 必备武器-skycc营销软件
  10. mysql报错3009_MySQL修改密码方法汇总