4. UART硬件模块初始化:时钟使能、GPIO复用功能配置、UART外设复位与使能
UART硬件模块的初始化是驱动开发的基础环节,也是中断模式通信能够稳定运行的前提。本节将系统讲解从时钟使能到外设使能的完整初始化链路,涵盖三个核心步骤:时钟使能、GPIO复用功能配置、UART外设复位与使能。每一步的遗漏或顺序错误,都可能导致通信失败或数据异常。
4.1 初始化流程总览
下图展示了UART硬件模块初始化的完整流程与各步骤之间的依赖关系。时钟使能是前提,GPIO复用功能配置紧随其后,最后完成外设复位与使能。
4.2 时钟使能:让UART模块获得工作时钟
时钟使能是初始化流程的第一步。MCU为了降低功耗,默认情况下大部分外设的时钟是关闭的。必须通过复位与时钟控制(RCC)寄存器,为UART外设提供工作时钟。
4.2.1 时钟使能的关键寄存器
| 寄存器 | 位域 | 操作 | 说明 |
|---|---|---|---|
| RCC_APB1ENR | Bit 17 (USART2EN) | 置1 | 使能USART2时钟(APB1总线) |
| RCC_APB1ENR | Bit 18 (USART3EN) | 置1 | 使能USART3时钟(APB1总线) |
| RCC_APB2ENR | Bit 14 (USART1EN) | 置1 | 使能USART1时钟(APB2总线) |
| RCC_APB2ENR | Bit 17 (USART6EN) | 置1 | 使能USART6时钟(APB2总线) |
4.2.2 时钟使能代码示例
/* 使能USART1时钟(APB2总线) */
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
/* 使能USART2时钟(APB1总线) */
RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
/* 使能USART3时钟(APB1总线) */
RCC->APB1ENR |= RCC_APB1ENR_USART3EN;
4.3 GPIO复用功能配置:将引脚连接到UART外设
时钟使能后,UART模块内部逻辑已获得时钟,但物理引脚(TX、RX)尚未与UART外设连接。必须将对应的GPIO引脚配置为复用功能(Alternate Function, AF)模式,并选择正确的复用号(AF编号),才能将UART的TX/RX信号路由到芯片引脚上。
4.3.1 GPIO复用配置步骤
- 配置GPIO模式:将引脚模式设置为复用功能(AF)。
- 配置输出类型:TX引脚通常设置为推挽输出(Push-Pull),RX引脚设置为浮空输入或上拉输入。
- 配置速度:建议设置为高速(High Speed),以适应波特率变化。
- 配置复用号:在GPIO_AFR寄存器中写入UART对应的AF编号。
4.3.2 常见UART引脚与复用号对照表
| UART实例 | TX引脚 | RX引脚 | 复用号(AF) |
|---|---|---|---|
| USART1 | PA9 | PA10 | AF7 |
| USART2 | PA2 | PA3 | AF7 |
| USART3 | PB10 | PB11 | AF7 |
| USART6 | PC6 | PC7 | AF8 |
4.3.3 GPIO复用配置代码示例
/* 以USART1(PA9=TX, PA10=RX)为例 */
/* 1. 使能GPIOA时钟 */
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
/* 2. 配置PA9和PA10为复用功能模式 */
GPIOA->MODER &= ~(GPIO_MODER_MODER9 | GPIO_MODER_MODER10);
GPIOA->MODER |= (GPIO_MODER_MODER9_1 | GPIO_MODER_MODER10_1); // 10: AF模式
/* 3. 配置输出类型:TX推挽,RX浮空输入 */
GPIOA->OTYPER &= ~GPIO_OTYPER_OT9; // TX推挽
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPDR10; // RX无上拉/下拉
/* 4. 配置速度:高速 */
GPIOA->OSPEEDR |= (GPIO_OSPEEDR_OSPEED9 | GPIO_OSPEEDR_OSPEED10);
/* 5. 配置复用号:AF7(USART1) */
GPIOA->AFR[1] &= ~(0xF << 4); // 清除PA9复用位
GPIOA->AFR[1] |= (7 << 4); // AF7
GPIOA->AFR[1] &= ~(0xF << 8); // 清除PA10复用位
GPIOA->AFR[1] |= (7 << 8); // AF7
4.4 UART外设复位与使能:确保外设处于已知状态
完成时钟使能和GPIO配置后,需要对UART外设进行复位和使能操作。复位操作将UART内部所有寄存器恢复为默认值,清除上电或之前配置可能遗留的脏数据;使能操作则正式激活UART外设,使其开始响应配置和收发数据。
4.4.1 外设复位操作
复位通过RCC的外设复位寄存器实现。复位操作通常采用“置位→短暂延时→清零”的序列,确保复位脉冲宽度满足硬件要求。
/* 复位USART1 */
RCC->APB2RSTR |= RCC_APB2RSTR_USART1RST; // 置位复位位
__NOP(); __NOP(); __NOP(); // 短暂延时(3个NOP)
RCC->APB2RSTR &= ~RCC_APB2RSTR_USART1RST; // 清除复位位
4.4.2 外设使能操作
使能操作通过UART控制寄存器1(USART_CR1)的UE(USART Enable)位实现。置位UE位后,UART外设开始工作,可以接收后续的波特率、数据格式、中断等配置。
/* 使能USART1 */
USART1->CR1 |= USART_CR1_UE; // 置位UE位,使能UART
4.4.3 复位与使能操作顺序
| 步骤 | 操作 | 寄存器 | 说明 |
|---|---|---|---|
| 1 | 置位复位位 | RCC_APBxRSTR | 将UART外设复位 |
| 2 | 等待复位完成 | — | 至少等待3~5个CPU周期 |
| 3 | 清除复位位 | RCC_APBxRSTR | 释放复位状态 |
| 4 | 置位UE位 | USART_CR1 | 使能UART外设 |
4.5 完整初始化代码示例
以下代码将上述三个步骤整合为一个完整的UART硬件初始化函数,以USART1为例:
void UART_Hardware_Init(void)
{
/* ========== 步骤1:时钟使能 ========== */
RCC->APB2ENR |= RCC_APB2ENR_USART1EN; // USART1时钟
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; // GPIOA时钟
/* ========== 步骤2:GPIO复用功能配置 ========== */
/* PA9 (TX): AF模式, 推挽输出, 高速 */
GPIOA->MODER &= ~GPIO_MODER_MODER9;
GPIOA->MODER |= GPIO_MODER_MODER9_1;
GPIOA->OTYPER &= ~GPIO_OTYPER_OT9;
GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEED9;
GPIOA->AFR[1] &= ~(0xF << 4);
GPIOA->AFR[1] |= (7 << 4); // AF7
/* PA10 (RX): AF模式, 浮空输入, 高速 */
GPIOA->MODER &= ~GPIO_MODER_MODER10;
GPIOA->MODER |= GPIO_MODER_MODER10_1;
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPDR10;
GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEED10;
GPIOA->AFR[1] &= ~(0xF << 8);
GPIOA->AFR[1] |= (7 << 8); // AF7
/* ========== 步骤3:外设复位与使能 ========== */
RCC->APB2RSTR |= RCC_APB2RSTR_USART1RST;
__NOP(); __NOP(); __NOP();
RCC->APB2RSTR &= ~RCC_APB2RSTR_USART1RST;
USART1->CR1 |= USART_CR1_UE; // 使能UART
}
4.6 初始化顺序检查清单
在调试UART通信问题时,请对照以下清单逐一排查初始化顺序:
- ☐ 时钟使能顺序:先使能GPIO时钟,再使能UART时钟?
- ☐ GPIO模式正确:TX/RX引脚是否配置为复用功能(AF)模式?
- ☐ 复用号匹配:AF编号是否与芯片参考手册一致?
- ☐ 外设复位执行:是否执行了置位→延时→清零的复位序列?
- ☐ UE位已置位:USART_CR1的UE位是否为1?
- ☐ 总线归属确认:UART实例挂载在APB1还是APB2?对应的RCC寄存器是否正确?
完成上述所有步骤后,UART硬件模块初始化即告完成,可以进入下一阶段的参数配置与中断使能环节。