说明
硬件平台: STM32F103 系列
IDE: keil
策略:利用串口空闲中断实现接收不定长数据。假如串口在短时间内接收了 N 段数据,如果我们来不及处理接收的的数据。导致 DMA 接收缓存满了,(开启循环模式) DMA 会开始新的一轮传输,覆盖掉前面的数据。所以为了防止这种情况出现我们会使用多缓存(此例程使用了 4 个缓存。当然你也可以使用 N 个缓存,理论上是不限缓存数的),每接收到一段数据,就切换一次缓存。但是你的应用程序在处理接收到的缓存时,需要一次性把所有缓存的数据处理完,并且释放缓存。不支持缓存级别的先入先出队列。
技术点说明:要看懂这篇文章的,并且运用在实际工程中需要掌握以下 2 个技术点。
1 串口。主要是串口配置,这个很基础。
2 DMA 传输。这个其实也不复杂,看一下教程自己试着做个示例就基本掌握了,但是 DMA 的各种模式配置要都弄明白就有点繁琐,需要仔细看文档。对你的硬件的串口和 DMA 要很熟悉,下面我的示例代码注释会尽量“啰嗦”一些。
正题
第一步:串口的配置
串口配置和平时差不多,这里多了 1 个空闲中断。
//usart.c
空闲中断,就是串口在接收到一个或多个数据后,没有数据再传输过来。串口控制器检测到这个空闲时间段就产生中断。就是通过这个中断,我们才能实现接收不定长的数据。不管串口接收了多少字节的数据,只要接收停止,就产生中断,我们就知道有数据来了。
至于这个空闲时间,是超过接收 1bit 的时间。
串口中断表
![18066799c531a1f324e45135e3df6c94.png](https://i-blog.csdnimg.cn/blog_migrate/ba6e1193a8695d76e2c4842489d3033a.jpeg)
空闲中断
![1acdcd28a60d4075e95927c333065b98.png](https://i-blog.csdnimg.cn/blog_migrate/dac1911745c8335e96bf39c5d1b159ae.jpeg)
当然如果接收完一段数据,空闲中断产生,之后较长的时间内都没数据来,在这段时间是不会再产生空闲中断的。
第二步:DMA 配置
DMA 的不同通道对应串口的收和发,有时候我们只用到 DMA 的接收或发送,所以这个 DMA 配置函数有个参数用来开启相应的接收或发送。
//dma.c
DMA 通道对应的相关外设
![8d43181bfe73a6196cdb78a2b52d897a.png](https://i-blog.csdnimg.cn/blog_migrate/359576c059098befc5c3622c31fe6c97.jpeg)
通过 DMA 收/发串口的函数接口,接收缓存的切换也是通过这个函数实现的。
//dma.c
第三步:串口空闲中断处理
串口用到的结构体
//usart.h
串口1 中断服务函数
//usart.c
至此我们的相关代码就解说完了,下面还有最后一段应用层代码的说明。
第四步:应用层
//highVol.c
应用层函数我就不多介绍了,因为我们的主题是“串口基于 DMA 接收不定长数据”。至于接收到的数据用来做什么那就是大家的事了。之所以把这段代码贴出来,是为了有头有尾。
李晋文
2020年9月20日