OpenEdv-开源电子网

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

STM32F407 DMA串口接收数据,只能接收一次,然后数据就维持不变了

[复制链接]

3

主题

7

帖子

0

精华

新手上路

积分
41
金钱
41
注册时间
2016-10-20
在线时间
9 小时
发表于 2017-1-18 16:54:52 | 显示全部楼层 |阅读模式
10金钱
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传输数量并重新使能了。不解,有什么是我没考虑到的写的不对的,望指点。

以上

QQ截图20170118162742.png
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

23

主题

69

帖子

0

精华

新手上路

积分
26
金钱
26
注册时间
2017-1-5
在线时间
50 小时
发表于 2017-1-19 09:16:42 | 显示全部楼层
回复

使用道具 举报

58

主题

6293

帖子

1

精华

资深版主

Rank: 8Rank: 8

积分
11476
金钱
11476
注册时间
2014-4-1
在线时间
1297 小时
发表于 2017-1-19 10:51:55 | 显示全部楼层

帮你理理物理过程:
串口接收以后,数据存放在DR寄存器,
“接收成功”触发DMA动作,把数据从DR搬走。

所以,进入中断并不意味着DMA完成,在中断理关DMA是错误的。

回复

使用道具 举报

58

主题

6293

帖子

1

精华

资深版主

Rank: 8Rank: 8

积分
11476
金钱
11476
注册时间
2014-4-1
在线时间
1297 小时
发表于 2017-1-19 10:54:51 | 显示全部楼层

一个经验:
用F4做DMA时,发现芯片的一个问题,
DMA运行期间,一旦在仿真器断点停过,再次连续运行时DMA已经错了,必须复位重新走。

所以,仿真时,要在适当的位置设断点。

回复

使用道具 举报

3

主题

7

帖子

0

精华

新手上路

积分
41
金钱
41
注册时间
2016-10-20
在线时间
9 小时
 楼主| 发表于 2017-1-20 11:11:00 | 显示全部楼层
xuande 发表于 2017-1-19 10:54
一个经验:
用F4做DMA时,发现芯片的一个问题,
DMA运行期间,一旦在仿真器断点停过,再次连续运行时DM ...

好的,谢谢提醒
回复

使用道具 举报

14

主题

171

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
450
金钱
450
注册时间
2017-3-31
在线时间
118 小时
发表于 2017-4-7 16:02:50 | 显示全部楼层
楼主,你程序里有USART_IT_IDLE中断处理程序,为啥没见清标志位?除了读SR和DR,不需要USART_ClearITPendingBit(USART2, USART_IT_IDLE);这句么?
回复

使用道具 举报

12

主题

38

帖子

0

精华

初级会员

Rank: 2

积分
129
金钱
129
注册时间
2015-9-6
在线时间
25 小时
发表于 2017-4-9 01:01:48 | 显示全部楼层
遇到同样的问题,不过我是SPI+DMA
回复

使用道具 举报

14

主题

171

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
450
金钱
450
注册时间
2017-3-31
在线时间
118 小时
发表于 2017-4-10 10:48:31 | 显示全部楼层
小米已被注册 发表于 2017-4-9 01:01
遇到同样的问题,不过我是SPI+DMA

清DMA中断标致位了么
回复

使用道具 举报

12

主题

38

帖子

0

精华

初级会员

Rank: 2

积分
129
金钱
129
注册时间
2015-9-6
在线时间
25 小时
发表于 2017-4-11 13:34:45 | 显示全部楼层
Owen 发表于 2017-4-10 10:48
清DMA中断标致位了么

这个必须清楚啊,现在维持不变的问题解决了,看文档应该是没有等发送完就关闭dma了,现在出现的问题就是数据要错位。。。唉,恼火
回复

使用道具 举报

12

主题

38

帖子

0

精华

初级会员

Rank: 2

积分
129
金钱
129
注册时间
2015-9-6
在线时间
25 小时
发表于 2017-4-11 13:47:30 | 显示全部楼层
Owen 发表于 2017-4-10 10:48
清DMA中断标致位了么

不过基本可以使用,只是一直感觉传输速率没有最大化
回复

使用道具 举报

14

主题

171

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
450
金钱
450
注册时间
2017-3-31
在线时间
118 小时
发表于 2017-4-11 14:31:21 | 显示全部楼层
小米已被注册 发表于 2017-4-11 13:34
这个必须清楚啊,现在维持不变的问题解决了,看文档应该是没有等发送完就关闭dma了,现在出现的问题就是 ...

数据错位?你配置时钟()RCC)了么?我现在USART也是一直错位,不过是因为时钟没配置好,波特率一直不对
回复

使用道具 举报

12

主题

38

帖子

0

精华

初级会员

Rank: 2

积分
129
金钱
129
注册时间
2015-9-6
在线时间
25 小时
发表于 2017-4-11 15:37:10 | 显示全部楼层
Owen 发表于 2017-4-11 14:31
数据错位?你配置时钟()RCC)了么?我现在USART也是一直错位,不过是因为时钟没配置好,波特率一直不对

我也解决了,出错的地方就是上一次通信数据有残余,然后就跑到下一次通信去了,具体的是SPI那个移位寄存器相关的。。
回复

使用道具 举报

14

主题

