社区导航

 
快捷导航
  • 首页
  • 论坛
  • 查看新帖
  • 最新回复
  • 社区活动
  • 联系管理员
  • 消灭零回复
  • E金币兑换
  • 干货
搜索
查看: 3867|回复: 10

[求助] STM32F407 DMA串口接收数据,只能接收一次,然后数据就写不进缓存维持不变了

[复制链接]

15

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

发表于 2017-1-18 16:56:21 | 显示全部楼层 |阅读模式
5芯币
407串口1采用DMA收发数据,发送一切正常,接收有问题;接收采用串口的空闲中断来判断接收完成,程序下进去启动后第一次接收正常,往后就不行了,数据维持不变,不往缓存区写数据了;反真是能进串口空闲中断的,也参考了许多许多网上的例程,没有发现什么差异,不知道是哪里有问题。
这是我的中断处理函数:
void Receive_Data_IRQHandler(void)
{
        if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)  
    {  
        USART1->SR;  
        USART1->DR; //清USART_IT_IDLE标志  
        //关闭DMA  
        DMA_Cmd(DMA2_Stream2,DISABLE);  
        //清除标志位  
        DMA_ClearFlag(DMA2_Stream2,DMA_FLAG_TCIF4);  

                RS485_RX_CNT = 64 - DMA_GetCurrDataCounter(DMA2_Stream2);  

        //获得接收帧帧长  
      //  memcpy(buf,Rx_Buf_Gsm,len);  

        //设置传输数据长度  
        DMA_SetCurrDataCounter(DMA2_Stream2,64);  
        //打开DMA  
        DMA_Cmd(DMA2_Stream2,ENABLE);  
    }        
}



这是网上的中断处理函数:
  • uint8_t drv_gsm_deal_irq_rx_end(uint8_t *buf)  
  • {     
  •     uint16_t len = 0;  
  •       
  •     //接收完成中断  
  •     if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET)  
  •     {  
  •         USART2->SR;  
  •         USART2->DR; //清USART_IT_IDLE标志  
  •         //关闭DMA  
  •         DMA_Cmd(DMA1_Stream5,DISABLE);  
  •         //清除标志位  
  •         DMA_ClearFlag(DMA1_Stream5,DMA_FLAG_TCIF5);  
  •          
  •         //获得接收帧帧长  
  •         len = RX_LEN_GSM - DMA_GetCurrDataCounter(DMA1_Stream5);  
  •         memcpy(buf,Rx_Buf_Gsm,len);  
  •          
  •         //设置传输数据长度  
  •         DMA_SetCurrDataCounter(DMA1_Stream5,RX_LEN_GSM);  
  •         //打开DMA  
  •         DMA_Cmd(DMA1_Stream5,ENABLE);  
  •   
  •         return len;  
  •     }   
  •       
  •     return 0;  
  • }  

这是我的接收部分DMA配置:

        //串口收DMA配置   
    //启动DMA时钟  
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);  
    //DMA通道配置  
        while(DMA_GetCmdStatus(DMA2_Stream2) != DISABLE){}        //等待DMA可配置
    DMA_DeInit(DMA2_Stream2);  
    DMA_InitStructure.DMA_Channel = DMA_Channel_4;  
    //外设地址  
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART1->DR);  
    //内存地址  
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)RS485_RX_BUF;  
    //dma传输方向  
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;  
    //设置DMA在传输时缓冲区的长度  
    DMA_InitStructure.DMA_BufferSize =64;  
    //设置DMA的外设递增模式,一个外设  
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  
    //设置DMA的内存递增模式  
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  
    //外设数据字长  
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  
    //内存数据字长  
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;  
    //设置DMA的传输模式  
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;  
    //设置DMA的优先级别  
    DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;  

    //指定如果FIFO模式或直接模式将用于指定的流 : 不使能FIFO模式   
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;      
    //指定了FIFO阈值水平  
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;         
    //指定的Burst转移配置内存传输   
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;         
    //指定的Burst转移配置外围转移 */   
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;   

    //配置DMA1的通道           
    DMA_Init(DMA2_Stream2, &DMA_InitStructure);   
    //使能通道  
    DMA_Cmd(DMA2_Stream2,ENABLE);




如果把DMA_Mode 改成 DMA_Mode_Circular(循环接收) 则接收正常,单次模式真的只能接收一次,但在串口接收中断里明明已经重新设定了DMA传输数量并重新使能了。不解,有什么是我没考虑到的写的不对的,望指点。

