硬汉嵌入式论坛

 找回密码
 立即注册
查看: 571|回复: 12
收起左侧

[LVGL] stm32f1使用fsmc驱动显示屏,改用dam传输数据后颜色不对

[复制链接]

3

主题

6

回帖

15

积分

新手上路

积分
15
发表于 2023-8-14 16:12:38 | 显示全部楼层 |阅读模式
使用的是MCU8080接口,ili9342。  原来是使用FSMC接口通过cpu搬运数据, 现在想提示下性能,想改用DMA搬运,但是使用DMA后显示屏上的颜色不对。 请问这种问题要如何解决?

DMA的配置代码
[C] 纯文本查看 复制代码
void bsp_dam_lcd_start(uint32_t BufferAddr, uint32_t BufferSize)
{
    DMA_InitTypeDef DMA_InitStructure;

    // 开启DMA时钟
    RCC_AHBPeriphClockCmd(DMA_CLOCK, ENABLE);
	#if 1
    // 源数据地址
    DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t)BufferAddr; //颜色数组
    // 目标地址
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)(LCD_BASE + (1 << 17));
    // 方向:外设到存储器
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    // 传输大小
    DMA_InitStructure.DMA_BufferSize = BufferSize;
    // 外设(内部的FLASH)地址递增
    DMA_InitStructure.DMA_PeripheralInc =  DMA_PeripheralInc_Enable;
    // 内存地址递增
    DMA_InitStructure.DMA_MemoryInc =  DMA_MemoryInc_Disable;


    // 外设数据单位
    DMA_InitStructure.DMA_PeripheralDataSize =DMA_PeripheralDataSize_HalfWord;
    // 内存数据单位
    DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord;
    // DMA模式,一次或者循环模式
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;
    //DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    // 优先级:高
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    // 使能内存到内存的传输
    DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;
    // 配置DMA通道
    DMA_Init(DMA_CHANNEL, &DMA_InitStructure);
    // 使能DMA
    DMA_Cmd(DMA_CHANNEL,ENABLE);

}

回复

使用道具 举报

3

主题

6

回帖

15

积分

新手上路

积分
15
 楼主| 发表于 2023-8-14 16:49:44 | 显示全部楼层
不好意思,是字长那里配置的不对。
之前的都配成外设的半字宏定义了,  它的值和存储器的半字宏定义不一样。

[C] 纯文本查看 复制代码
    // 外设数据单位
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    // 内存数据单位
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
回复

使用道具 举报

3

主题

6

回帖

15

积分

新手上路

积分
15
 楼主| 发表于 2023-8-14 16:51:14 | 显示全部楼层
已结贴。没啥技术含量的帖子,管理员可以删帖了。
回复

使用道具 举报

28

主题

130

回帖

214

积分

高级会员

积分
214
发表于 2023-8-22 20:50:55 来自手机 | 显示全部楼层
fsmc 一下子就写过去了有必要用dma吗
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106997
QQ
发表于 2023-8-23 08:44:17 | 显示全部楼层
logo 发表于 2023-8-22 20:50
fsmc 一下子就写过去了有必要用dma吗

配合RTOS下,可以节省CPU利用率。
回复

使用道具 举报

28

主题

130

回帖

214

积分

高级会员

积分
214
发表于 2023-8-23 11:43:54 | 显示全部楼层
eric2013 发表于 2023-8-23 08:44
配合RTOS下,可以节省CPU利用率。

我的理解是fmsc直接写,软件层面也不需要等待,这样和用dma感觉没啥区别啊
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106997
QQ
发表于 2023-8-23 11:49:57 | 显示全部楼层
logo 发表于 2023-8-23 11:43
我的理解是fmsc直接写,软件层面也不需要等待,这样和用dma感觉没啥区别啊

不行,这个需要CPU参与。
回复

使用道具 举报

28

主题

130

回帖

214

积分

高级会员

积分
214
发表于 2023-8-23 11:56:15 | 显示全部楼层
eric2013 发表于 2023-8-23 08:44
配合RTOS下,可以节省CPU利用率。

