在嵌入式开发中,串口通信经常被广泛使用。不同的应用场景需要采用不同的方案。
今天我们将介绍一种高效、可靠、安全的方案,希望大家能够从中受益。
常见的串口通信方案包括串口轮询模式、串口中断模式、串口DMA接收传输等等。
利用串口的空闲中断结合DMA的环形缓冲区模式,可以实现高效接收不固定长度的消息报文。
在下图中,黄色部分表示空闲状态持续的时间,当空闲状态持续一段时间后,将会触发一个空闲事件,即IDLE EVENT。
空闲信号
因为DMA功能有HC
和TC
中断;
-
HC
(Harf Complete
)DMA传输一半成功标志; -
TC
(Total Complete
) DMA传输完成成功标志;
举个例子;
如下图所示,这里分配了一个DMA缓冲区,大小是12字节,如果从地址1开始接收,会出现以下这两种情况;
-
DMA接收到第6个字节的时候,会触发HC事件; -
DMA接收到第12个字节的时候,会触发TC事件;
HC TC
这个思路其实我之前也有实践过,但是没有很好地利用HC和TC事件。
所以无法处理这种情况,即DMA缓冲区处于环形模式(Circular
)的时候,数据覆盖的问题,最近看到了一个非常棒的开源项目,这里的思路非常不错,下面会详细介绍。
下面是DMA HC
/DMA TC
/Idle
组合进行串口接收的细节,如下图所示;
来自原项目
再次简单介绍一下缩略词的含义;
-
R
读取; -
W
写入; -
I
空闲信号; -
HT
Half-Transfer complete DMA缓冲区半传输完成; -
TC
Transfer-Complete DMA缓冲区全部接收完成;
这里简单介绍一下情况E的解决方案,上面图片最右边小图;
-
缓冲区大小20格,这里假设20字节,情况E需要接收30个字节,也就是说,10字节可能会被覆盖;
-
经过前面的四次接收后,串口继续从字母R处接收数据至DMA缓冲区;
-
接收4字节时,会触发
TC
事件,这时候可以将4字节数据处理;第一步
-
因为是环形模式,所以回到第一个字节处,继续接收10字节,触发
HT
事件,这时候可以处理10字节数据;第二步
-
第三步,继续接收10字节,触发
TC
事件,其中,已经有4字节被覆盖(下图橙色所示),因为之前这部分数据已经处理了,所以,即使覆盖也不影响;第三步
-
第四步,上述已经接收了24个字节,所以还有6个字节没有接收,后面接收会产生空闲信号,并对之前的数据区域进行覆盖,如下图示所示;
所以,不难发现,如果只使用空闲中断,如果需要接收的数据长度大于缓冲区,就会出现数据覆盖的情况,而加上DMA的HT和TC中断,就完美解决了这样的问题;
当然除了这些,还有很多优秀的方案,这个项目提供大量的例子。
项目地址:https://github.com/MaJerle/stm32-usart-uart-dma-rx-tx
项目主页
目前这个项目主要支持主流的STM32芯片平台和一些开发板上的测试DEMO,具体如下所示;
支持平台
相应的例子程序如下所示,除了裸机程序,还有环形缓冲区接收,轮询接收,DMA+空闲中断基于RTOS的模式接收,挺丰富的,可以参考一下;
例子程序
作者在 STM32F413-Nucleo 开发板进行程序的测试,发现优化效果很不错;
在115200
的串口波特率下,每秒发送1581个字节,大约142ms
;
-
不使用DMA,CPU负载14%; -
使用DMA,CPU负载0%;
以上就是良许教程网为各位朋友分享的Linu系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你 !