#申请原创# 串口是MCU当中最通用的外设之一了,一般在使用一款单片机时,都会先调通串口,串口说简单也简单,但要高效的使用串口,就需要配合其他外设一起使用了。我们先看看AT32F425这款芯片的外设资源 我们可以看到,这款芯片有4组串口,和1个7通道,并支持弹性映射的的DMA, 对MCU熟悉的人都应该清楚,串口常见的应用方式有 查询 中断和DMA这几种,从对CPU占用角度看,DMA方式< 中断方式 < 查询方式。 我将介绍一种利用DMA实现双缓冲的高效串口收发方式,这种方式是建立在DMA基础上的,如果没有DMA就没法应用我这种方式了。为了实现双缓冲,我们需要利用DMA的如下特性 我要利用DMA的半传输和传输完成中断实现一次传输的2次相应过程,从而实现双缓冲,但由于DMA传输的次数是要预先设定的,对串口发送来说,还是没问题的,因为要发送的数据长度,你是知道的。但如果要接收不固定长度的数据,想要利用DMA来处理就比较麻烦了。如果遇到这种情况,就要用到串口本身的一种特性了 这里我要利用串口空闲中断弥补DMA不能接收不定长度数据的问题,当接收的数据没有达到触发DMA半传输和传输完成中断时,使用串口空闲中断来结束这帧数据的传输。整个收发方式的思路就是这样了,我们看看代码如何实现吧 由于整个方式都是在中断中实现的,main函数中主要是对DMA和串口的初始化。 以串口1为例,DMA配置如图所示。 将串口1的TX绑定到DMA的CH3上,由于DMA支持弹性映射,也可以根据需求绑定到其他通道上,DMA发送完成中断这里没有开启,发送完成的处理我放到的串口发送完成中断中处理了,这里可以根据自己的需求修改。 将串口1的RX帮定到了DMA的CH4上,由于DMA支持弹性映射,也可以根据需求绑定到其他通道上。通道4的中断我开启了 半传输中断 和 传输完成中断,这样在大数据传输时就可以实现双缓冲的目的了。 dma_init_struct.memory_base_addr =(uint32_t)uart1_dma_buff.RX_BUFF.rx_buff;//内存地址 在CH4的内存地址设置这,我利用结构体将缓存区分为2个部分,正好与 半传输中断 和 传输完成中断 的数据缓存相对应。 其他具体细节见源码文件。 在串口初始化中,要开启 空闲中断 和 发送完中断 空闲中断是用来处理DMA接收无法处理的不定长度数据。发送完中断用于关闭发送。 DMA中断函数用到绑定串口接收的中断,中断内分为 半传输处理 和传输完处理,将DMA接收到内存的数据进行处理 串口中断内分为发送完中断和空闲中断,发送完中断很好理解,就是关闭发送的DMA通道即可。空闲中断是用来处理不满足DMA接收通道的数据,弥补DMA存在的不足。 整个方式的核心代码就是这样了,具体细节可以在附件的源码文件看看。 顺便介绍一下F425 DMA的弹性映射功能 由于这款芯片的DMA只有7个通道,为了让每个外设都能雨露均沾的享受到DMA的特性,厂家设计了弹性映射功能,可以让每个外设任意绑定到其中的一个通道上,大大加强了灵活度,可以根据需求灵活配置。
附件源码测试了串口1 和串口2,可以根据需要修改为其他串口
@21ic小管家
|