171

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
450
金钱
450
注册时间
2017-3-31
在线时间
118 小时
发表于 2017-4-11 16:10:22 | 显示全部楼层
小米已被注册 发表于 2017-4-11 15:37
我也解决了,出错的地方就是上一次通信数据有残余,然后就跑到下一次通信去了,具体的是SPI那个移位 ...

...不错啊
回复

使用道具 举报

0

主题

7

帖子

0

精华

新手上路

积分
43
金钱
43
注册时间
2018-4-17
在线时间
7 小时
发表于 2018-4-26 00:16:11 | 显示全部楼层
楼主,这个问题我在F207上面也遇到了,请问你最早是如何解决的?谢谢
回复

使用道具 举报

5

主题

10

帖子

0

精华

初级会员

Rank: 2

积分
119
金钱
119
注册时间
2016-7-24
在线时间
36 小时
发表于 2018-7-20 10:21:12 | 显示全部楼层
DMA_ClearFlag(DMA2_Stream2,DMA_FLAG_TCIF4)   改成 TCIF2
回复

使用道具 举报

27

主题

132

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
328
金钱
328
注册时间
2018-7-20
在线时间
117 小时
发表于 2018-8-16 18:05:38 | 显示全部楼层
F103上面也有这样的问题,只传输一个字节之后,DMA就不再收数据了,用在USART2接收数据上面,到现在还没有解决
我只喜欢喜欢我的人
回复

使用道具 举报

9

主题

44

帖子

0

精华

初级会员

Rank: 2

积分
166
金钱
166
注册时间
2015-12-30
在线时间
32 小时
发表于 2018-8-17 10:28:48 | 显示全部楼层
使用DMA串口接收最好采用循环方式,上位机定好协议一次传多少字节,收完了进DMA中断处理,不用循环方式处理完后要重新开启DMA接受
回复

使用道具 举报

9

主题

44

帖子

0

精华

初级会员

Rank: 2

积分
166
金钱
166
注册时间
2015-12-30
在线时间
32 小时
发表于 2018-8-17 10:30:11 | 显示全部楼层
用DMA传送数据统统进DMA的传输完成中断比较方便,串口中断就不要理会她,里面就写一个清楚标志位就行
回复

使用道具 举报

17

主题

170

帖子

0

精华

高级会员

Rank: 4

积分
562
金钱
562
注册时间
2018-7-8
在线时间
118 小时
发表于 2018-11-19 10:20:23 | 显示全部楼层
同问,请问如何解决啊?改为循环模式就可以正常了,为什么啊,论坛上的实例都是正常模式的,一直到407后,就不行了。
回复

使用道具 举报

2

主题

474

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6252
金钱
6252
注册时间
2018-6-27
在线时间
534 小时
发表于 2018-12-13 15:46:25 | 显示全部楼层
这个比较晕,学习学习。
回复

使用道具 举报

2

主题

46

帖子

0

精华

初级会员

Rank: 2

积分
140
金钱
140
注册时间
2014-8-31
在线时间
33 小时
发表于 2019-7-7 13:06:19 | 显示全部楼层
想问下楼主的问题解决了没?最近也遇到了一样的问题咧
回复

使用道具 举报

1

主题

5

帖子

0

精华

初级会员

Rank: 2

积分
57
金钱
57
注册时间
2020-5-11
在线时间
14 小时
发表于 2021-5-12 16:54:55 | 显示全部楼层
xuande 发表于 2017-1-19 10:51
帮你理理物理过程:
串口接收以后,数据存放在DR寄存器,
“接收成功”触发DMA动作,把数据从DR搬走。
...

请教一下,DMA动作过程是否是串口接收一字节数据,DMA动作一次,将数据放入目标地址?如果是这样,进入中断后就只剩下最后接收的一个字节没有放入目标地址中。在中断函数中设定适当的延时(即足够DMA搬运一字节的时间),然后关闭DMA接收是否可行?

回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165377
金钱
165377
注册时间
2010-12-1
在线时间
2111 小时
发表于 2021-5-13 01:48:22 | 显示全部楼层
yixiaojue 发表于 2021-5-12 16:54
请教一下,DMA动作过程是否是串口接收一字节数据,DMA动作一次,将数据放入目标地址?如果是这样,进入中 ...

你用了DMA,就不需要开串口接收中断了,DMA比你中断处理快。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

1

主题

5

帖子

0

精华

初级会员

Rank: 2

积分
57
金钱
57
注册时间
2020-5-11
在线时间
14 小时
发表于 2021-5-13 09:11:26 | 显示全部楼层
正点原子 发表于 2021-5-13 01:48
你用了DMA,就不需要开串口接收中断了,DMA比你中断处理快。

我用的是DMA+空闲中断接收不定长数据
回复

使用道具 举报

58

主题

6293

帖子

1

精华

资深版主

Rank: 8Rank: 8

积分
11476
金钱
11476
注册时间
2014-4-1
在线时间
1297 小时
发表于 2021-5-13 11:26:17 | 显示全部楼层
yixiaojue 发表于 2021-5-12 16:54
请教一下,DMA动作过程是否是串口接收一字节数据,DMA动作一次,将数据放入目标地址?如果是这样,进入中 ...


道理上可以。

但是这样的行为是很扭曲的。


回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-2-27 20:48

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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