📊 一、核心寄存器概览
寄存器 | 功能 | 位宽 | 关键位域 |
---|---|---|---|
USART_SR | 状态寄存器(只读) | 32位 | RXNE (接收就绪)、TC (发送完成)、TXE (发送寄存器空)、ORE (溢出错误) |
USART_DR | 数据寄存器(读写) | 32位 | 低9位有效,存储发送/接收的数据(实际用8位) |
USART_BRR | 波特率寄存器 | 32位 | DIV_Mantissa (整数部分) + DIV_Fraction (小数部分),控制通信速率 |
USART_CR1 | 控制寄存器1 | 32位 | UE (使能)、TE (发送使能)、RE (接收使能)、M (字长)、PCE (校验使能) |
USART_CR2 | 控制寄存器2 | 32位 | STOP (停止位长度)、LINEN (LIN模式)、CLKEN (时钟使能) |
USART_CR3 | 控制寄存器3 | 32位 | DMAT (DMA发送使能)、DMAR (DMA接收使能)、RTSE (RTS流控)、CTSE (CTS流控) |
⚠️ 注意:
- 所有寄存器必须按32位字访问(禁止半字/字节操作);
- 操作前需使能时钟 (
RCC_APBxPeriphClockCmd()
),否则配置无效。
⚙️ 二、寄存器详解与配置方法
1. 状态寄存器(USART_SR)
- 关键位 :
RXNE
(位5):接收数据就绪(读DR自动清除)TXE
(位7):发送寄存器空(写DR自动清除)TC
(位6):发送完成(读SR后写DR清除)
cpp
// 发送前检测TXE
while (!(USART1->SR & USART_SR_TXE)); // 等待发送寄存器空
USART1->DR = data; // 写入数据
2. 波特率寄存器(USART_BRR)
- 计算公式 :
BRR=波特率×16fclk- 整数部分存于
DIV_Mantissa[15:4]
,小数部分存于DIV_Fraction[3:0]
- 整数部分存于
cpp
// 设置115200波特率(系统时钟72MHz)
USART1->BRR = (72000000 / (115200 * 16)); // 计算结果=39.0625 → BRR=0x0273
3. 控制寄存器1(USART_CR1)
位 | 名称 | 功能 |
---|---|---|
13 | UE |
使能USART(1=使能,0=关闭) |
12 | M |
字长(0=8位,1=9位) |
10 | PCE |
校验使能(1=启用奇偶校验) |
3 | TE |
发送使能(1=开启TX) |
2 | RE |
接收使能(1=开启RX) |
cpp
// 使能8位数据、无校验、收发模式
USART1->CR1 |= USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;
4. 控制寄存器2(USART_CR2)
- 停止位控制 :
STOP[13:12]
:00
=1位停止位,01
=0.5位,10
=2位,11
=1.5位
cpp
// 设置1位停止位
USART1->CR2 &= ~USART_CR2_STOP; // 清零STOP位
5. 控制寄存器3(USART_CR3)
- 高级功能 :
DMAT
(位7):DMA发送使能DMAR
(位6):DMA接收使能RTSE
(位8):RTS硬件流控使能
cpp
// 启用DMA接收
USART1->CR3 |= USART_CR3_DMAR;
🔧 三、完整配置流程(寄存器版)
步骤1:使能时钟
cpp
RCC->APB2ENR |= RCC_APB2Periph_USART1; // USART1时钟使能(APB2总线)
RCC->APB2ENR |= RCC_APB2Periph_GPIOA; // GPIOA时钟使能
步骤2:配置GPIO为复用模式
cpp
// PA9(TX):复用推挽输出
GPIOA->CRH &= ~(0xF << 4); // 清除PA9配置
GPIOA->CRH |= (0xB << 4); // 50MHz复用推挽(CNF=10, MODE=11)
// PA10(RX):浮空输入
GPIOA->CRH &= ~(0xF << 8);
GPIOA->CRH |= (0x4 << 8); // 浮空输入(CNF=01, MODE=00)
步骤3:设置波特率与帧格式
cpp
USART1->BRR = 0x0273; // 72MHz下115200波特率
USART1->CR1 &= ~USART_CR1_M; // 8位数据
USART1->CR2 &= ~USART_CR2_STOP; // 1位停止位
USART1->CR1 &= ~USART_CR1_PCE; // 无校验
步骤4:使能收发与USART
cpp
USART1->CR1 |= USART_CR1_TE | USART_CR1_RE; // 使能发送和接收
USART1->CR1 |= USART_CR1_UE; // 使能USART
步骤5(可选):中断配置
cpp
USART1->CR1 |= USART_CR1_RXNEIE; // 接收中断使能
NVIC->ISER[0] |= (1 << USART1_IRQn); // 使能NVIC中断
💻 四、数据收发实战代码
1. 阻塞式发送函数
cpp
void USART_SendChar(uint8_t ch) {
while (!(USART1->SR & USART_SR_TXE)); // 等待发送寄存器空
USART1->DR = ch; // 写入数据
while (!(USART1->SR & USART_SR_TC)); // 等待发送完成
}
2. 中断接收服务函数
cpp
void USART1_IRQHandler(void) {
if (USART1->SR & USART_SR_RXNE) { // 检查接收中断标志
uint8_t data = USART1->DR; // 读取数据(自动清除RXNE)
// 处理接收到的数据...
}
}
⚠️ 五、关键注意事项
-
时钟一致性:
- USART1挂载APB2(最高72MHz),USART2/3挂载APB1(最高36MHz)
- BRR计算需根据实际总线频率调整。
-
中断标志清除:
RXNE
:读DR自动清除TC
:需"读SR + 写DR"序列清除
-
9位数据模式:
-
启用
USART_CR1_M
后,DR需按16位操作:cppuint16_t data = USART1->DR & 0x1FF; // 读取9位数据
-
-
硬件流控:
- 启用
USART_CR3_RTSE
/CTSE
时,需连接CTS/RTS引脚。
- 启用
🔍 六、调试技巧
-
状态寄存器诊断 :
cppif (USART1->SR & USART_SR_ORE) { // 检测溢出错误 USART1->SR &= ~USART_SR_ORE; // 写1清除错误标志 }
-
波特率验证 :
用示波器测量TX引脚波形,计算实际波特率:
实际波特率=1/位周期
通过直接操作寄存器,串口通信延迟可降至1μs以内(比库函数快3-5倍),适用于电机控制、高速传感器等实时场景