关于使用IDLE中断与DMA实现USART不定长字符接收的问题。

之前做过一个多串口转发的东西,MCU用的STM32F407,串口每次接收到的字符长度不定。

通常的办法是使用RX中断,接到了个字符便转发一个字符。但是这有个缺点,每字符都中断会影响系统的性能,而且这种方式并不能分开每个字符串,如果是带格式的字符串,接收者无法对每一个字符串进行解析。

另外一种方式就是使用DMA+IDLE中断的方式,通过DMA接收数据,通过IDLE中断来确定收到一个完整的字串。这也算是一个比较成熟的方式了,网上有很多相关资料。通常的流程是先使能IDLE中断,使能并启动DMA接收,当IDLE中断到来时,由DMA缓冲区读取接收到的完整字串。如果字串的长度比较大,超过DMA缓冲区,那么就在DMA缓冲区满中断中将数据存到另外的地方,最后IDLE中断中再汇总即可。

我开始也是是按上述的原理进行编程的,发现实际运行中,会偶发字串被截断的情况,一开始我以为是程序逻辑的问题,找了半天没找到原因。后来调试时仔细想了一下,前面的运行方式是建立在每发一个字串只触发一次IDLE中断的基础上的,可是实际调试时,发现无论是PC主板自带的串口还是USB转出来的串口,并不能保证一个字符串中的字符可以连续不间断的发送出来。比如"123456789012345678901234567890"这三十个字符组成的字符串,某一次发送中有可能就会分成两串发送出来,两串中可能有一个很小的间隔,但是MCU只要检测到就会触发IDLE中断,于是从MCU这边看,就是字串被截断了。对于有格式的字串,直接结果就是格式错误。

知道这个原因后就好办了,我的解决方法是在IDLE中断并不处理接收到的字符串,而只是记录中断发生时的时间戳,比如systick。在mainloop中检测idle标志,只有当idle标志为真且时间间隔大于某一个值时才认为字串接收完整。我定的间隔是5ms,这样收到的字符串再也不会被截断了。

注意这个时间间隔与串口的波特率有关,可以自己试一试。

我把示例代码附在后面了,有兴趣的可以看一下,IAR工程,MCU是STM32F407

https://download.csdn.net/download/qqwwing/12466718

你可能感兴趣的:(关于使用IDLE中断与DMA实现USART不定长字符接收的问题。)