以前使用STM32都是使用CubeMX,直接填数配置,简单方便,但是没有看过具体原理。现在使用标准库来手动配置系统时钟。

看下标准库中,PLL时钟配置函数
cpp
/**
* @brief 配置主PLL锁相环的时钟源、倍频与分频系数
* @note 仅当主PLL处于关闭状态时,才能调用此函数。
*
* @param RCC_PLLSource:选择PLL模块的输入时钟源
* 可选取值如下:
* @arg RCC_PLLSource_HSI:选择内部高速RC振荡器HSI作为PLL输入时钟
* @arg RCC_PLLSource_HSE:选择外部高速晶振HSE作为PLL输入时钟
* @note 该时钟源(RCC_PLLSource)同时供给主PLL与PLLI2S使用。
*
* @param PLLM:PLL内部VCO振荡器的输入分频系数
* 参数取值范围:0 ~ 63
* @note 必须合理设置PLLM,保证VCO输入时钟频率处于 1 ~ 2 MHz。
* 推荐输入频率选择2MHz,用来降低PLL时钟抖动。
*
* @param PLLN:PLL内部VCO振荡器的倍频系数
* 参数取值范围:50 ~ 432
* @note 必须合理设置PLLN,保证VCO输出时钟频率处于 100 ~ 432 MHz。
*
* @param PLLP:系统主时钟(SYSCLK)的输出分频系数
* 参数只能选取:2、4、6、8
* @note 配置PLLP时,务必保证最终系统时钟频率不超过168MHz。
*
* @param PLLQ:OTG FS、SDIO、RNG模块的时钟分频系数
* 参数取值范围:4 ~ 15
* @note 如果项目使用USB OTG FS,必须正确配置PLLQ,输出严格48MHz供给USB。
* SDIO与RNG外设要求输入时钟≤48MHz才能正常工作。
*
* @retval 无
*/
void RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t PLLM, uint32_t PLLN, uint32_t PLLP, uint32_t PLLQ)
{
/* 参数合法性检查 */
assert_param(IS_RCC_PLL_SOURCE(RCC_PLLSource));
assert_param(IS_RCC_PLLM_VALUE(PLLM));
assert_param(IS_RCC_PLLN_VALUE(PLLN));
assert_param(IS_RCC_PLLP_VALUE(PLLP));
assert_param(IS_RCC_PLLQ_VALUE(PLLQ));
// 将各个分频、倍频参数按照寄存器位定义,组合写入PLL配置寄存器
RCC->PLLCFGR = PLLM | (PLLN << 6) | (((PLLP >> 1) -1) << 16) | (RCC_PLLSource) |
(PLLQ << 24);
}
通过注释其实也就知道函数输入参数怎么设置。
总结一下:
1. RCC_PLLSource 【PLL 时钟源】
可选两种:
-
RCC_PLLSource_HSI:选择内部 16MHz 高速 RC 振荡器作为 PLL 输入 -
RCC_PLLSource_HSE:选择外部高速晶振作为 PLL 输入
作用:决定 PLL 从哪里获取原始基准时钟信号。
2. pllm → PLL_M 【预分频器】
PLL 输入分频器 原始时钟经过 PLL_M 分频,得到 VCO 输入频率。 公式: f_VCO_IN = f_时钟源 / PLL_M
3. plln → PLL_N 【倍频器】
VCO 倍频系数 1MHz 的基准信号送入 VCO 电压控制振荡器进行倍频 公式: f_VCO_OUT = f_VCO_IN × PLL_N
⚠️ 硬性限制:100MHz ≤ f_VCO_OUT ≤ 432MHz
举例:N=336 → 1M × 336 = 336MHz
4. pllp → PLL_P 【SYSCLK 分频器】
VCO 输出经过 P 分频后,得到系统时钟 SYSCLK(内核、AHB 总线主频) 公式: SYSCLK = f_VCO_OUT / PLL_P
⚠️ PLL_P 只能取值:2、4、6、8 F407 最大 SYSCLK = 168MHz,不能超过。
5. pllq → PLL_Q 【USB/SDIO 专用分频器】
VCO 输出另外一路独立分频,专门供给 USB OTG、SDIO。 公式: f_USB = f_VCO_OUT / PLL_Q
USB 硬件要求严格 48MHz; 不用 USB 时,Q 随便填合法数值即可,不影响单片机正常运行。
举例:
配置系统时钟频率为168M:
时钟源 = HSI (16MHz),M=16,N=336,P=2,Q=7
HSI 16MHz
↓【PLL_M 预分频】
16M /16 = 1MHz (VCO输入)
↓【PLL_N 倍频】
1M × 336 = 336MHz (VCO输出)
├→【PLL_P分频】 336M/2 = 168MHz → SYSCLK系统主频
└→【PLL_Q分频】 336M/7 = 48MHz → USB时钟
1、为什么不直接倍频到目标频率,非要 M→N→P 多级?
PLL 内部 VCO 有严格工作区间(100~432M),必须先升到高频 VCO,再分频输出,这是锁相环 PLL 硬件结构决定。
2、PLL 硬件 和 SYSCLK
PLL:锁相环,负责升频的模拟硬件模块;
SYSCLK:PLL 最终输出、供给内核运行的主时钟;
单片机所有外设时钟(CAN、TIM、USART、GPIO)全部由 SYSCLK 经过 AHB/APB 再次分频得到。