扫码加入

  • 正文
  • 相关推荐
申请入驻 产业图谱

STM32 串口 DMA 不定长数据接收:RTO 接收超时中断实现方案

01/27 17:05
4187
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

在 STM32 串口通信开发中,不定长数据接收是高频需求。传统方案(定时器计时、IDLE 中断)存在占用资源多、超时配置不灵活等问题。本文基于 ST 官方 LAT1315 应用笔记,详解 “串口 DMA + 接收超时中断(RTO)” 的实现方法,该方案无需额外定时器、超时时间可灵活配置,适用于 STM32 全系列支持 RTO 特性的芯片

1. 核心原理:RTO 接收超时中断的工作逻辑

1.1 技术核心

接收超时中断(Receiver Timeout, RTO)是部分 STM32 UART/USART 外设的硬件特性,通过配置超时时间,当串口超过设定时间未接收新数据时,自动触发中断,判定为一帧数据接收完成。

1.2 关键机制

  • 配置入口:通过 USART_RTOR 寄存器RTOEN位使能功能,RTO位域配置超时时间(单位:单个数据位的传输时间,即波特率倒数);
  • 计时起始点:随停止位配置不同变化
    • 停止位为 00/11:从停止位末尾开始计时;
    • 停止位为 10:从第二个停止位末尾开始计时;
    • 停止位为 01:从停止位起始开始计时;
  • 中断触发:计时超过RTO设定值,且使能RTOIE位时,触发错误中断,通过回调函数处理数据。

1.3 适用前提

  • 芯片与外设支持:需确认目标 STM32 芯片及所用 UART/USART 是否支持 RTO 特性(参考对应芯片参考手册);
  • 软件依赖:STM32Cube HAL 库已提供 RTO 相关 API,直接调用即可,无需底层寄存器操作。

2. 实操步骤:从配置到代码实现(以 STM32U575 为例)

以 STM32U575ZIT6 为目标芯片,实现 115200 波特率下的不定长数据接收,步骤分 “STM32CubeMX 配置” 和 “代码编写” 两部分。

2.1 STM32CubeMX 配置

(1)基础参数配置

  • 系统时钟:配置为 160MHz;
  • UART 配置:USART1,异步模式(Asynchronous),引脚 PA9(TX)、PA10(RX);
  • 串口参数:波特率 115200 bits/s,数据位 8bit,校验位 None,停止位 1bit;
  • 中断使能:启用 USART1 全局中断,配置 NVIC 优先级。

(2)DMA 配置

  • DMA 通道:USART1_RX 关联 GPDMA1 Channel 0;
  • 传输参数:方向 “Peripheral To Memory”,源地址增量禁用,目的地址增量启用,数据宽度均为 Byte;
  • 模式配置:正常模式(Circular Mode 禁用),优先级 Low,禁用触发与数据处理功能。

2.2 代码编写与核心配置

(1)宏定义与全局变量

#define MAX_UART_RCV_LEN 10  // 最大接收数据长度
uint8_t Uart_RcvBuf[MAX_UART_RCV_LEN];  // 接收缓冲区
uint16_t Uart_RcvLen;  // 实际接收数据长度

(2)初始化配置(main 函数 USER CODE BEGIN 2 段)

// 1. 配置RTO超时时间:10ms(计算逻辑:波特率/100 = 115200/100 = 1152)
HAL_UART_ReceiverTimeout_Config(&huart1, huart1.Init.BaudRate / 100);
// 2. 使能接收超时功能
HAL_UART_EnableReceiverTimeout(&huart1);
// 3. 启动DMA接收(循环接收,缓冲区满则覆盖)
HAL_UART_Receive_DMA(&huart1, Uart_RcvBuf, MAX_UART_RCV_LEN);

(3)中断回调函数处理

RTO 中断触发后,会进入HAL_UART_ErrorCallback回调函数,需在此解析错误类型并处理数据:
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {
  if (huart == &huart1) {  // 确认是USART1触发中断
    // 检查是否为DMA模式且触发RTO错误
    if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR) && 
        (huart->ErrorCode & HAL_UART_ERROR_RTO) == HAL_UART_ERROR_RTO) {
      // 计算实际接收长度:最大长度 - DMA未传输字节数
      uint16_t nb_remaining_rx_data = (uint16_t)__HAL_DMA_GET_COUNTER(huart->hdmarx);
      Uart_RcvLen = MAX_UART_RCV_LEN - nb_remaining_rx_data;
      
      // 此处添加数据处理逻辑(如解析数据、发送响应等)
      // 示例:打印接收数据(需自行实现串口打印功能)
      printf("接收数据长度:%d,数据内容:", Uart_RcvLen);
      for (uint16_t i = 0; i < Uart_RcvLen; i++) {
        printf("%02X ", Uart_RcvBuf[i]);
      }
      printf("rn");
      
      // 清除错误标志,重启DMA接收
      __HAL_UART_CLEAR_ERRORCODE(huart);
      HAL_UART_Receive_DMA(&huart1, Uart_RcvBuf, MAX_UART_RCV_LEN);
    }
  }
}

3. 核心优势:与传统方案的对比

接收方案 核心优势 存在不足 适用场景
RTO 接收超时 + DMA 1. 无需额外定时器,节省硬件资源;2. 超时时间可灵活配置(按波特率动态调整);3. 中断触发少,CPU 占用低 仅支持部分 STM32 芯片及 UART 外设 需省资源、灵活配置超时的不定长接收场景
定时器计时 + DMA 兼容性强,所有 STM32 芯片均支持 1. 占用 1 个定时器资源;2. 定时器中断频繁,CPU 负载高 不支持 RTO 特性的芯片
IDLE 中断 + DMA 无需配置超时时间,自动检测空闲状态 超时逻辑固定,无法自定义空闲时长 对超时时间无严格要求的场景

4. 注意事项与避坑指南

  1. 特性兼容性:务必先查阅芯片参考手册,确认所用 UART/USART 是否支持 RTO(如 STM32U5、STM32H7 系列大部分支持,部分低端系列可能不支持);
  2. 超时时间计算:HAL_UART_ReceiverTimeout_Config的第二个参数单位为 “数据位传输时间”,需根据波特率换算(如 115200 波特率下,10ms 对应 115200/100=1152);
  3. DMA 计数器使用:__HAL_DMA_GET_COUNTER用于获取 DMA 未传输的字节数,需注意数据类型转换(避免溢出);
  4. 错误标志清除:处理完 RTO 中断后,需调用__HAL_UART_CLEAR_ERRORCODE清除错误标志,否则无法重启 DMA 接收;
  5. 缓冲区大小:MAX_UART_RCV_LEN需根据实际最大接收数据长度配置,避免缓冲区溢出。
“串口 DMA+RTO 接收超时中断” 是 STM32 不定长数据接收的高效方案,核心优势在于 “省资源 + 高灵活”—— 既无需占用额外定时器,又能根据需求自定义超时时间,大幅降低 CPU 负载。该方案完全基于 HAL 库 API 开发,代码可移植性强,适用于智能家居工业传感器、串口透传等各类需要稳定接收不定长数据的场景。

相关推荐

登录即可解锁
  • 海量技术文章
  • 设计资源下载
  • 产业链客户资源
  • 写文章/发需求
立即登录