4. 系统时钟(SYSCLK)与总线时钟(AHB/APB1/APB2)分频设定:分频系数选择与最大频率限制

4.1 原理概述

在 STM32 时钟树中,SYSCLK(系统时钟)是内核与总线时钟的源头,它由 HSI、HSE 或 PLL 输出提供。SYSCLK 经过三级预分频器逐级分配到各总线域:

  • AHB 预分频器(HPRE) — 将 SYSCLK 分频后产生 HCLK(AHB 总线时钟),也作为内核时钟。
  • APB1 预分频器(PPRE1) — 将 HCLK 分频后产生 PCLK1(APB1 总线时钟),供低速外设使用。
  • APB2 预分频器(PPRE2) — 将 HCLK 分频后产生 PCLK2(APB2 总线时钟),供高速外设使用。

每条总线都有严格的 最大频率上限,超出限制将导致外设工作异常或芯片不稳定。合理选择分频系数是系统设计的第一步。

关键约束(以 STM32F103 为例):
SYSCLK ≤ 72 MHz | HCLK ≤ 72 MHz | PCLK1 ≤ 36 MHz | PCLK2 ≤ 72 MHz
STM32 时钟树 — SYSCLK 与 AHB/APB 分频结构 SYSCLK 系统时钟 最大 72 MHz AHB Prescaler HPRE 分频 1/2/4/8/16/64/128/256/512 AHB Bus (HCLK) 最大 72 MHz APB1 Prescaler PPRE1 分频 1/2/4/8/16 APB2 Prescaler PPRE2 分频 1/2/4/8/16 APB1 Bus (PCLK1) 最大 36 MHz APB2 Bus (PCLK2) 最大 72 MHz SYSCLK / AHB 总线 预分频器 APB1 相关 APB2 相关 时钟路径(带箭头)

4.2 分频系数与最大频率限制

下表列出三个预分频器支持的分频系数及对应的总线频率上限(基于 SYSCLK = 72 MHz 计算)。

分频器寄存器位域可选分频系数目标总线最大允许频率
HPRECFGR[7:4]1, 2, 4, 8, 16, 64, 128, 256, 512HCLK(AHB)72 MHz
PPRE1CFGR[10:8]1, 2, 4, 8, 16PCLK1(APB1)36 MHz
PPRE2CFGR[13:11]1, 2, 4, 8, 16PCLK2(APB2)72 MHz
设计准则:APB1 频率必须 ≤ 36 MHz,因此当 HCLK = 72 MHz 时,PPRE1 至少选 2 分频;PPRE2 可直接使用 1 分频(72 MHz)以获取最高外设性能。

4.3 实现流程

  1. 确定 SYSCLK 来源与频率 — 选择 HSI、HSE 或 PLL 输出作为系统时钟源。
  2. 设定 HPRE 分频系数 — 使 HCLK ≤ 72 MHz,同时满足内核与存储器访问时序。
  3. 设定 PPRE1 分频系数 — 确保 PCLK1 ≤ 36 MHz,并考虑 USART、I²C、SPI2 等外设的时钟需求。
  4. 设定 PPRE2 分频系数 — 确保 PCLK2 ≤ 72 MHz,为 GPIO、SPI1、USART1 等高速外设提供足够带宽。
  5. 配置闪存等待周期 — 根据 SYSCLK 频率设置 FLASH_ACR.LATENCY,保证指令预取稳定。
  6. 验证时钟配置 — 读取 RCC_CFGR 寄存器或调用 HAL 库频率获取函数,确认各总线频率符合预期。

4.4 代码实现

4.4.1 寄存器直接配置(以 STM32F1 为例)

/* 假设 SYSCLK 已经通过 PLL 锁定在 72 MHz */
/* 1. 设置 AHB 分频系数 = 1  (HCLK = 72 MHz) */
RCC->CFGR &= ~RCC_CFGR_HPRE;              /* 清空 HPRE[3:0] */
RCC->CFGR |= RCC_CFGR_HPRE_DIV1;          /* 0x0: 不分频 */
/* 2. 设置 APB1 分频系数 = 2  (PCLK1 = 36 MHz) */
RCC->CFGR &= ~RCC_CFGR_PPRE1;             /* 清空 PPRE1[2:0] */
RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;         /* 0x4: 2 分频 */
/* 3. 设置 APB2 分频系数 = 1  (PCLK2 = 72 MHz) */
RCC->CFGR &= ~RCC_CFGR_PPRE2;             /* 清空 PPRE2[2:0] */
RCC->CFGR |= RCC_CFGR_PPRE2_DIV1;         /* 0x0: 不分频 */
/* 4. 配置闪存等待周期 (SYSCLK=72MHz, 需要 2 个等待周期) */
FLASH->ACR = (FLASH->ACR & ~FLASH_ACR_LATENCY)
           | FLASH_ACR_LATENCY_2