OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 11878|回复: 9

STM32F103---DMA-->FSMC-->LCD 刷屏 还是好卡 我方法错了?

[复制链接]

16

主题

103

帖子

0

精华

高级会员

Rank: 4

积分
830
金钱
830
注册时间
2020-7-1
在线时间
110 小时
发表于 2021-9-17 14:30:30 | 显示全部楼层 |阅读模式
本帖最后由 q879524825 于 2021-9-17 14:30 编辑

最近用STM32F103ZET6做 LVGL 的移植,结果发现  画曲线图的 页面只有4FPS,,所以想办法进行优化,使用的是F1精英板  。没有使用外扩SRAM 加速 。
目前采用 显示接口函数如下: 采用双buf
  1. void lv_port_disp_init(void)
  2. {
  3.     /*-------------------------
  4.      * Initialize your display
  5.      * -----------------------*/
  6.     disp_init();

  7.     /*-----------------------------
  8.      * Create a buffer for drawing
  9.      *----------------------------*/
  10.         static lv_disp_draw_buf_t disp_buf;

  11.         /* Example for 2) */                             //240*10*2/1024=  4.7KB
  12.   static lv_color_t buf_2_1[LV_HOR_RES_MAX * 10];      //双buf没什么提升     /*A buffer for 10 rows*/
  13.   static lv_color_t buf_2_2[LV_HOR_RES_MAX * 10];                        /*An other buffer for 10 rows*/
  14.   lv_disp_draw_buf_init(&disp_buf, buf_2_1, buf_2_2, LV_HOR_RES_MAX * 10);   /*Initialize the display buffer*/
  15.         
  16.    /* Example for 3) also set disp_drv.full_refresh = 1 below*/
  17.                         //320*240*2*2/1024= 300KB ??  太大了
  18. //    static lv_color_t buf_3_1[LV_HOR_RES_MAX * LV_VER_RES_MAX];            /*A screen sized buffer*/
  19. //    static lv_color_t buf_3_2[LV_HOR_RES_MAX * LV_VER_RES_MAX];            /*An other screen sized buffer*/
  20. //    lv_disp_draw_buf_init(&disp_buf, buf_3_1, buf_3_2, LV_HOR_RES_MAX * LV_VER_RES_MAX);   /*Initialize the display buffer*/
  21.         
  22.         static lv_disp_drv_t disp_drv;          /*A variable to hold the drivers. Must be static or global.*/

  23.         lv_disp_drv_init(&disp_drv);            /*Basic initialization*/
  24.         disp_drv.draw_buf = &disp_buf;          /*Set an initialized buffer*/
  25.         disp_drv.flush_cb = disp_flush;        /*Set a flush callback to draw to the display*/

  26.         disp_drv.hor_res = lcddev.width;      //从LCD的结构体里获取分辨率         
  27.         disp_drv.ver_res = lcddev.height;      

  28.         lv_disp_t * disp;
  29.         disp = lv_disp_drv_register(&disp_drv); /*Register the driver*/
  30.         
  31.   
  32. }
  33. static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
  34. {
  35.                 //LCD_Color_Fill(area->x1,area->y1,area->x2,area->y2,(u16*)color_p);   //正点LVGL 源码里 使用的 是这个
  36.                 DMA2C4_LCD_Color_Fill(area->x1,area->y1,area->x2,area->y2,(u16*)color_p);  //尝试用DMA吧  cpu太拉了
  37.         
  38.     /* IMPORTANT!!!
  39.      * Inform the graphics library that you are ready with the flushing*/
  40.     lv_disp_flush_ready(disp_drv);
  41. }
