3. 时钟

📌 本节学习目标
  • 理解 STM32 时钟树的结构
  • 掌握 HSE、HSI、PLL 等时钟源
  • 学会配置系统时钟 SYSCLK
  • 理解总线时钟(AHB、APB1、APB2)的分频关系

3.1 时钟系统概述

STM32 的时钟系统比 MCS-51 复杂得多。STM32F103 拥有多个时钟源和可编程的分频器,可以灵活配置各总线的时钟频率。

3.2 时钟源

时钟源类型频率用途
HSE(高速外部)外部晶振4~16MHz系统时钟 PLL 输入源
HSI(高速内部)内部 RC8MHz上电默认时钟,精度稍差
PLL(锁相环)倍频输出最高 72MHz系统时钟主要来源
LSE(低速外部)外部晶振32.768kHzRTC(实时时钟)
LSI(低速内部)内部 RC40kHz独立看门狗

3.3 时钟树

STM32 的时钟树结构如下:

HSE(8MHz) ─┬─→ PLLSRC ─→ PLLMUL(x9) ─→ SYSCLK(72MHz) ─┬─→ AHB 分频 ─┬─→ HCLK → Cortex-M3, MEM, FMC
           │                                              │              │
           │                                              │              ├─→ APB1 分频(÷2) → APB1(36MHz)
           │                                              │              │
           └─→ 直接作为 SYSCLK                           │              └─→ APB2 分频(÷1) → APB2(72MHz)
                                                          │
HSI(8MHz) ───────────────────────────────────────────→ SYSCLK(8MHz, 默认)

3.4 系统时钟配置示例

典型配置:HSE(8MHz) → PLL(x9) → SYSCLK(72MHz)

C 代码(系统时钟配置)
void HSE_SetSysClock(void)
{
    ErrorStatus HSEStatus;

    // 复位 RCC 配置
    RCC_DeInit();

    // 使能 HSE
    RCC_HSEConfig(RCC_HSE_ON);
    HSEStatus = RCC_WaitForHSEStartUp();

    if (HSEStatus == SUCCESS)
    {
        // 预取缓冲、Flash 等待周期(72MHz 需 2 个等待周期)
        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
        FLASH_SetLatency(FLASH_Latency_2);

        // HCLK = SYSCLK(AHB 不分频)
        RCC_HCLKConfig(RCC_SYSCLK_Div1);

        // PCLK2 = HCLK(APB2 不分频,最高 72MHz)
        RCC_PCLK2Config(RCC_HCLK_Div1);

        // PCLK1 = HCLK/2(APB1 最高 36MHz)
        RCC_PCLK1Config(RCC_HCLK_Div2);

        // PLL 配置:HSE(8MHz) × 9 = 72MHz
        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
        RCC_PLLCmd(ENABLE);
        while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

        // 选择 PLL 作为系统时钟
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
        while (RCC_GetSYSCLKSource() != 0x08);
    }
    else
    {
        // HSE 启动失败,使用 HSI 运行
    }
}
💡 这段代码怎么用?
  1. 实际工程中无需手写——SystemInit() 已按 SYSCLK_FREQ_xxMHz 宏自动完成同样的配置(见实验 08 时钟实验)
  2. 这段代码的意义在于讲清「先选时钟源 → 分频 → 倍频 → 切换系统时钟」的顺序,理解它才能排查时钟相关故障
  3. 关键检查点:RCC_WaitForHSEStartUp() 失败要回退 HSI;APB1 不能超 36MHz、APB2 不能超 72MHz
⚠️ 注意事项
  • APB1 总线最高 36MHz,APB2 最高 72MHz
  • 定时器的时钟与 APB 预分频系数相关
  • USART1 在 APB2 上,USART2/3 在 APB1 上
📎 配套资料课件:3.时钟.pptx | 实验:实验08:时钟实验