我注意到了数据源地址他这里采用了自动递增使能,的确是是可以减少cpu直接写fmsc的时间开销。但是他这数据源的内容也是需要CPU来写的,除非他这个数据源内容保持不变 ,不需要修改。每次cpu只需要启动dma传输即可。不然的话如果数据内容改变还是需要cpu花时间来写的。相比其他软件层面需要等待的,这里用dma好像cpu释放率没提高很多。

[C] 纯文本查看 复制代码
    // 源数据地址
    DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t)BufferAddr; //颜色数组
    DMA_InitStructure.DMA_PeripheralInc =  DMA_PeripheralInc_Enable;
回复

使用道具 举报

28

主题

130

回帖

214

积分

高级会员

积分
214
发表于 2023-8-23 12:06:34 | 显示全部楼层
eric2013 发表于 2023-8-23 11:49
不行,这个需要CPU参与。

除非数据源里的数据是不变的,即屏幕显示内容是不变的,这样cpu才可以解放,不然如果数据源里的的数据需要改变这样同样需要cpu搬运数据到数据源地址里吧。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106997
QQ
发表于 2023-8-23 16:09:51 | 显示全部楼层
logo 发表于 2023-8-23 11:56
我注意到了数据源地址他这里采用了自动递增使能,的确是是可以减少cpu直接写fmsc的时间开销。但是他这数 ...

首先源数据,不管你是否使用了DMA,这个都是GUI准备的好的。

我们节省的是大部分源数据到实际LCD的展示,全部采用了DMA,这个节省的CPU还是比较明显的,比如刷新图标,背景图,GIF动态等,节省了很多CPU时间。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106997
QQ
发表于 2023-8-23 16:13:22 | 显示全部楼层
logo 发表于 2023-8-23 12:06
除非数据源里的数据是不变的,即屏幕显示内容是不变的,这样cpu才可以解放,不然如果数据源里的的数据需 ...

最根本的地方在于LVGL的输出都是通过这个接口函数输出的,基本所有的都是。

也就是说所有的实际输出都是它实现的,这个减轻的CPU利用率是相当明显的。

就像我们串口DMA一样,串口的原始数据怎么来的,跟DMA无关。DMA管理的就是实际的串口输出,这个LCD DMA同理。
回复

使用道具 举报

28

主题

130

回帖

214

积分

高级会员

积分
214
发表于 2023-8-23 17:19:39 | 显示全部楼层
eric2013 发表于 2023-8-23 16:09
首先源数据,不管你是否使用了DMA,这个都是GUI准备的好的。

我们节省的是大部分源数据到实际LCD的展 ...

你说的情况是指GUI源数据已经准备好的情况,但如果源数据是实时计算出来的,计算出来的结果无论是直接写LCD->RAM还是写到dma源地址里(然后再让dma自动传输到LCD->RAM)总归还是要CPU花时间开销来写的吧。除非dma源地址是实时计算的数据结果变量的地址指针,这样实时计算的结果相当于直接就在源地址里,cpu就可以不用再单独的往dma源地址里写实时计算的数据了,这样就节省了CPU开销了。

回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106997
QQ
发表于 2023-8-23 17:39:28 | 显示全部楼层
logo 发表于 2023-8-23 17:19
你说的情况是指GUI源数据已经准备好的情况,但如果源数据是实时计算出来的,计算出来的结果无论是直接写L ...

你的理解已经完全跑偏了,停留在二次复制粘贴这个点上了,这个本质上是GUI的绘制机制,作用是局部加速,防止卡顿。你不用DMA,它也必须要二次复制粘贴

你知道这个dma源地址缓冲反应到LVGL是什么不,这个是LVGL的局部缓冲,LVGL的绘制都是优先绘制到这个局部缓冲来实现加速,防止局部卡顿效果的,然后整理绘制到LCD显存里面,因为显存速度比缓存RAM速度慢多了,这个是大部分GUI的玩法,这个是一个重要作用点。你现在用的emWin也是类似玩法,你看下emWin的16bpp接口函数,是不是将GUI弄好的缓存数据绘制到LCD。

我们这里恰恰是将局部缓冲使用DMA绘制到LCD的显存里面。这个节省的时间是相当明显的,比如你刷新800*480整个显示屏要多少时间,F407怎么也得100ms左右才一帧,这个由DMA来绘制,得节省多少CPU时间。
回复

使用道具 举报

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

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-14 06:25 , Processed in 0.188625 second(s), 26 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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