本帖最后由 eltonchang2001 于 2022-11-9 13:56 编辑
#技术资源# #申请原创# @21小跑堂
HT32F52352的串口分为USART和UART,USART和UART都支持DMA传输,使用DMA能够让串口在不过多占用CPU的情况下实现高效的数据收发,使用DMA发送数据比较简单,但要实现DMA接收就分为2种情况,一种是接收固定长度的数据,另一种是接收不固定长度数据,在实际使用中,接收不定长度数据的实际意义是比较大的。接收不定长度数据的难点是要判断接收数据何时结束的,这就要用到串口的超时中断,串口超时中断只在USART中支持,UART是不支持的。所以,只有USRAT能够实现DMA接收不定长度数据。
原本原理还是比较清楚的,但HT32F52352的USART还有个特性就是FIFO,由于FIFO的存在,在实现使用DMA接收不定长度数据遇到了麻烦,我们先来看一下串口的方框图
从框图上看,串口的收发都要经过FIFO,收发中断也都和FIFO相关
在代码实现工程中,遇到的实际问题也都和FIFO相关。
具体什么问题,我在下面的代码讲解,由于没找到官方的应用笔记,下面的代码都是一点点测试出来的,费了不少功夫
先来看看DMA初始化
首先使能DMA的时钟
DMA发送配置如下:
由于发送数据不确定,所以数据块数量先设为0。配置完参数但不生效,需要在发送数据前再生效参数。使能中断时,PDMA_INT_GE必须使能,否则PDMA_INT_TC中断进步去(测试发现),DMA发送使用的是通道3(#definePDMA_USART1_TX PDMA_CH3 /*!< USART1_TX PDMAchannel number */)
DMA接收配置如下:
使能中断时,PDMA_INT_GE必须使能,同时开启半传输和传输完中断,用于实现DMA的双缓冲接收。DMA接收使用的是通道2(#define PDMA_USART1_RX PDMA_CH2 /*!< USART1_RX PDMAchannel number */)
串口初始化如下:
先使能串口时钟和相关GPIO时钟,配置串口相关管脚功能。
配置串口基本参数。使能串口收发DMA,开启串口总中断,配置串口的接收超时中断,配置超时时间,设置FIFO收发阈值,最后使能串口发送和接收。
这里重点要说一下 USART_RXTLConfig(HT_USART1, USART_RXTL_02); 接收FIFO阈值不能设置为USART_RXTL_01(这里使用的是USART_RXTL_02),因为设置为USART_RXTL_01后,超时中断不能产生,会被DMA操作清除相关中断标志,这点非常重要!!!
由于开启了DMA和USART中断,相关的中断函数如下
DMA中断函数内有三个分支,分别是 接收半传输完成中断;接收完传输完成 中断;发送完 中断。在 接收半传输完成 中断和 接收完传输完成中断有读取缓存区数据操作,可用于数据分析。发送完 中断内关闭先关通道,等待下次数据发送。
读取缓存区数据函数如下:
这个函数的实际操作示意图如下
串口中断中只有FIFO time out 中断,用于处理接收超时后的操作,这里也是DMA接收不定长度数据的灵魂所在。Receive_DataPack(HT_USART1,USART_ReceiveData(HT_USART1));函数处理接收的数据,再配合之前的DMA中断处理,就可以收取到所有不定长的数据了。
DMA接收搬运的字节数由buff_length算的。
由于设置接收FIFO阈值为2,所以,此函数内处理了一下几种情况:
1 只接收到1个字节,不能触发DMA搬运,DMA搬运字节0(buff_length 为 0),直接从接收寄存器取数据
2 DMA搬运字节大于0个字节小于 半传输完 的字节
接收到最后一个字节前的数据由DMA接收通道搬运,搬运到缓存区的前区(usart1_dma_buff.RX_BUFF.R_BUFF.Rx_buff1),最后一个字节直接从接收寄存器取数据。
3 DMA搬运字节等于 半传输完的字节
DMA半传输 中断将缓存区数据取走(在DMA中断内处理,搬运到缓存区的前区(usart1_dma_buff.RX_BUFF.R_BUFF.Rx_buff1)),最后一个字节直接从接收寄存器取数据,存放到缓存区的后区的第一个字节位置。
4DMA搬运字节大于 半传输 的字节小于 全传输完 的字节
DMA半传输 中断将缓存区数据取走(在DMA中断内处理,搬运到缓存区的前区(usart1_dma_buff.RX_BUFF.R_BUFF.Rx_buff1)),大于半传输的DMA搬运数据在此处取出,存放在缓存区的后区,最后一个字节直接从接收寄存器取数据,存放到DMA缓存区的数据后面。
5DMA搬运字节等于 完全传输完
此时,DMA中断已将所以数据取走,最后这个字节为溢出字节。
至此,所有和DAM接收不定长度数据的处理方法就介绍完了,这里面有不少坑,完全是一点点摸索出来的,我将源码放在附件内,希望对大家有所帮助!!!
|