搜索
bottom↓
回复: 4

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

[复制链接]

出0入0汤圆

发表于 2013-3-20 09:51:35 | 显示全部楼层 |阅读模式
各位大神们!

小弟用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停止后启动时间大概多长?貌似手册上没有说明

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

 楼主| 发表于 2013-3-20 11:06:11 | 显示全部楼层
打开溢出(ORN)中断 再清除ORN标志,治标不治本。
会丢失500个Byte

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


难道没其它办法了吗? 非要用中断接收?  
230400的波特率采用中断接收不知道对整个系统的稳定性影响大不

出0入0汤圆

发表于 2014-5-14 11:21:32 | 显示全部楼层
我的串口4 DMA发送方式,进不去发送中断,楼主可知道方法
邮箱:baoj.zhang@gmail.com

出0入0汤圆

发表于 2014-5-14 11:50: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将对应数组的值复制出来或者直接处理数组中的值。

你可以根据自己项目和硬件资源的需要对以上步骤进行个性化实现。

出0入4汤圆

发表于 2018-12-3 08:49:22 来自手机 | 显示全部楼层
DMA轮训打开,溢出就少了
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-18 23:28

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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