单片机高负载串口通信,如何设计可靠的方案?

福利干货,第一时间送达

1 前言

直接存储器访问(Direct Memory Access),简称DMA。DMA是CPU一个用于数据从一个地址空间到另一地址空间“搬运”(拷贝)的组件,数据拷贝过程不需CPU干预,数据拷贝结束则通知CPU处理。

因此,大量数据拷贝时,使用DMA可以释放CPU资源。DMA数据拷贝过程,典型的有:

  • 内存—>内存,内存间拷贝

  • 外设—>内存,如uart、spi、i2c等总线接收数据过程

  • 内存—>外设,如uart、spi、i2c等总线发送数据过程

2 串口有必要使用DMA吗

串口(uart)是一种低速的串行异步通信,适用于低速通信场景,通常使用的波特率小于或等于115200bps。

对于小于或者等于115200bps波特率的,而且数据量不大的通信场景,一般没必要使用DMA,或者说使用DMA并未能充分发挥出DMA的作用。

对于数量大,或者波特率提高时,必须使用DMA以释放CPU资源,因为高波特率可能带来这样的问题:

  • 对于发送,使用循环发送,可能阻塞线程,需要消耗大量CPU资源“搬运”数据,浪费CPU

  • 对于发送,使用中断发送,不会阻塞线程,但需浪费大量中断资源,CPU频繁响应中断;以115200bps波特率,1s传输11520字节,大约69us需响应一次中断,如波特率再提高,将消耗更多CPU资源

  • 对于接收,如仍采用传统的中断模式接收,同样会因为频繁中断导致消耗大量CPU资源

因此,高波特率场景下,串口非常有必要使用DMA。

3 实现方式

5.1 基本流程

即是数据搬运到buf大小的一半时,可以产生一个中断信 。基于这个机制,我们可以实现双缓存功能,只需将buf空间开辟大一点即可。

【1】第一步,DMA将数据搬运完成buf的前一半时,产生“半满中断”,CPU来拷贝buf前半部分数据

【2】第二步,DMA继续将数据搬运到buf的后半部分,与CPU拷贝buf前半部数据不会冲突

【3】第三步,buf后半部分数据搬运完成,触发“溢满中断”,CPU来拷贝buf后半部分数据

【4】执行完第三步,DMA返回执行第一步,一直循环

DMA 错误中断,一般用于前期调试使用,用于检查DMA出现错误的次数,发布软件可以不使能该中断。

5.3 接收处理

基于上述描述机制,DMA方式接收串口数据,有三种中断场景需要CPU去将buf数据拷贝到fifo中,分别是:

  • DMA通道buf溢满(传输完成)场景

  • DMA通道buf半满场景

  • 串口空闲中断场景

前两者场景,前面文章已经描述。串口空闲中断指的是,数据传输完成后,串口监测到一段时间内没有数据进来,则触发产生的中断信 。

5.3 .1 接收数据大小

数据传输过程是随机的,数据大小也是不定的,存在几类情况:

  • 数据刚好是DMA接收buf的整数倍,这是理想的状态

  • 数据量小于DMA接收buf或者小于接收buf的一半,此时会触发串口空闲中断

因此,我们需根据来计算当前接收的数据大小。

DMA通道buf溢满场景计算

DMA通道buf溢满中断处理函数:

串口空闲中断场景计算

串口空闲中断场景的接收数据计算与“DMA通道buf半满场景”计算方式是一样的。

串口空闲中断处理函数

注:串口空闲中断处理函数,除了将数据拷贝到串口接收fifo中,还可以增加特殊处理,如作为串口数据传输完成标识、不定长度数据处理等等。

5.3.2 接收数据偏移地址

将有效数据拷贝到fifo中,除了需知道有效数据大小外,还需知道数据存储于DMA 接收buf的偏移地址。

有效数据偏移地址只需记录上一次接收的总大小即,可,在DMA通道buf全满中断处理函数将该值清零,因为下一次数据将从buf的开头存储。

在DMA通道buf溢满中断处理函数中将数据偏移地址清零:

关键步骤

【1】初始化串口

【2】使能串口DMA发送模式

【3】配置DMA发送通道,这一步无需在初始化设置,有数据需要发送时才配置使能DMA发送通道

UART2 DMA模式发送配置代码如下,与其他外设使用DMA的配置基本一致,留意关键配置:

  • 串口发送是,DMA通道工作模式设为单次模式(正常模式),每次需要发送数据时重新配置DMA

  • 使能DMA通道传输完成中断,利用该中断信息处理一些必要的任务,如清空发送状态、启动下一次传输

  • 启动DMA通道前清空相关状态标识,防止首次传输错乱数据

6.3 发送处理

串口待发送数据存于发送fifo中,发送处理函数需要做的的任务就是循环查询发送fifo是否存在数据,如存在则将该数据拷贝到DMA发送buf中,然后启动DMA传输。

前提是需要等待上一次DMA传输完毕,即是DMA接收到DMA传输完成中断信 。

串口发送处理函数:

上述串口发送处理函数可以在几种情况调用:

  • 主线程任务调用,前提是线程不能被其他任务阻塞,否则导致fifo溢出

  • DMA通道传输完成中断中调用

    —— The End ——

    往期推荐

    量子充电,9秒充满一辆车!这是玄学p>

    GD32替换STM32,有哪些区别坑你别踩…

    高效解析单片机通讯协议,最实用的一个方法

    最适合单片机的通信协议,如何设计p>

    4600万台销量!树莓派炼成之路

    好工具,不私藏!介绍一个提高效率的利器

    点击下方名片关注我

    文章知识点与官方知识档案匹配,可进一步学习相关知识Java技能树首页概览92461 人正在系统学习中

    声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2022年2月26日
下一篇 2022年2月26日

相关推荐