搜索
bottom↓
回复: 4
打印 上一主题 下一主题

斑竹,帮忙解决一下DMA不能搬运数据到液晶屏

[复制链接]

出390入22汤圆

跳转到指定楼层
1
发表于 2022-9-13 11:22:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 liudingding 于 2022-9-13 11:40 编辑

我属愚笨型人员,主控F407是用寄存器开发的,显示屏用TK499,例程都是库开发的,不懂库函数,写起程序很困难,照瓢画瓢从例程上抄了个DMA搬运数据显示的程序,不工作,求斑竹看看哪里错了,直接来个正确的程序,你要是说修改方法的话,我将是云里雾里的听不懂,这个帖子就看不懂:www.amobbs.com/forum.php?mod=vie ... 4&highlight=DMA


程序如下:
LCD_Fill_Pic(0, 0,320, 480, (u32*)gImage_MM_T035);  //用DMA模式 显示一幅图片       


/******************************************
函数名:Lcd图像填充
功能:向Lcd指定位置填充图像
入口参数:
                                        (x,y): 图片左上角起始坐标
                                        (pic_H,pic_V): 图片的宽高
                                         pic  指向存储图片数组的指针
******************************************/
void LCD_Fill_Pic(u16 x, u16 y,u16 pic_H, u16 pic_V, u32*  pic)
{
        //DMA 方式
        BlockWrite(x,x+pic_H-1,y,y+pic_V-1);     //开窗函数
        TK80_DMA_Init((u32)pic, pic_H*pic_V*2);  //DMA初始化
        while((DMA2->ISR & 0x20)==0);
        DMA2->IFCR |=1<<5;       
}
void TK80_DMA_Init(u32 srcAdd ,u32 len)         //TK80的DMA配置函数,srcAdd是源地址,len是数据长度,一次能搬运42亿点
{   
        RCC->AHB2ENR |= RCC_AHB2Periph_TK80;   
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);
       
        DMA2_Channel2->CCR = 0x3090;                        //0x3090==8位, 0x3590==16位,        0x3A90==32位,
        DMA2_Channel2->CPAR = (u32)&(TK80->DINR);
        TK80->CFGR1 = 0x05050102;
        TK80->CFGR2 = 0x0501;

        DMA2_Channel2->CMAR  = srcAdd;  //存储器地址(发送地址)
        DMA2_Channel2->CNDTR = len;     //数据传输长度
        DMA2_Channel2->CCR  |= 1;       //通道开启
        TK80->CR |= 1;
}
void WriteComm(unsigned int CMD) //写命令
{
        TK80->CMDIR = CMD;
        while(TK80->SR & 0x10000);
}

void WriteData(u32 dat) //写数据
{
        TK80->DINR = dat;
        while(TK80->SR & 0x10000);       
}
/**********************************************
函数名:开窗函数

入口参数:XStart x方向的起点
          Xend   x方向的终点
                                        YStart y方向的起点
          Yend   y方向的终点

这个函数的意义是:开一个矩形框,方便接下来往这个框填充数据
***********************************************/
void BlockWrite(unsigned int Xstart,unsigned int Xend,unsigned int Ystart,unsigned int

Yend)
{

        WriteComm(0x2a);
        WriteData(Xstart>>8);
        WriteData(Xstart);
        WriteData(Xend>>8);
        WriteData(Xend);

        WriteComm(0x2b);   
        WriteData(Ystart>>8);
        WriteData(Ystart);
        WriteData(Yend>>8);
        WriteData(Yend);
        WriteComm(0x2c);
}

出16170入6148汤圆

2
发表于 2022-9-13 11:23:56 来自手机 | 只看该作者
已经帮你转告版主

出0入143汤圆

3
发表于 2022-9-13 12:27:49 | 只看该作者
        你是用在7寸屏上吗?7寸屏这种属于线性显示器,你用这个DMA属于直接内存到内存copy,可以用在特例下面,就是搬运的数据刚好等于屏的分辨率,也就是全屏显了。或者还有一个特例情况,就是整行显示,这个用在LVGL界面上比较多,就只更新需要更新的行数,其它不动的行不更新显示,达到快速显示的效果。
        只参考DMA例程中的M to M例程就行,如下函数,只需要更改目标地址M_addr_des及源地址M_addr_scr 两个参数就行。
        原理是,线性显示器是从内存中顺序读取数据,发送到LTDC接口给显示器显示的,所以所有操作只有内存操作就行。
  1. void DMA_m32tom32_test(void)
  2. {
  3.         DMA_InitTypeDef DMA_InitStructure;

  4.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

  5.         DMA_InitStructure.DMA_PeripheralBaseAddr = M_addr_des;
  6.   DMA_InitStructure.DMA_MemoryBaseAddr = M_addr_scr;
  7.   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
  8.   DMA_InitStructure.DMA_BufferSize = 128;
  9.   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
  10.   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  11.   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
  12.   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
  13.   DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
  14.   DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
  15.   DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;
  16.   DMA_Init(DMA1_Channel6, &DMA_InitStructure);
  17.        
  18.         DMA_Cmd(DMA1_Channel6, ENABLE);
  19.         AI_Responder_refresh();//refresh the AI Responder
  20. }
复制代码


出390入22汤圆

4
 楼主| 发表于 2022-9-13 14:05:59 | 只看该作者
本帖最后由 liudingding 于 2022-9-13 14:42 编辑
tiky 发表于 2022-9-13 12:27
你是用在7寸屏上吗?7寸屏这种属于线性显示器,你用这个DMA属于直接内存到内存copy,可以用在特例 ...
(引用自3楼)


谢谢斑竹答复,还有个问题不明白:
DMA_InitStructure.DMA_PeripheralBaseAddr = M_addr_des;
如果我要让源起始地址为:__align(4) const unsigned char gImage_MM_T035[614400]首地址,
或者u32  cc[8000]首地址,应该怎么写?
可能是基础问题,基础不行,只会 if  else



解决了,从寄存器来,一直用&取地址,用库不会了,基础不牢,不要笑话,

出0入143汤圆

5
发表于 2022-9-13 15:57:40 | 只看该作者
你定义变量时,gImage_MM_T035这个变量就已经是4字节对齐了,直接把这个地址递交给DMA就行
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-3 19:23

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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