4. UART中断类型

在 STM32 等主流 MCU 的 UART 外设中,中断控制器(NVIC)会根据不同的触发条件向 CPU 发送中断请求。理解每种中断类型的触发时机、标志位清除方式以及典型应用场景,是编写健壮中断服务函数(ISR)的前提。本章将逐一剖析四种核心 UART 中断类型:发送完成中断(TC)、发送数据寄存器空中断(TXE)、接收数据寄存器非空中断(RXNE) 和 溢出错误中断(ORE)。

4.1 中断类型总览

下表从触发条件、标志位、清除方式及典型用途四个维度,对这四种中断进行横向对比:

中断类型 触发条件 状态标志位 标志位清除方式 典型用途
发送完成中断(TC) 移位寄存器发送完当前帧,且 TXE=1 TC (USART_SR 位 6) 读 USART_SR 后写 USART_DR;或直接写 0 清除 RS485 收发切换、DMA 传输完成同步
发送数据寄存器空中断(TXE) 发送数据寄存器(TDR)为空,可写入新数据 TXE (USART_SR 位 7) 向 USART_DR 写入数据后硬件自动清除 逐字节发送数据流、中断方式发送
接收数据寄存器非空中断(RXNE) 接收移位寄存器数据已转移到 RDR,数据可读 RXNE (USART_SR 位 5) 读 USART_DR 后硬件自动清除 逐字节接收数据、中断方式接收
溢出错误中断(ORE) RXNE=1 时新数据到达,导致前一个数据被覆盖 ORE (USART_SR 位 3) 读 USART_SR 后读 USART_DR 错误检测与恢复、数据流控保护
关键记忆点: TXE 表示“可以放数据”,TC 表示“数据已经发完”。在单字节发送场景中,TXE 中断频率更高;TC 中断更适合需要确认物理帧发送完成的场景。

4.2 发送完成中断(TC)

TC 中断是 UART 发送流程中最“靠后”的中断。它不仅在发送数据寄存器为空(TXE=1)时触发,还必须满足当前帧的移位操作已经完成,即停止位已经发出。这意味着 TC 中断标志着整个数据帧(包括起始位、数据位、校验位、停止位)已经物理发送完毕。

典型应用场景:

  • RS485 方向控制: 在发送完最后一个字节后,立即将 RE/DE 引脚从发送模式切换为接收模式,避免总线冲突。
  • 低功耗模式进入: 确保所有待发数据已送出后再关闭 UART 时钟或进入睡眠模式。
  • DMA 传输完成同步: 配合 DMA 发送完成回调,确认物理层发送完毕。
常见陷阱: 在初始化时,如果 USART_SR 寄存器的 TC 位默认为 1,且使能了 TC 中断,则会在使能瞬间立即进入一次中断。建议在使能 TC 中断前先清除 TC 标志位,或使用 TXE 中断完成首字节发送。

4.3 发送数据寄存器空中断(TXE)

TXE 是发送中断中最常用的类型。当发送数据寄存器(TDR)中的数据被硬件自动转移到移位寄存器后,TDR 变为空,TXE 标志位被硬件置 1。此时 CPU 可以写入下一个待发送字节。TXE 中断的触发频率与波特率直接相关:波特率越高,中断间隔越短。

中断服务函数典型流程:

  1. 进入 ISR,读取 USART_SR 寄存器,确认 TXE 标志位为 1。
  2. 从发送缓冲区(如环形缓冲区)取出下一个字节。
  3. 将取出的字节写入 USART_DR 寄存器(写操作自动清除 TXE 标志)。
  4. 如果缓冲区已空,则禁止 TXE 中断,避免空中断浪费 CPU 资源。
// TXE 中断服务函数示例(伪代码)
void USART1_IRQHandler(void) {
    if (USART_GetITStatus(USART1, USART_IT_TXE) != RESET) {
        uint8_t data;
        if (RingBuf_Dequeue(&tx_buf, &data) == 0) {
            // 缓冲区非空,发送下一个字节
            USART_SendData(USART1, data);
        } else {
            // 缓冲区已空,关闭 TXE 中断
            USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
        }
    }
}

4.4 接收数据寄存器非空中断(RXNE)

RXNE 是接收中断的核心。当 UART 完成一帧数据的接收(包括起始位、数据位、校验位、停止位),接收移位寄存器中的数据会被转移到接收数据寄存器(RDR),此时 RXNE 标志位被硬件置 1。CPU 必须在下一个数据帧接收完成之前读取 USART_DR,否则将触发溢出错误(ORE)。

