3. 时钟
📌 本节学习目标
- 理解 STM32 时钟树的结构
- 掌握 HSE、HSI、PLL 等时钟源
- 学会配置系统时钟 SYSCLK
- 理解总线时钟(AHB、APB1、APB2)的分频关系
3.1 时钟系统概述
STM32 的时钟系统比 MCS-51 复杂得多。STM32F103 拥有多个时钟源和可编程的分频器,可以灵活配置各总线的时钟频率。
3.2 时钟源
| 时钟源 | 类型 | 频率 | 用途 |
|---|---|---|---|
| HSE(高速外部) | 外部晶振 | 4~16MHz | 系统时钟 PLL 输入源 |
| HSI(高速内部) | 内部 RC | 8MHz | 上电默认时钟,精度稍差 |
| PLL(锁相环) | 倍频输出 | 最高 72MHz | 系统时钟主要来源 |
| LSE(低速外部) | 外部晶振 | 32.768kHz | RTC(实时时钟) |
| LSI(低速内部) | 内部 RC | 40kHz | 独立看门狗 |
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 运行
}
}💡 这段代码怎么用?
- 实际工程中无需手写——
SystemInit()已按SYSCLK_FREQ_xxMHz宏自动完成同样的配置(见实验 08 时钟实验) - 这段代码的意义在于讲清「先选时钟源 → 分频 → 倍频 → 切换系统时钟」的顺序,理解它才能排查时钟相关故障
- 关键检查点:
RCC_WaitForHSEStartUp()失败要回退 HSI;APB1 不能超 36MHz、APB2 不能超 72MHz
⚠️ 注意事项
- APB1 总线最高 36MHz,APB2 最高 72MHz
- 定时器的时钟与 APB 预分频系数相关
- USART1 在 APB2 上,USART2/3 在 APB1 上