打印
[开发板与模块]

【HT32F52352 Starter Kit测评】USART使用DMA接收不定长度数据详解

[复制链接]
7378|71
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 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接收不定长度数据的处理方法就介绍完了,这里面有不少坑,完全是一点点摸索出来的,我将源码放在附件内,希望对大家有所帮助!!!

源码.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 | 只看该作者
学习了!

使用特权

评论回复
5
chenqianqian| | 2022-6-7 07:51 | 只看该作者
学到了,谢谢分享

使用特权

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

使用特权

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

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

使用特权

评论回复
8
daichaodai| | 2022-6-9 08:18 | 只看该作者
DMA使用好了,能大大提高程序运行效率。

使用特权

评论回复
9
mmbs| | 2022-11-3 20:38 | 只看该作者
可以使用串口的idle中断吧。              

使用特权

评论回复
10
yeates333| | 2022-11-3 20:58 | 只看该作者
串口产生IDLE(空闲)中断,在中断函数中清除中断标志位,并获取接收 数据长度。

使用特权

评论回复
11
xiaoyaodz| | 2022-11-3 21:30 | 只看该作者
能不能用定时器判断接收数据超时?

使用特权

评论回复
12
6552918|  楼主 | 2022-11-3 21:38 | 只看该作者
mmbs 发表于 2022-11-3 20:38
可以使用串口的idle中断吧。

可以,但这款MCU是带FIFO的,和不带FIFO的还是有点区别

使用特权

评论回复
13
6552918|  楼主 | 2022-11-3 21:39 | 只看该作者
xiaoyaodz 发表于 2022-11-3 21:30
能不能用定时器判断接收数据超时?

理论上可以

使用特权

评论回复
14
tabmone| | 2022-11-3 21:57 | 只看该作者
添加启动IDLE中断和启动DMA接收

使用特权

评论回复
15
6552918|  楼主 | 2022-11-4 09:03 | 只看该作者
tabmone 发表于 2022-11-3 21:57
添加启动IDLE中断和启动DMA接收

说的是没错,但有FIFO,操作上还是有区别的

使用特权

评论回复
16
AloneKaven| | 2022-11-4 20:34 | 只看该作者
DMA能提高程序运行效率

使用特权

评论回复
17
6552918|  楼主 | 2022-11-4 20:37 | 只看该作者
AloneKaven 发表于 2022-11-4 20:34
DMA能提高程序运行效率

是的,非常高效

使用特权

评论回复
18
51xlf| | 2022-11-5 10:45 | 只看该作者
这个判断字符之间间隔使用的是什么算法

使用特权

评论回复
19
6552918|  楼主 | 2022-11-5 14:23 | 只看该作者
51xlf 发表于 2022-11-5 10:45
这个判断字符之间间隔使用的是什么算法

和单字节中断一样,保险起见逐个字节再遍历一遍,找包头包尾。

使用特权

评论回复
20
loutin| | 2022-12-2 19:59 | 只看该作者
如何判断dma发送完毕呢?              

使用特权

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

本版积分规则

认证:北京汇冠触摸技术有限公司/电子工程师
简介:电子工程师,嵌入式应用爱好者。

102

主题

1262

帖子

9

粉丝