STM32 串口 DMA 接收不定长数据的一种方法

1. 前言

使用串口接收不定长数据时,可以有多种方法,比如最常见的有额外使能一个定时器,在超过定时范围未收到后续的字节时,认为此帧结束;或者利用 IDLE 中断,当数据空闲时,自动产生中断;亦或每接收到一个字节后都通过应用程序进行一次处理。这次我们介绍另外一种方法,在 DMA 方式下利用硬件接收超时中断(Receiver timeout interrupt)实现不定长数据的接收。

2. 实现原理

首先,并非所有的 STM32 系列的 MCU,也并非所有的 USART/UART 外设都支持Receiver timeout (RTO)特性,具体的支持情况,可以通过对应芯片的参考手册去查询。

对于 MCU 的配置,可以通过 USART_RTOR 寄存器的 RTOEN 位使能接收超时功能,通过 RTO 位域配置超时时间,时间单位为传输一个数据位的时间(即波特率)。
接收超时在停止位设置不同的情况下,计时的起始位置不同:

  1. 如果 stop = ’ 00 '或 stop = ’ 11 ',从停止位的末尾开始。
  2. 如果 stop = ’ 10 ',则从第二个停止位的末尾开始。
  3. 如果 stop = ’ 01 ',则从停止位的起始开始。

当计数超过 RTO 位域的设定值时,且使能了 RTOIE 位,就会产生一个错误中断,此时我
们就可以认为此帧结束,进而进行处理。

3. 应用示例

HAL 库已经为我们提供了操作 RTO 相关的 API,应用开发过程,我们直接调用即可。

void HAL_UART_ReceiverTimeout_Config(UART_HandleTypeDef *huart, uint32_t 
TimeoutValue);
HAL_StatusTypeDef HAL_UART_EnableReceiverTimeout(UART_HandleTypeDef *huart);
HAL_StatusTypeDef HAL_UART_DisableReceiverTimeout(UART_HandleTypeDef *huart);

我们以 STM32U575ZIT6 为例,配置一个测试工程。

  1. 系统时钟配置为 160MHz
  2. 配置 USART1 为 Asynchrones,管脚配置为 PA9,PA10
  3. USART1 参数:115200bits/s,8bit,None,1Stop
  4. 使能 USART1 中断
  5. 配置 USART1_RX GPDMA

在这里插入图片描述
在这里插入图片描述
生成工程后,配置超时时间,使能接收超时功能,使能串口的 DMA 接收,处理串口的错误回调函数(接收超时后,HAL 库中经 HAL_UART_ErrorCallback()回调)。

/* USER CODE BEGIN 2 */
 HAL_UART_ReceiverTimeout_Config(&huart1, huart1.Init.BaudRate/100); //10ms BaudRate = 115200
 HAL_UART_EnableReceiverTimeout(&huart1);
 HAL_UART_Receive_DMA(&huart1, Uart_RcvBuf, MAX_UART_RCV_LEN);
 /* USER CODE END 2 */
#define MAX_UART_RCV_LEN 10 //config the max receive data length
uint8_t Uart_RcvBuf[MAX_UART_RCV_LEN];
uint16_t Uart_RcvLen;
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
	if(huart == &huart1)
	{
		/* Check if DMA mode is enabled in UART */
		 if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
		 { 
			 if((huart->ErrorCode & HAL_UART_ERROR_RTO) == HAL_UART_ERROR_RTO)
			 {
				 uint16_t nb_remaining_rx_data = (uint16_t) 
				__HAL_DMA_GET_COUNTER(huart->hdmarx);
				 Uart_RcvLen = MAX_UART_RCV_LEN - nb_remaining_rx_data;
			 }
		 	HAL_UART_Receive_DMA(&huart1, Uart_RcvBuf, MAX_UART_RCV_LEN);
		 }
	}
}

HAL_UART_ErrorCallback 是一个支持所有错误中断的回调函数,在处理 RTO 错误引起的中断响应时,可以通过 ErrorCode 增加相应的判断。

通过调用__HAL_DMA_GET_COUNTER(huart->hdmarx)可以得到 DMA 未搬移完的字节数,从而得到已搬移完成的字节数。

4. 总结

利用 RTO 方式接收不定长串口数据,相比用定时器计时,可以节省一个硬件定时器资源,同时减少了定时器每次进入中断处理的运行时间;相比 IDLE 的方式,可以更灵活的配置超时时间。但需注意的是,所选用的 MCU 以及所使用的 USART/UART 是否支持这个特性要确认好。

在这里插入图片描述


本文档参考ST官方的《【应用笔记】LAT1315+串口DMA接收不定长数据的一种方法》文档。
参考下载地址:https://download.csdn.net/download/u014319604/89044851

  • 24
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值