[STM32F1] 空闲中断+DMA双缓冲切换问题

[复制链接]
 楼主| djz1992 发表于 2020-10-13 09:46 | 显示全部楼层 |阅读模式
各位大佬好,@dirtwillfly @hgjinwei @icecut @m564522634 @tyw @ufbycd @xyz549040622 前阶段做了个DMA双缓冲,用着也还行,但是最近发现一个问题。
DMA在前第一次切换的时候会不成功。代码如下。
第一次进空闲中断时,数据在UartxRT->RxDMA_Buf,if(UartxRT->witchbuf==1)中,将缓冲区切换到UartxRT->RxDMA_Buf2.
第二次进空闲中断时,发现实际上数据还是接收到了UartxRT->RxDMA_Buf。此时运行的是else if(UartxRT->witchbuf==2)  ,再次切换到UartxRT->RxDMA_Buf。
第三次进空闲中断时,数据在UartxRT->RxDMA_Buf。然后再次切换到UartxRT->RxDMA_Buf2.
第四次进空闲中断时,发现数据在UartxRT->RxDMA_Buf2,以后的切换都正常。


问题来了,为什么第一次切换会不成功?此前初始化过串口,改了波特率,与这个有关?
  1. void UsartReceive_IDLE(UART_HandleTypeDef *huart,UartBufferTypedef *UartxRT )
  2. {
  3.         uint32_t temp;
  4.         if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET))                                //获取IDLE标志位,如果idle标志被置
  5.         {
  6.                 __HAL_UART_CLEAR_IDLEFLAG(huart);                                                                        //清除串口空闲标志
  7.                 HAL_UART_DMAStop(huart);
  8.                 temp=__HAL_DMA_GET_COUNTER(huart->hdmarx);                                                        //获取DMA中未传输的数据个
  9.                 UartxRT->RxDMALen =  MAX_RxDMA_BUFFER - temp;                                                        //总计数减去未传输的数据个数,得到已经接收的数据个

  10.                 if(UartxRT->witchbuf==1)                                                                        //之前用的buf1,切换为2
  11.                 {
  12.                         UartxRT->witchbuf=2;
  13.                         HAL_UART_Receive_DMA(huart,(uint8_t *)UartxRT->RxDMA_Buf2,MAX_RxDMA_BUFFER);        //重启串口DMA接收到buf2
  14.                         UartxRT->RxLen+=UartxRT->RxDMALen;
  15.                 }
  16.                 else if(UartxRT->witchbuf==2)                                                             //之前用的buf2,切换为buf1
  17.                 {
  18.                         UartxRT->witchbuf=1;
  19.                         HAL_UART_Receive_DMA(huart,(uint8_t *)UartxRT->RxDMA_Buf,MAX_RxDMA_BUFFER);                //重启串口DMA接收到buf1
  20.                         UartxRT->RxLen+=UartxRT->RxDMALen;
  21.                 }
  22.         }
  23. }



ufbycd 发表于 2020-10-15 16:12 | 显示全部楼层

c

本帖最后由 ufbycd 于 2020-10-15 16:20 编辑

个人觉得像串口这种低速外设,没必要搞双DMA这么复杂。越复杂越容易出错,一般串口通信也就115200bps,搞双DMA没什么意义。只有在点阵屏显示、摄像头等这些高速外设搞双DMA才有作用。

我一般都是用中断接收,把收到的数据丢到环形队列,最多开个定时器判断连续3.5个字节时间没有收到数据就当作是帧结尾,然后再取出队列的数据进行解析处理。

有了环形队列做缓存就已经可以一边接收一边处理不同的数据帧了,即便波特率上到1Mbps也处理得过来。

icecut 发表于 2020-10-16 10:40 | 显示全部楼层
witchbuf 初始值是啥?是不是初始化的时候设置错了?
zhuomuniao110 发表于 2020-10-18 22:57 | 显示全部楼层
不懂啥意思。
 楼主| djz1992 发表于 2020-10-19 09:37 | 显示全部楼层
本帖最后由 djz1992 于 2020-10-19 09:40 编辑
ufbycd 发表于 2020-10-15 16:12
个人觉得像串口这种低速外设,没必要搞双DMA这么复杂。越复杂越容易出错,一般串口通信也就115200bps,搞双 ...

是的呢,但是搞都搞了。。不想彻底改了。。。另外之前按教程改中断接收的时候老是会出错,好像是溢出错误,没办法又改了dma。能不能给个可用的例程。
 楼主| djz1992 发表于 2020-10-19 09:39 | 显示全部楼层
icecut 发表于 2020-10-16 10:40
witchbuf 初始值是啥?是不是初始化的时候设置错了?

witchbuf 初始值是1,启动DMA接收的时候也是缓冲区1
        Uart1RT.witchbuf=1;
        HAL_UART_Receive_DMA(&huart1,Uart1RT.RxDMA_Buf,MAX_RxDMA_BUFFER);//
wowu 发表于 2020-11-12 12:29 | 显示全部楼层
问题好深奥哎
xiaoqizi 发表于 2020-11-12 12:31 | 显示全部楼层
这个是个别现象?
木木guainv 发表于 2020-11-12 12:33 | 显示全部楼层
看了 讨论 我也是长知识了
磨砂 发表于 2020-11-12 12:35 | 显示全部楼层
每轮现象都一样?
晓伍 发表于 2020-11-12 12:35 | 显示全部楼层
跟波特率没关系
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:人生苦短,冬日苦长,正是青葱,却无骄阳

115

主题

620

帖子

5

粉丝
快速回复 在线客服 返回列表 返回顶部
个人签名:人生苦短,冬日苦长,正是青葱,却无骄阳

115

主题

620

帖子

5

粉丝
快速回复 在线客服 返回列表 返回顶部