这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » STM32 » 串口工作在DMA模式下有时接收异常的案例分享

共4条 1/1 1 跳转至

串口工作在DMA模式下有时接收异常的案例分享

管理员
2017-03-12 18:36:40     打赏

前言

客户反馈在使用STM32F205的串口工作在DMA模式时,有时能够接收数据,有时完全没有数据,但如果换成中断模式来接收又能100%正常收到数据。

问题背景

与客户沟通,客户使用的是STM32F2标准库V1.1.0,串口波特率为1.408Mbps,不经过串口RS232,直接连接主CPU和从MCU(STM32F205)的串口发送和接收引脚,如下图所示:

一、问题重现

由于客户使用的是主从架构,实验就采用两块STM3220G-EVAL评估板来重现现象。一块用来不间断发送串口数据,另一块采用串口DMA进行接收,直接通过杜邦线连接串口PIN脚并共地,不使用评估板上的RS232收发器。接收端使用STM32F2xx_StdPeriph_Examples\USART\USART_TwoBoards的示例代码。

经过对代码进行比较测试,发现如下现象:

1先启动接收端板再启动发送端板,接收端MCU的串口能正常接收。

2先启动发送端板再启动接收端板,接收端MCU的串口100%接收异常。

3对发送端代码稍作修改,让发送端MCU串口每间隔1秒发送一次,则无论启动先后顺序如何,接收端的串口都正常。


二、 程序分析

接收端的程序是先在USART_Config()函数内初始化串口并使能,然后在main()while循环内初始化DMA并使能。这个是标准库内附带的示例代码,咋看没什么问题,但仔细一想,针对用户的使用场景还是有个隐患:

因为用户的主CPU有可能在从MCU启动之前就已经启动,那么在接收端MCU从初始化串口并使能,到DMA配置及使能的这段时间内,若主CPU向从MCU发送串口数据,就可能出问题。

从上面的测试结果2也可以证实,若在接收端串口初始化并使能到DMA使能就绪之前有数据过来,它是不能正确接收的。经进一步调试发现,此时数据寄存器USART_DR已经存在数据,且状态寄存器USART_SR中ORE值为1


由于发送端与接收端在启动及操作上的时序差,当接收端的串口接收寄存器中已收到数据时,由于接收DMA未及时开启就绪,但后面的数据又来了,导致后面的数据无法存入,进而产生了上溢错误(ORE)。而一旦产生上溢错误,就无法再触发DAM请求,即使之后再启动DMA也不行,无法触发DMA请求就无法将数据寄存器内的数据及时转移走,如此陷入死锁。这也就是串口无法正常接收的原因。


继续针对上面的测试情形3,做进一步的分析和探讨。

测试过程中,尽管启动两块板顺序随意,但启动先后时间差很小,发送端的1s延时让接收端有足够时间去完成串口初始化及DMA准备,所以每次接收正常。

那么,如果主从段各自启动时间随机,即使发送端辅以延时发送,还是会存在不能正常接收的情况。因为根本上讲,是否能正常接收完全取决于发送的时间点是落在接收端的串口初始化及使能到DMA使能就绪之前还是之后。这个时间窗口非常关键。如果刚好在时间窗内,那么串口DMA接收就会不正常,如果在这个时间窗之后,串口就能正常接收。

实际应用中主从端的启动时间差以及发送的时机往往是随机的,那如何彻底解决这个问题呢?


三、 问题处理

处理有两种方法,第一种方法是在使能DMA后,及时将数据寄存器DR中的数据清除掉,如下参考代码所示:

...

/* Enable the DMA Stream */

DMA_Cmd(USARTx_RX_DMA_STREAM, ENABLE);

/* Enable the USART Rx DMA requests */

USART_DMACmd(USARTx, USART_DMAReq_Rx , ENABLE);

while(SET==USART_GetFlagStatus(USARTx,USART_FLAG_ORE))

{

Tmp =USART_ReceiveData(USARTx);

}

...

这里是使用读DR的方法来清除的,参考手册中有清除ORE标志的相关描述。

上面提到的方法类似于一种纠错措施,下面介绍另一种推荐的方法,如下参考代码所示:

...

/* Enable the DMA Stream */

DMA_Cmd(USARTx_RX_DMA_STREAM, ENABLE);

/* Enable the USART Rx DMA requests */

USART_DMACmd(USARTx, USART_DMAReq_Rx ,ENABLE);

USART_Cmd(USARTx, ENABLE); //

...

让接收端的DMA使能先于UART的使能,这样就不存在前面提到的那个时间窗了。只要UART接收到了数据,就能被DAM及时转走。这个是推荐的解决方法。


四、 结论

ST官方参考库中的示例代码整体上讲都是可供参考的,绝大部分情况都能正常工作,实现基本功能的演示。但由于具体应用千变万化,不保证代码适应所有应用状况。此时更需要我们针对问题进行具体问题具体分析,适当调整软硬件来解决问题。

 

转载自STM32官方微信公众号




关键词: 串口     异常     USART     启动    

专家
2017-03-12 21:54:10     打赏
2楼
原来如此,谢谢楼主提醒。

高工
2017-03-19 14:00:21     打赏
3楼
熊猫辛苦

助工
2017-03-22 08:41:33     打赏
4楼
每天学点经验少走弯路。。。哈哈

共4条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]