中断服务函数典型流程:

  1. 进入 ISR,读取 USART_SR 寄存器,确认 RXNE 标志位为 1。
  2. 读取 USART_DR 寄存器,获取接收到的字节(读操作自动清除 RXNE 标志)。
  3. 将字节存入接收缓冲区(如环形缓冲区)。
  4. 如果启用了接收超时或空闲检测,可在此处更新相关计数器。
性能提示: 在高速波特率(如 921600 bps)下,RXNE 中断间隔可能短至 10 μs 左右。此时应确保 ISR 执行时间足够短,或考虑使用 DMA + 空闲中断的方式减轻 CPU 负担。

4.5 溢出错误中断(ORE)

ORE 中断属于错误类中断,其触发条件为:当 RXNE 标志位仍为 1(即上一个接收数据尚未被 CPU 读取)时,新的数据帧已经接收完成并试图转移到 RDR,导致前一个数据被覆盖。ORE 中断的优先级通常建议设置为较高等级,以便及时处理错误状态,避免数据丢失扩散。

ORE 中断处理步骤:

  • 读取 USART_SR 寄存器,确认 ORE 标志位为 1。
  • 读取 USART_DR 寄存器(即使数据已无效,也必须执行读操作以清除 ORE 标志)。
  • 记录错误计数,或触发上层协议的重传机制。
  • 如果启用了硬件流控(RTS/CTS),可考虑拉低 RTS 信号,暂停对端发送。
调试建议: ORE 中断频繁触发通常意味着接收缓冲区太小或 ISR 处理不及时。排查方向包括:增大环形缓冲区深度、降低中断优先级、检查是否有其他高优先级中断长时间阻塞 UART 中断。

4.6 中断类型关系图

下图展示了 UART 发送与接收路径上,四种中断的触发位置与数据流向关系:

UART 四种中断类型触发位置与数据流向图 UART 中断类型触发位置与数据流向 发送路径 CPU 写入 USART_DR TDR → 移位寄存器 逐位发送(TX 引脚) TXE 中断触发 TC 中断触发 接收路径 逐位接收(RX 引脚) 移位寄存器 → RDR CPU 读取 USART_DR RXNE 中断触发 ORE 中断触发 中断触发条件总结 • TXE:TDR 为空,可写入新数据 • TC:移位寄存器发送完成,且 TXE=1 • RXNE:RDR 有数据,可读取 • ORE:RXNE=1 时新数据覆盖旧数据

4.7 中断使能与标志位清除对照

在编写初始化代码时,需要正确配置中断使能寄存器(USART_CR1/CR2/CR3)中的对应位。下表列出每种中断对应的使能位:

中断类型 使能控制位 所在寄存器 标志位清除方式
发送完成中断(TC) TCIE USART_CR1 位 6 读 SR 后写 DR;或软件写 0
发送数据寄存器空中断(TXE) TXEIE USART_CR1 位 7 写 DR 后硬件自动清除
接收数据寄存器非空中断(RXNE) RXNEIE USART_CR1 位 5 读 DR 后硬件自动清除
溢出错误中断(ORE) RXNEIE(与 RXNE 共用) USART_CR1 位 5 读 SR 后读 DR
注意: ORE 中断与 RXNE 中断共用同一个使能位(RXNEIE)。使能 RXNEIE 后,ORE 事件也会产生中断请求。在 ISR 中应优先检查 ORE 标志位,再处理 RXNE 数据,避免因溢出导致的数据错误被忽略。

4.8 中断优先级配置建议

在 NVIC 中配置 UART 中断优先级时,建议遵循以下原则:

  • RXNE 中断: 设置为较高优先级(如抢占优先级 1),避免因接收延迟导致 ORE 错误。
  • ORE 中断: 与 RXNE 共用优先级,但在 ISR 内优先处理。
  • TXE 中断: 可设置为较低优先级(如抢占优先级 2),发送延迟通常不会导致数据丢失。
  • TC 中断: 优先级可低于 TXE,仅在发送完成时需要同步操作的场景下才需较高优先级。

通过合理配置中断优先级和正确清除标志位,可以构建稳定高效的 UART 中断驱动系统,为后续的环形缓冲区管理和协议解析打下坚实基础。