OpenEdv-开源电子网

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

F4 DMA双缓冲的使用心得

[复制链接]

42

主题

297

帖子

0

精华

高级会员

Rank: 4

积分
994
金钱
994
注册时间
2016-7-22
在线时间
318 小时
发表于 2016-11-18 14:16:41 | 显示全部楼层 |阅读模式
1金钱
本帖最后由 hi我歌月徘徊 于 2016-11-18 14:26 编辑

使用了串口接收DMA,DMA初始化
[mw_shl_code=c,true]DMA_InitTypeDef  DMA_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
        if((u32)DMA_Streamx>(u32)DMA2)
        {
          RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);
               
        }else
        {
          RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);
        }
  DMA_DeInit(DMA_Streamx);
        
        while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE){}
        

  DMA_InitStructure.DMA_Channel = chx;
  DMA_InitStructure.DMA_PeripheralBaseAddr = par;
  DMA_InitStructure.DMA_Memory0BaseAddr = mar;                                    //(1)
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//串口接收--内存
  DMA_InitStructure.DMA_BufferSize = ndtr;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//内存自增
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//使能双缓冲模式,将会自动设置为循环模式,参考手册9.3.8提到了
  DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_Init(DMA_Streamx, &DMA_InitStructure);
        
        NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream5_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;               
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        
        NVIC_Init(&NVIC_InitStructure);        
        
        DMA_DoubleBufferModeConfig(DMA2_Stream5,(uint32_t)RxBuff2, DMA_Memory_0);    //(2)设置第二缓冲区地址和选定当前缓冲区
  DMA_DoubleBufferModeCmd(DMA2_Stream5,ENABLE);                                          // (3) 使能

        DMA_ITConfig(DMA2_Stream5,DMA_IT_TC,ENABLE);//发送完成中断 当DMA_BufferSize =0才算发送完成
                  
  DMA_Cmd(DMA2_Stream5,ENABLE);[/mw_shl_code]

双缓冲模式只需要增加代码中的(2)(3),即可。
两个缓冲区,buff1和buff2,当dma完成以后,自动切换buff2当中继续存储
比如 buff1【1000】,buff2【1000】,DMA_BufferSize =100;发送100个字节到到了buff1,dma就自动将目标地址设为buff2,那么你在发送100字节就到了buff2当中了,如此循环。

但是假如我换一种方式,每当串口来一次数据,我就换一次缓冲区,
比如第一次数据,dma到了buf1;第二次数据,dma到了buf2,第三次数据,又到了buf1,但是buf1当中第一次的数据就会被覆盖。怎么样才能不被覆盖呢?

打开了串口空闲中断,
每当串口空闲中断的时候,都会将当前buff切换,比如初始化dma时,当前buff为buff1,那么空闲中断中将当前buff设为buff2第一次串口助手发送:0 1 2 3
接收:
          buff1:0 1 2 3
          buff2:0 0 0 0
空闲中断,设置当前buff为 buff2

第二次串口助手发送:0 1 2 3
          buff1:0 1 2 3  (第一次发送的值)
          buff1 : 0 1 2 3
空闲中断,设置当前buff为buff1

第三次串口助手发送:0 1 2 3
          buff1:0 1 2 3       此时buff1中收到的值被更新覆盖,其实我想达到的效果为  buff1:0 1 2 3 0 1 2 3   数组指针后移,本来设置的就是内存地址自增(同一个缓冲区内存是自增的),但是一切换缓冲区,内存地址都会从0开始的!!!
          buff1 : 0 1 2 3 (第二次发送的值)
怎么解决这个问题呢??  总不能每次中断都把数据取出来吧?这样也太浪费时间了。还有一种方法,就是在指定缓冲区的时候,把内存基地址在指定一下(buf1地址+上一次收到的数据个数),简单试了一下:
                        DMA_Cmd(DMA2_Stream5, DISABLE);
                        rx_num=SEND_BUF_SIZE-DMA_GetCurrDataCounter(DMA2_Stream5);//获得接收数据项数
                        DMA2_Stream5->CR |= (uint32_t)(DMA_SxCR_CT); /* Set Memory 1 as current memory address */
                        DMA2_Stream5->M0AR=(uint32_t)&RxBuff2+rx_num;     当前buff存储位置=buff2基地址+上一次接收数据个数
                        DMA_Cmd(DMA2_Stream5, ENABLE);  

这样也可实现,但是数据如果多了 感觉很麻烦了。。。。
请问大神有没有什么好的办法呢? 感激不尽




最佳答案

查看完整内容[请看2#楼]

还是用查询的方式把数据取出吧
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

42

主题

297

帖子

0

精华

高级会员

Rank: 4

积分
994
金钱
994
注册时间
2016-7-22
在线时间
318 小时
 楼主| 发表于 2016-11-18 14:16:42 | 显示全部楼层
还是用查询的方式把数据取出吧
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-5-14 18:32

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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