STM32 UART DMA方式,如何避免出现数据过载错误

2019-12-15 10:58发布

各位大神们!

小弟用STM32 UART4接收(用DMA方式)串口WIFI模块数据时  UART4 有时会出现过载错误

现象描述:
WIFI模块是接收/发送 实时音频传输的数据,8K采样率,每采集500个字节对方发送一次
UART4 DMA方式接收 波特率:230400  
  接收方法:当UART4总结空闲标志置1了,才去读取DMA接收到的数据

串口WIFI模块的数据量:
网络良好时: 每隔40ms有会500Byte数据
网络较差时:每隔40ms左右会有500个Byte,但500Byte可能会被分成十多次从WIFI模块串口发送出来,每次发送的间隔有几毫秒甚至底于1毫秒
                   (过载错误时基本上是在这个情况下出现的)
网络很差时:有时连续几百毫秒都没数据,突然3000左右字节连接发送过来
注:以上情况是用示波器观察到的

代码如下:
  1. /*****************************************************
  2. ** 查询DMA接收数据的状态
  3. ** buff: 存储接收到的数据
  4. ** 返回:没有接收数据返回0
  5.          否则返回接收到数据的个数
  6. *****************************************************/
  7. unsigned short Receive_UART4(unsigned char *buff)
  8. {
  9.         unsigned short remaining,i,num;
  10.         static unsigned short count = UART4_RX_SIZE;
  11.         if(USART_GetFlagStatus(UART4,USART_FLAG_IDLE))
  12.         {
  13.                 //思想:Receive_UART4函数每隔2ms调度1次,
  14.                 //若两次调度期间接收到的数据的数量没有发送变化。
  15.                 //则串口处于空闲状态;即可复制DMA传输的数据
  16.                 remaining = DMA_GetCurrDataCounter(DMA2_Channel3);
  17.                 if((remaining == UART4_RX_SIZE) || (count != remaining))               
  18.                          count = remaining;
  19.                 else
  20.                 {
  21.                         num = (UART4_RX_SIZE - remaining);
  22.                         //再次判断总线是否空闲
  23.                         if(!USART_GetFlagStatus(UART4,USART_FLAG_IDLE))
  24.                                 return 0;
  25.                         DMA2_Channel3->CCR   &= ~(1 << 0);        //停止DMA
  26.                         for(i = 0; i < num; i++)
  27.                         {
  28.                                 buff[i] = UART4_RxBuff[i];
  29.                         }
  30.                         DMA2_Channel3->CNDTR = UART4_RX_SIZE;         //设置DMA传输大小
  31.                         DMA2_Channel3->CMAR  = (unsigned long)UART4_RxBuff; //设置DMA缓存
  32.                         DMA2_Channel3->CCR   |= (1 << 0);          //启动DMA
  33.                         return num;               
  34.                 }
  35.         }
  36.         return 0;       
  37. }
复制代码请教各位,这种环境下如何避免UART的数据过载现象?
另外,DMA停止后启动时间大概多长?貌似手册上没有说明
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
4条回答
danshi126
1楼-- · 2019-12-15 16:00
打开溢出(ORN)中断 再清除ORN标志,治标不治本。
会丢失500个Byte

清除ORN方法:
i = *(volatile unsigned long *)UART4->SR;
i = UART4->DR;


难道没其它办法了吗? 非要用中断接收?  
230400的波特率采用中断接收不知道对整个系统的稳定性影响大不
devinzhang
2楼-- · 2019-12-15 16:04
我的串口4 DMA发送方式,进不去发送中断,楼主可知道方法
邮箱:baoj.zhang@gmail.com
chencc8
3楼-- · 2019-12-15 19:15
你的RAM都不够大,够大的话使用多缓存,或者双缓存。
我文字描述下。
1、创建二维数组xxxxx
和数组的第一维度写索引BuffWirteIndex=0;//指向第一个数组
数组的第一维度读索引BuffReadIndex=0;
当前接收到的数据量BuffRcvNum = 0;
2、初始化DMA,将写入地址设置到&xxxxx[BuffWirteIndex][0];
3、在两个位置处理接收的情况
一个类似于你LZ位的程序,当一定时间没接收到数据,就将BuffWirteIndex+1;
初始化DMA,将写入地址设置到&xxxxx[BuffWirteIndex][0];
BuffReadIndex = BuffWirteIndex;
给BuffRcvNum赋值。

另外一个在DMA溢出中断中,不同点是BuffRcvNum的大小不用算,直接赋原先定义的大小。

4、后台可以查询BuffRcvNum的大小,有数据的话就用BuffReadIndex将对应数组的值复制出来或者直接处理数组中的值。

你可以根据自己项目和硬件资源的需要对以上步骤进行个性化实现。
SCREA
4楼-- · 2019-12-15 20:01
 精彩回答 2  元偷偷看……

一周热门 更多>