[开发板与模块] 【HT32F52352 Starter Kit测评】USART使用DMA接收不定长度数据详解

[复制链接]
217|7
手机看帖
扫描二维码
随时随地手机跟帖
6552918|  楼主 | 2022-6-5 20:34 | 显示全部楼层 |阅读模式
本帖最后由 6552918 于 2022-6-6 20:57 编辑

#技术资源# #申请原创# @21小跑堂
       HT32F52352的串口分为USART和UART,USART和UART都支持DMA传输,使用DMA能够让串口在不过多占用CPU的情况下实现高效的数据收发,使用DMA发送数据比较简单,但要实现DMA接收就分为2种情况,一种是接收固定长度的数据,另一种是接收不固定长度数据,在实际使用中,接收不定长度数据的实际意义是比较大的。接收不定长度数据的难点是要判断接收数据何时结束的,这就要用到串口的超时中断,串口超时中断只在USART中支持,UART是不支持的。所以,只有USRAT能够实现DMA接收不定长度数据。
         原本原理还是比较清楚的,但HT32F52352的USART还有个特性就是FIFO,由于FIFO的存在,在实现使用DMA接收不定长度数据遇到了麻烦,我们先来看一下串口的方框图
1.png

从框图上看,串口的收发都要经过FIFO,收发中断也都和FIFO相关
2.png

在代码实现工程中,遇到的实际问题也都和FIFO相关。
       具体什么问题,我在下面的代码讲解,由于没找到官方的应用笔记,下面的代码都是一点点测试出来的,费了不少功夫
       先来看看DMA初始化
3.png

首先使能DMA的时钟
4.png

DMA发送配置如下:
5.png

由于发送数据不确定,所以数据块数量先设为0。配置完参数但不生效,需要在发送数据前再生效参数。使能中断时,PDMA_INT_GE必须使能,否则PDMA_INT_TC中断进步去(测试发现),DMA发送使用的是通道3(#definePDMA_USART1_TX            PDMA_CH3                      /*!< USART1_TX PDMAchannel number          */)
DMA接收配置如下:
6.png

使能中断时,PDMA_INT_GE必须使能,同时开启半传输和传输完中断,用于实现DMA的双缓冲接收。DMA接收使用的是通道2(#define PDMA_USART1_RX            PDMA_CH2                      /*!< USART1_RX PDMAchannel number          */)
       串口初始化如下:
7.png

先使能串口时钟和相关GPIO时钟,配置串口相关管脚功能。
8.png

配置串口基本参数。使能串口收发DMA,开启串口总中断,配置串口的接收超时中断,配置超时时间,设置FIFO收发阈值,最后使能串口发送和接收。
这里重点要说一下 USART_RXTLConfig(HT_USART1, USART_RXTL_02);       接收FIFO阈值不能设置为USART_RXTL_01(这里使用的是USART_RXTL_02),因为设置为USART_RXTL_01后,超时中断不能产生,会被DMA操作清除相关中断标志,这点非常重要!!!
由于开启了DMA和USART中断,相关的中断函数如下
9.png

DMA中断函数内有三个分支,分别是 接收半传输完成中断;接收完传输完成 中断;发送完 中断。在 接收半传输完成 中断和 接收完传输完成中断有读取缓存区数据操作,可用于数据分析。发送完 中断内关闭先关通道,等待下次数据发送。

读取缓存区数据函数如下:
10.png

这个函数的实际操作示意图如下

11.png
12.png

串口中断中只有FIFO time out 中断,用于处理接收超时后的操作,这里也是DMA接收不定长度数据的灵魂所在。Receive_DataPack(HT_USART1,USART_ReceiveData(HT_USART1));函数处理接收的数据,再配合之前的DMA中断处理,就可以收取到所有不定长的数据了。
13.png

DMA接收搬运的字节数由buff_length算的。

14.png
由于设置接收FIFO阈值为2,所以,此函数内处理了一下几种情况:
1 只接收到1个字节,不能触发DMA搬运,DMA搬运字节0(buff_length 为 0),直接从接收寄存器取数据
15.png

2 DMA搬运字节大于0个字节小于 半传输完 的字节
16.png

接收到最后一个字节前的数据由DMA接收通道搬运,搬运到缓存区的前区(usart1_dma_buff.RX_BUFF.R_BUFF.Rx_buff1),最后一个字节直接从接收寄存器取数据。
3 DMA搬运字节等于 半传输完的字节
17.png

DMA半传输 中断将缓存区数据取走(在DMA中断内处理,搬运到缓存区的前区(usart1_dma_buff.RX_BUFF.R_BUFF.Rx_buff1)),最后一个字节直接从接收寄存器取数据,存放到缓存区的后区的第一个字节位置。
4DMA搬运字节大于 半传输 的字节小于 全传输完 的字节
18.png

DMA半传输 中断将缓存区数据取走(在DMA中断内处理,搬运到缓存区的前区(usart1_dma_buff.RX_BUFF.R_BUFF.Rx_buff1)),大于半传输的DMA搬运数据在此处取出,存放在缓存区的后区,最后一个字节直接从接收寄存器取数据,存放到DMA缓存区的数据后面。
5DMA搬运字节等于 完全传输完
19.png

此时,DMA中断已将所以数据取走,最后这个字节为溢出字节。

       至此,所有和DAM接收不定长度数据的处理方法就介绍完了,这里面有不少坑,完全是一点点摸索出来的,我将源码放在附件内,希望对大家有所帮助!!!

源码.zip

7.08 KB

源码

使用特权

评论回复
chenjun89| | 2022-6-6 08:10 | 显示全部楼层
学习了,平时很少用到DMA,out了。

使用特权

评论回复
6552918|  楼主 | 2022-6-6 10:32 | 显示全部楼层
chenjun89 发表于 2022-6-6 08:10
学习了,平时很少用到DMA,out了。

用起来很爽,但用之前的过程中有很对坑

使用特权

评论回复
zwsam| | 2022-6-6 17:25 | 显示全部楼层
学习了!

使用特权

评论回复
chenqianqian| | 2022-6-7 07:51 | 显示全部楼层
学到了,谢谢分享

使用特权

评论回复
skyHorse999| | 2022-6-7 10:58 | 显示全部楼层
串口不定长度数据接收不是弄个FIFO水位到达中断,和一个超时中断就可以了嘛,需要整得这么复杂吗?!

使用特权

评论回复
6552918|  楼主 | 2022-6-7 15:22 | 显示全部楼层
skyHorse999 发表于 2022-6-7 10:58
串口不定长度数据接收不是弄个FIFO水位到达中断,和一个超时中断就可以了嘛,需要整得这么复杂吗?!
...

大数据量传输效率可不是一个水平的哦,比如要收60多个字节,FIFO加中断要中断8次,用DMA一次就中断就可以。

使用特权

评论回复
daichaodai| | 2022-6-9 08:18 | 显示全部楼层
DMA使用好了,能大大提高程序运行效率。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则