以上


回复

使用道具 举报

130

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

发表于 2017-1-18 19:47:14 | 显示全部楼层
你DMA mode 设定的是DMA_Mode_Normal啊,也就是发送一次后DMA就停止循环了啊,串口就不会有新数据了,这没毛病啊。你换成Circular就一直循环。


回复

使用道具 举报

963

TA的帖子

1

TA的资源

版主

Rank: 6Rank: 6

发表于 2017-1-18 21:42:44 | 显示全部楼层
如果你要设置单次循环,必须重新设置内存地址DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)RS485_RX_BUF;  

点评

我试过接受完重新配置DMA,是可以的,问题是应该不需要啊,就是缓存区数组接收一次后指针不指向数组开头了  详情 回复 发表于 2017-1-20 11:01
那为什么我看别人例程都没设呢,我也想到了试缓存区地址指针不对,因为循环模式就正常,但别人的单次循环很正常啊。  详情 回复 发表于 2017-1-20 10:54


回复

使用道具 举报

15

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

 楼主| 发表于 2017-1-20 10:54:50 | 显示全部楼层
qwerghf 发表于 2017-1-18 21:42
如果你要设置单次循环,必须重新设置内存地址DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)RS485_RX ...

那为什么我看别人例程都没设呢,我也想到了试缓存区地址指针不对,因为循环模式就正常,但别人的单次循环很正常啊。

点评

我是实际用的代码,别人的不对  详情 回复 发表于 2017-1-20 10:59


回复

使用道具 举报

963

TA的帖子

1

TA的资源

版主

Rank: 6Rank: 6

发表于 2017-1-20 10:59:17 | 显示全部楼层
wk好好学习 发表于 2017-1-20 10:54
那为什么我看别人例程都没设呢,我也想到了试缓存区地址指针不对,因为循环模式就正常,但别人的单次循环 ...

我是实际用的代码,别人的不对

点评

这确实能解决问题,每次重新配置一下DMA  详情 回复 发表于 2017-1-20 11:10


回复

使用道具 举报

15

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

 楼主| 发表于 2017-1-20 11:01:10 | 显示全部楼层
qwerghf 发表于 2017-1-18 21:42
如果你要设置单次循环,必须重新设置内存地址DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)RS485_RX ...

我试过接受完重新配置DMA,是可以的,问题是应该不需要啊,就是缓存区数组接收一次后指针不指向数组开头了


回复

使用道具 举报

15

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

 楼主| 发表于 2017-1-20 11:07:57 | 显示全部楼层
关于STM32 DMA重新使能的话题  http://sanwen.net/a/jtjbspo.html
这篇文章好像和我的问题有关系,问题差不多,可是看得似懂非懂


回复

使用道具 举报

15

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

 楼主| 发表于 2017-1-20 11:10:50 | 显示全部楼层
qwerghf 发表于 2017-1-20 10:59
我是实际用的代码,别人的不对

这确实能解决问题,每次重新配置一下DMA


回复

使用道具 举报

12

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

发表于 2017-2-9 15:12:58 | 显示全部楼层
想求教一下楼主,我也遇到了这个问题,但是我的DMA_Mode 是DMA_Mode_Circular(循环接收),也是只能接收一次,设置的缓存区存满后,就不接收了,不知道楼主有没有遇到这种情况,想请教一下


回复

使用道具 举报

12

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

发表于 2017-2-9 16:48:34 | 显示全部楼层
刚刚又调试了一下,缓存区可以一直循环存放数据,然后我用的printf打印输出存在DMA缓存区的数据,printf打印输出显示到串口调试助手,一开始的数据是显示的,但是过了一段时间后printf就不工作了,想知道为什么


回复

使用道具 举报

1

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2017-2-10 09:40:55 | 显示全部楼层
F7中使用DMA操作SPI也遇到了这个问题,只有第一次DMA发送SPI成功,后面的数据就没有了
我每次发送DMA前都会重写传输数据寄存器的,应该不会有问题啊。
DMA.png


回复

使用道具 举报

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

本版积分规则

  • 论坛活动 E手掌握

    扫码关注
    EEWORLD 官方微信

  • EE福利  唾手可得

    扫码关注
    EE福利 唾手可得

小黑屋|手机版|Archiver|电子工程世界 ( 京ICP证 060456

GMT+8, 2018-2-25 06:01 , Processed in 0.307526 second(s), 16 queries , Redis On.

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