Skip to content

RCC

RCC 全称 Reset and Clock Control(复位与时钟控制)

主要管两件事

一、心跳(时钟 Clock)

单片机是同步时序电路,所有的动作(取指令、发数据、计数)都需要跟着一个节拍走。这个节拍就是时钟

  • 频率:RCC 负责把外部晶振(比如 8MHz)或者内部震荡源,通过 PLL(锁相环) 倍频到 72MHz、168MHz 甚至更高,供给 CPU 狂奔。
  • 分频:CPU 跑太快,有些慢速外设(比如看门狗、简单的定时器)跟不上,RCC 还要负责把频率降下来分给它们。

2. 开闸(时钟门控 Clock Gating)—— 新手第一大坑!

这是 ARM 架构为了省电设计的机制。

  • 默认状态:单片机里所有的外设(GPIOA, ADC, SPI...),默认时钟都是关断的!
  • 后果:如果你不开启某个外设的时钟,就算你把 GPIO 的模式配置代码写出一朵花来,那个引脚也不会有任何反应,因为它的逻辑电路根本没通电(没时钟驱动)。

老鸟比喻: 单片机是一栋大楼。 RCC 就是大楼的配电室。 你想用 3 楼会议室(SPI1)的灯,你必须先给配电室打电话:“把 3 楼的电闸推上去!”。否则你按断了开关也没用。

二、RCC 的标志位(Flags)

RCC 的标志位主要集中在系统启动故障诊断阶段。平时跑业务代码时很少看,但在 SystemInit(系统初始化)函数里,它们是主角。

1. “准备就绪”类标志 (Ready Flags)

单片机刚上电时,晶振起振、PLL 锁定都需要时间(虽然很短)。CPU 必须等它们稳了才能切换时钟源,否则会跑飞。

  • HSIRDY (High Speed Internal Ready):内部高速时钟(HSI)稳定了。
    • 上电默认就是它,虽然不准,但最快能用。
  • HSERDY (High Speed External Ready):外部高速晶振(HSE)稳定了。
    • 这是我们最关注的。因为外部晶振最准,但它容易不起振(比如虚焊)。
  • PLLRDY (PLL Ready):锁相环(PLL)锁定完成了。
    • 这时候 CPU 就可以切换到高速模式(比如 72MHz)了。

代码里的经典等待(启动流程):

C

// 开启外部晶振
RCC_HSEConfig(RCC_HSE_ON);

// 死等 HSERDY 变 1。
// 如果硬件坏了,程序就会卡死在这里(或者超时退出)
while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);

// ... 配置 PLL ...
// ... 开启 PLL ...

// 死等 PLL 稳定
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

2. “死亡原因”类标志 (Reset Flags) —— 老鸟查 Bug 神器

当你的单片机莫名其妙重启了,你怎么知道是因为掉电了?还是代码跑飞了?还是看门狗咬人了? RCC 有一组标志位专门记录**“上次是怎么死的”**。

  • PINRSTF (Pin Reset Flag):被复位引脚(NRST)拉低导致的重启。
    • 人话:有人按了复位键,或者下载器复位了芯片。
  • PORRSTF (Power-On/Power-Down Reset Flag):上电/掉电复位。
    • 人话:刚插上电,或者电源波动太大导致重启。
  • SFTRSTF (Software Reset Flag):软件复位。
    • 人话:代码里调用了 NVIC_SystemReset() 自己杀死了自己。
  • IWDGRSTF (Independent Watchdog Reset Flag):独立看门狗复位。
    • 人话:程序卡死了,没喂狗,被狗咬死了。这个标志位对排查“死机”问题至关重要!

3. CSS (Clock Security System) 标志

  • CSSF (Clock Security System Interrupt Flag):时钟安全系统中断标志。
    • 高级功能:如果你的外部晶振突然坏了(比如受到撞击),RCC 会自动监测到,把时钟源切回内部 HSI,并置位这个标志,触发 NMI(不可屏蔽中断)。让你有机会报警或安全停机。

时钟树 (Clock Tree) 避坑指南

了解 RCC,必须看懂时钟树。为了让你理解,我需要强调几个关键的“总线”概念。

1. AHB, APB1, APB2 的区别

单片机内部有不同的“高速公路”。

  • AHB (Advanced High-performance Bus):高铁。连接 CPU、DMA、Flash。速度最快(通常 72MHz 或 168MHz)。
  • APB2 (Advanced Peripheral Bus 2):快速路。连接 GPIO、串口1、SPI1、ADC。速度较快(通常全速)。
  • APB1 (Advanced Peripheral Bus 1):慢速路。连接 I2C、串口2/3、SPI2、定时器2/3/4。注意:它的速度通常被限制在 AHB 的一半!

2. 只有老手知道的“倍频坑”

  • 坑点:虽然 APB1 的时钟被除以 2 了(比如 AHB=72M,APB1=36M),但是挂在 APB1 上的定时器(TIM2,3,4...),RCC 会自动给它乘 2
  • 结果:虽然 APB1 是 36MHz,但 TIM2 的计数时钟其实还是 72MHz。
  • 影响:很多新手算定时器时间的时候,按照 36M 去算,结果发现定时器快了一倍,百思不得其解。

3. 为什么我的 SPI/I2C 不工作?

  • 检查清单第一条RCC_APB2PeriphClockCmd 还是 RCC_APB1PeriphClockCmd
  • STM32 的外设挂在不同的总线上。
    • SPI1 在 APB2。
    • SPI2 在 APB1。
  • 如果你写 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI2, ENABLE);,编译器不会报错(因为宏定义只是数字),但代码跑起来 SPI2 永远没电。因为你去“快速路”的配电箱开了“慢速路”的灯。

总结

  1. RCC 是外设吗? 是,它是控制所有外设的大管家
  2. 核心标志位
    • HSERDY / PLLRDY:开机时检查,看时钟稳没稳。
    • IWDGRSTF:死机重启后检查,看是不是被看门狗咬了。
  3. 最高频动作:开启外设时钟(Clock Gating)。写任何外设驱动的第一行代码,必须是 RCC Enable!