复制代码
DMA 的代码如下本来用的是LCD_Color_Fill() 这个函数 ,我照葫芦画瓢 写了DMA2C4_LCD_Color_Fill  由于原子的 函数 是 逐行 逐列  一个点一个点的 写的  ,每一行写之前 还要 定为 坐标LCD_SetCursor(sx,sy+i); //设置光标位置  以及 LCD_WriteRAM_Prepare(); //开始写入GRAM  
有些问题 感觉有点困惑 :
1.不能 将 整块字节  用DMA 写入  目前只是用DMA  写入一行 ,
2.我想要 main函数里初始化一次DMA, 然后在DMA2C4_LCD_Color_Fill  里更改 寄存器 更改DMA2_Channel4 CNDTR CMAR 从而修改 缓存大小 和 内存地址,但是这样不起作用,烧录后屏幕白屏,模糊。 所以只能每次写一行 之前 都初始化一次 DMA 更改缓存大小 和 内存地址 ,感觉有点蠢。 另外就是这样用DMA 和用 原本的 刷屏函数 没什么区别啊 ,还是很卡 72M 不太好用 啊
  1. /*配置 DMA 内存到内存   从 数组 到 FSMC

  2. */

  3. static DMA_InitTypeDef DMA_FSMC_InitStructure;  //全局变量  ,
  4. void DMA2C4_FSMC_Config(u32 size, u32 mem_addr)
  5. {
  6.         
  7.          RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);        //使能DMA传输
  8.         
  9.   DMA_DeInit(DMA2_Channel4);   //将DMA的通道 寄存器重设为缺省值

  10.         DMA_FSMC_InitStructure.DMA_PeripheralBaseAddr = (u32)&LCD->LCD_RAM;  //DMA外设基地址
  11.         DMA_FSMC_InitStructure.DMA_MemoryBaseAddr = mem_addr;  //DMA内存基地址   内存地址是?
  12.         DMA_FSMC_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;  //数据传输方向,从内存读取发送到外设
  13.         DMA_FSMC_InitStructure.DMA_BufferSize = size;  //DMA通道的DMA缓存的大小
  14.         DMA_FSMC_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //外设地址寄存器不变 *****
  15.         DMA_FSMC_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  //内存地址寄存器递增
  16.         DMA_FSMC_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;  //数据宽度为16位
  17.         DMA_FSMC_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //数据宽度为16位
  18.         DMA_FSMC_InitStructure.DMA_Mode = DMA_Mode_Normal;  //工作在正常模式   传输一次后 就停止了 因为 缓存大小 被复位为0了
  19.         DMA_FSMC_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA通道 x拥有中优先级
  20.         DMA_FSMC_InitStructure.DMA_M2M = DMA_M2M_Enable;  //DMA通道x 设置为内存到内存传输
  21.         DMA_Init(DMA2_Channel4, &DMA_FSMC_InitStructure);  //根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器
  22.         
  23.         DMA_Cmd(DMA2_Channel4, DISABLE );  //先关闭         
  24. }

  25. void DMA2C4_LCD_Color_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 *color)
  26. {
  27.                 u16 i=0,j=0;
  28.                 u16 height,width;
  29.                 u32 Fill_Num;
  30.                 width=ex-sx+1;                         //得到填充的宽度
  31.                 height=ey-sy+1;                        //高度
  32.                
  33.                
  34.                 for(i=0;i<height;i++)                //一行一行的写      
  35.                 {
  36.                         
  37.                         LCD_SetCursor(sx,sy+i);           //设置光标位置
  38.                         LCD_WriteRAM_Prepare();     //开始写入GRAM
  39.                         
  40. //                     DMA2_Channel4->CCR &= (uint16_t)(~DMA_CCR1_EN);      //关闭DMA2,
  41. //                     DMA2_Channel4->CNDTR =width;                               //设置buffsize 正常模式 工作一次后 该寄存器就清空了
  42. //                     DMA2_Channel4->CMAR =(u32)(color+(i*width));           //寄存器修改内存地址
  43.                         DMA2C4_FSMC_Config(width,(u32)(color+(i*width)));  //每次 重新配置DMA ? 浪费时间 啊  
  44.                         DMA2_Channel4->CCR |= DMA_CCR1_EN;                            //开启一次DMA传输               
  45.                         while(DMA_GetFlagStatus(DMA2_FLAG_TC4)!=SET);                        //等完成 一行一行的发      
  46.                         DMA2_Channel4->CCR &= (uint16_t)(~DMA_CCR1_EN);                //关闭DMA2,
  47.                                 
  48.                 }                  //可以用了 但是显示效果没什么变化
  49.                
  50.                 //就不能 一个块 DMA 发送嘛        
  51. }
