使用 UART 空闲中断(IDLE) + DMA 接收数据

1. 基本原理

  • 空闲中断(IDLE):当 UART 接收数据后,总线在 1 字节传输时间 内无新数据时触发中断。

  • DMA 传输:在后台自动将 UART 接收的数据搬运到内存缓冲区,无需 CPU 干预。

  • 协作流程

    1. 启动 DMA 接收,持续监听 UART 数据。

    2. 当数据到达时,DMA 自动填充缓冲区。

    3. 数据停止传输后,触发空闲中断。

    4. 在中断中计算实际接收长度,处理数据。

2. 硬件与库配置

2.1 硬件使能

  • 在 STM32CubeMX 中:

    1. 启用 UART 的 DMA RX 通道

    2. 启用 UART 的 全局中断(NVIC Settings)。

2.2 代码配置

// 定义全局变量
#define RX_BUFFER_SIZE 256
uint8_t g_rxBufferDMA[RX_BUFFER_SIZE];  // DMA 接收缓冲区
volatile uint16_t g_rxLength = 0;     // 实际接收数据长度// 在 main() 初始化中启动 DMA 接收
void UART_Init(void) {
    // 启用 UART 空闲中断(需手动添加)
    __HAL_UART_ENABLE_IT(&huart4, UART_IT_IDLE);
    // 启动 DMA 接收
    HAL_UART_Receive_DMA(&huart4, g_rxBufferDMA, RX_BUFFER_SIZE);
}

CubeIDE图形配置如下

3. 中断处理

// 在 stm32xx_it.c 的 USARTx_IRQHandler 中添加空闲中断判断
void USARTx_IRQHandler(void) {
    HAL_UART_IRQHandler(&huart4);            // HAL 库默认中断处理
    // 检查并处理错误
    if (huart4.ErrorCode != HAL_UART_ERROR_NONE) {
        if (huart4.ErrorCode & HAL_UART_ERROR_DMA) {
            // DMA错误特定处理,解决插拔串口或者发送数据频率过导致后DMA缓冲区一直为空的问题
            HAL_DMA_Abort(huart4.hdmarx);  // 中止DMA通道
            HAL_DMA_DeInit(huart4.hdmarx); // 反初始化DMA
            HAL_DMA_Init(huart4.hdmarx);   // 重新初始化DMA
        }
        // 清除所有错误标志
        __HAL_UART_CLEAR_FLAG(&huart4, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF | UART_CLEAR_IDLEF);
        huart4.ErrorCode = HAL_UART_ERROR_NONE;  // 重置错误码

        // 重启DMA接收
        HAL_UART_DMAStop(&huart4);
        memset(g_rxBufferDMA, 0, RX_BUFFER_SIZE);
        HAL_UART_Receive_DMA(&huart4, g_rxBufferDMA, RX_BUFFER_SIZE);  // 立即重启DMA
    }
    if (__HAL_UART_GET_FLAG(&huart4, UART_FLAG_IDLE)) {
        __HAL_UART_CLEAR_IDLEFLAG(&huart4);  // 清除空闲中断标志
        
        HAL_UART_DMAStop(&huart4);// 停止 DMA 以防止数据覆盖
        
        g_rxLength = RX_BUFFER_SIZE - __HAL_DMA_GET_COUNTER(huart4.hdmarx);// 计算实际接收的数据长度
        //处理串口数据
        // ...
        
        HAL_UART_Receive_DMA(&huart4, g_rxBufferDMA, RX_BUFFER_SIZE);// 重新启动 UART DMA 接收
    }    
}

通过此方案,可彻底解决轮询接收中的超时问题,同时提升系统整体性能和稳定性。实际部署时需根据硬件特性调整缓冲区和中断优先级。

 

posted @ 2025-03-04 13:50  阿坦  阅读(1168)  评论(0)    收藏  举报