STM32 串口

本笔记主要总结 STM32 使用串口中断方式进行数据发送和接收的机制与代码实现,使用 HAL 库进行举例,适用于初学者理解串口中断的原理与用法。


一、串口中断发送流程

当使用串口中断方式发送数据时,整体流程如下:

  1. CPU 将一个待发送字节写入 USARTx->TDR(发送数据寄存器)。
  2. 然后 CPU 立即返回执行其他任务
  3. 此时硬件会自动将 TDR 中的数据移入发送移位寄存器。
  4. TDR 为空时,会触发一次 TXE(Transmit Data Register Empty)中断
  5. CPU 响应中断,在中断处理函数中再次将下一个字节写入 TDR
  6. 重复上述流程,直到数据全部发送。
  7. 最后一个字节写入后会再次触发 TXE,必须手动关闭 TXEIE 避免空中断持续触发

🔧 提示:发送是否真正完成,可以查看 TC(Transmission Complete)标志。

✅ 示例代码:中断方式发送数据

uint8_t txData[] = "Hello, UART!";
HAL_UART_Transmit_IT(&huart1, txData, sizeof(txData)-1);

HAL库会自动开启 TXEIE,当发送完成后会自动调用回调函数:

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
    if (huart->Instance == USART1) {
        // 发送完成后的处理逻辑
    }
}

二、串口中断接收流程

  1. 当串口接收移位寄存器接收到完整的一帧数据后,会将数据转移至 USARTx->RDR(接收数据寄存器)。
  2. 此时触发 RXNE(Receive Data Register Not Empty)中断。
  3. CPU 被中断叫回,并读取 RDR 中的数据存入变量中(👉 这一步很关键)
  4. CPU 随后继续处理其他任务。

✅ 示例代码:中断方式接收数据

uint8_t rxBuffer[10];
HAL_UART_Receive_IT(&huart1, rxBuffer, sizeof(rxBuffer));

当接收到设定数量的数据后,会调用回调函数:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
    if (huart->Instance == USART1) {
        // 处理接收到的数据 rxBuffer
    }
}

三、中断机制说明与回调函数

  • STM32 的串口中断向量只有一个(例如 USART1_IRQHandler()),但可以由多个事件触发(如 TXE、RXNE、OE、FE 等)。
  • HAL库封装了中断处理函数 HAL_UART_IRQHandler(),并提供了**弱定义(__weak)**的回调函数接口,供用户实现具体逻辑。

🔁 常用回调函数原型

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart);

🧠 回调函数使用说明

  • 若用户需要自定义处理逻辑,需重写上述函数。
  • 若不重写,则默认的弱定义函数什么都不做。

四、底层流程图(发送流程举例)

串口中断流程图


五、关键中断标志说明

中断标志 含义 触发条件
TXE 发送数据寄存器空 TDR 为空,表示可写入新数据
RXNE 接收数据寄存器非空 接收到数据到 RDR
TC 发送完成标志(非中断) 所有数据已发送并移出移位寄存器

⚠ 使用中断方式必须手动控制 TXEIERXNEIE,否则可能导致空中断频繁触发。


六、总结

  • 串口中断提高了系统效率,减少了轮询等待时间;
  • 使用 HAL 库开发时要充分利用回调函数机制,实现收发逻辑与业务逻辑的解耦;
  • 注意在发送最后一个字节后手动关闭中断,避免中断空转。

❤️ 你的点赞与评论是我持续更新的最大动力!

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