复制代码
刚跨过大门,入眼是海洋
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

16

主题

103

帖子

0

精华

高级会员

Rank: 4

积分
830
金钱
830
注册时间
2020-7-1
在线时间
110 小时
 楼主| 发表于 2021-9-17 14:30:31 | 显示全部楼层
画了一个动态 画曲线 的chart
QQ截图20210916153040.png
刚跨过大门,入眼是海洋
回复 支持 反对

使用道具 举报

3

主题

20

帖子

0

精华

初级会员

Rank: 2

积分
68
金钱
68
注册时间
2019-9-9
在线时间
20 小时
发表于 2021-10-19 15:14:45 | 显示全部楼层
可以整块刷屏,帮顶
回复 支持 反对

使用道具 举报

1

主题

31

帖子

0

精华

高级会员

Rank: 4

积分
688
金钱
688
注册时间
2019-6-2
在线时间
237 小时
发表于 2021-10-25 11:56:33 | 显示全部楼层
你可以开一个窗口 然后再写GRAM  DMA一直发就行了
回复 支持 反对

使用道具 举报

16

主题

103

帖子

0

精华

高级会员

Rank: 4

积分
830
金钱
830
注册时间
2020-7-1
在线时间
110 小时
 楼主| 发表于 2021-10-25 21:34:24 | 显示全部楼层
会单片机 发表于 2021-10-25 11:56
你可以开一个窗口 然后再写GRAM  DMA一直发就行了

是不是调用void LCD_Set_Window(u16 sx,u16 sy,u16 width,u16 height) 这个函数?
刚跨过大门,入眼是海洋
回复 支持 反对

使用道具 举报

5

主题

51

帖子

0

精华

初级会员

Rank: 2

积分
84
金钱
84
注册时间
2021-8-27
在线时间
27 小时
发表于 2022-7-8 11:28:39 | 显示全部楼层
类似于OLED,开一个GRAM,把数据写进去,然后通过DMA一次性把GRAM里的数据刷到屏幕上
回复 支持 反对

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
8
金钱
8
注册时间
2022-9-2
在线时间
0 小时
发表于 2022-9-2 15:09:07 | 显示全部楼层
楼主,有源码分享一下吗
回复 支持 反对

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
8
金钱
8
注册时间
2022-9-2
在线时间
0 小时
发表于 2022-9-2 15:09:29 | 显示全部楼层
是姜先生啊 发表于 2022-7-8 11:28
类似于OLED,开一个GRAM,把数据写进去,然后通过DMA一次性把GRAM里的数据刷到屏幕上

大佬,有源码分享一下吗
回复 支持 反对

使用道具 举报

5

主题

51

帖子

0

精华

初级会员

Rank: 2

积分
84
金钱
84
注册时间
2021-8-27
在线时间
27 小时
发表于 2022-10-21 14:11:37 | 显示全部楼层
hxq0818 发表于 2022-9-2 15:09
大佬,有源码分享一下吗

手上暂时没有,这是常见的解决方法,你可以去网上搜一下
回复 支持 反对

使用道具 举报

0

主题

9

帖子

0

精华

初级会员

Rank: 2

积分
70
金钱
70
注册时间
2020-12-26
在线时间
25 小时
发表于 2023-2-17 16:28:43 | 显示全部楼层
借宝地问一下, 从SPI2口读数据刷到SPI1接口的屏, 都用DMA传输, 但是是一个DMA1的3(LCD发送),4(W25Q读取)两个通道, 可以异步同时工作吗?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-24 16:06

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表