4、UART核心寄存器详解(上):USART_SR(状态寄存器)、USART_DR(数据寄存器)
UART通信的底层控制,本质上是MCU通过寄存器读写来驱动硬件收发。在STM32等主流MCU中,USART模块的核心寄存器主要包括状态寄存器(USART_SR)和数据寄存器(USART_DR)。理解这两个寄存器的每一位含义,是编写稳定、高效UART驱动的基础。
4.1 USART_SR:状态寄存器(Status Register)
USART_SR是驱动开发中最常查询的寄存器,它实时反映UART外设的当前工作状态,包括数据是否就绪、发送是否完成、是否发生溢出或帧错误等。该寄存器为32位,但实际有效位集中在低8位。
| 位号 | 名称 | 类型 | 描述 |
|---|---|---|---|
| Bit 9 | CTS | 只读 | CTS标志(硬件流控制时使用) |
| Bit 8 | LBD | 只读 | LIN断开检测标志 |
| Bit 7 | TXE | 只读 | 发送数据寄存器空:1表示DR已空,可写入新数据 |
| Bit 6 | TC | 只读 | 发送完成:1表示帧发送完成(包括停止位) |
| Bit 5 | RXNE | 只读 | 接收数据寄存器非空:1表示DR已收到新数据,可读取 |
| Bit 4 | IDLE | 只读 | 空闲线路检测 |
| Bit 3 | ORE | 只读 | 溢出错误:1表示数据未及时读取,新数据覆盖旧数据 |
| Bit 2 | NF | 只读 | 噪声标志(检测到噪声) |
| Bit 1 | FE | 只读 | 帧错误:1表示停止位无效(波特率不匹配或线路干扰) |
| Bit 0 | PE | 只读 | 奇偶校验错误 |
驱动开发关键位速记:
- TXE:发送缓冲区空 → 可以写DR
- TC:发送完成 → 帧已发完(关闭使能或切换模式前必须检查)
- RXNE:接收数据就绪 → 可以读DR
- ORE:溢出错误 → 驱动必须处理,否则会丢失后续数据
4.1.1 中断使能与SR的联动
在中断模式下,USART_SR的某些位与中断使能寄存器(USART_CR1/CR2/CR3)配合工作。例如:
- 使能RXNEIE(接收中断使能)后,当SR的RXNE位变为1时,硬件自动触发中断。
- 使能TCIE(发送完成中断使能)后,当SR的TC位变为1时触发中断。
驱动开发中,中断服务函数(ISR)的第一步通常是读取SR,判断是哪个事件触发了中断,然后执行对应的读写操作。
避坑提示:读取SR后,某些标志位(如TC、RXNE)不会自动清零。通常采用“先读SR,再读/写DR”的序列来硬件清除标志。如果使用软件清零,需查阅参考手册确认具体操作。
4.2 USART_DR:数据寄存器(Data Register)
USART_DR是UART数据收发的直接通道。它是一个32位寄存器,但实际有效数据只占用低8位(或9位,取决于数据位配置)。
| 位号 | 名称 | 类型 | 描述 |
|---|---|---|---|
| Bit 31:9 | 保留 | — | 保留位,写入0 |
| Bit 8:0 | DR[8:0] | 读/写 | 数据值:发送时写入,接收时读取 |
4.2.1 发送数据流程(轮询模式示例)
// 发送一个字节(轮询模式)
void UART_SendByte(uint8_t data) {
// 等待TXE置1,表示DR空
while (!(USART1->SR & USART_SR_TXE));
// 写入数据到DR
USART1->DR = data;
// 可选:等待TC置1,确保帧完全发送完成
while (!(USART1->SR & USART_SR_TC));
}
4.2.2 接收数据流程(轮询模式示例)
// 接收一个字节(轮询模式)
uint8_t UART_ReceiveByte(void) {
// 等待RXNE置1,表示DR有数据
while (!(USART1->SR & USART_SR_RXNE));
// 读取DR获取数据
return (uint8_t)(USART1->DR & 0xFF);
}
关键注意:
- 读DR前必须先读SR:这是硬件清除RXNE标志的标准序列。如果顺序颠倒,可能导致标志位无法正确清除,引发中断风暴或数据重复读取。
- 写DR前必须等待TXE:如果DR未空就写入新数据,会覆盖上一个未发送的数据,造成发送错误。
- 9位数据模式:当配置为9位数据位时,DR[8:0]全部有效,读取/写入时需使用uint16_t类型。
4.3 SR与DR的协同工作流程
下图展示了UART收发过程中,SR与DR的交互关系,以及中断触发的时机。
4.4 中断模式下的寄存器操作要点
- ISR入口先读SR:通过读取SR判断中断来源(RXNE、TC、IDLE、ORE等),避免误处理。
- 清除标志位:RXNE和TC标志通过“读SR后操作DR”自动清除;ORE标志需先读SR再读DR才能清除。
- 错误处理:当检测到ORE、FE、NF或PE时,建议在ISR中记录错误计数,并重新初始化接收逻辑,防止数据错位。
- 中断优先级:UART中断优先级不宜设置过高,避免阻塞其他实时任务;但接收中断(RXNE)应略高于发送中断(TC),防止接收溢出。
实战口诀:
“先读SR再读DR,接收不丢;先等TXE再写DR,发送不乱;ORE必须清,否则数据停。”