4. UART硬件模块初始化:时钟使能、GPIO复用功能配置、UART外设复位与使能

UART硬件模块的初始化是驱动开发的基础环节,也是中断模式通信能够稳定运行的前提。本节将系统讲解从时钟使能到外设使能的完整初始化链路,涵盖三个核心步骤:时钟使能、GPIO复用功能配置、UART外设复位与使能。每一步的遗漏或顺序错误,都可能导致通信失败或数据异常。

4.1 初始化流程总览

下图展示了UART硬件模块初始化的完整流程与各步骤之间的依赖关系。时钟使能是前提,GPIO复用功能配置紧随其后,最后完成外设复位与使能。

UART硬件模块初始化流程 ① 时钟使能 RCC → UARTx_CLK_EN ② GPIO复用功能配置 AF模式 + 复用号 ③ 外设复位 RCC → UARTx_RST ④ 外设使能 USARTx->CR1 |= UE ⚠ 关键顺序约束: 必须先使能时钟,再配置GPIO复用功能,最后复位并使能UART外设。顺序颠倒可能导致寄存器写入无效。

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总线)
💡 专家提示: 不同UART实例挂载的总线不同。USART1和USART6通常挂在APB2(高速总线),USART2和USART3挂在APB1(低速总线)。务必查阅芯片参考手册确认总线归属,否则时钟使能无效。

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复用配置步骤

  1. 配置GPIO模式:将引脚模式设置为复用功能(AF)。
  2. 配置输出类型:TX引脚通常设置为推挽输出(Push-Pull),RX引脚设置为浮空输入或上拉输入。
  3. 配置速度:建议设置为高速(High Speed),以适应波特率变化。
  4. 配置复用号:在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
⚠ 常见错误: 忘记配置GPIO时钟(AHB1ENR)直接操作GPIO寄存器,会导致写入无效。另外,复用号写错(如USART6误写为AF7)会导致引脚无信号输出,这是排查UART通信故障时最容易忽略的原因之一。

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
}
📌 初始化完成标志: 执行完上述函数后,UART硬件模块已具备工作条件。此时可以安全地进行波特率设置、数据格式配置、中断使能等后续操作。建议在初始化函数末尾添加一个寄存器回读校验,确认UE位已成功置位。

4.6 初始化顺序检查清单

在调试UART通信问题时,请对照以下清单逐一排查初始化顺序:

  • ☐ 时钟使能顺序:先使能GPIO时钟,再使能UART时钟?
  • ☐ GPIO模式正确:TX/RX引脚是否配置为复用功能(AF)模式?
  • ☐ 复用号匹配:AF编号是否与芯片参考手册一致?
  • ☐ 外设复位执行:是否执行了置位→延时→清零的复位序列?
  • ☐ UE位已置位:USART_CR1的UE位是否为1?
  • ☐ 总线归属确认:UART实例挂载在APB1还是APB2?对应的RCC寄存器是否正确?

完成上述所有步骤后,UART硬件模块初始化即告完成,可以进入下一阶段的参数配置与中断使能环节。