一、前言
RCC 全称:Reset and Clock Control 复位和时钟控制器
时钟是所有外设和STM32运行的心跳,没有时钟给出一个一个精准的脉搏,各个外设就无法和CPU或者其他外设通信。这一节就重点理解时钟树相关知识。
二、RCC(复位与时钟控制)
主要看看寄存器。
时钟控制寄存器(RCC_CR)
顾名思义,主要是负责控制时钟寄存器的控制的,比如是否启动PLL锁相环,锁相环是否锁定,选用哪个时钟源、是否启动CSS时钟安全系统等等,这些都是比较深入的知识,我们只需要知道有这个寄存器就行,可能就只会接触到PLL的那几位,寄存器配置图如下
时钟配置寄存器(RCC_CFGR)
这个就是配置时钟的参数,比如PLL倍频系数,HSI和HSE等的时钟频率是多少,分频系数是多少,和时钟最终频率值相关的寄存器。为了不占用篇幅就只截取我觉得有用的配置信息了
时钟中断寄存器 (RCC_CIR)
RCC_CIR 是 RCC 时钟中断寄存器,包含各个振荡器、PLL 就绪中断的使能位、中断标志和标志清除位;支持 HSE 故障 CSS 安全中断,作用是把时钟就绪事件从轮询改成中断通知,适合异步时钟切换和时钟故障保护。我没用过,还不清楚怎么使用
APB2外设复位寄存器 (RCC_APB2RSTR)
RCC_APB2RSTR 是 APB2 外设软件复位寄存器,对应位置 1 复位外设、清零释放复位;APB2 上 GPIO、USART1、SPI1、TIM1、AFIO 等在这里复位。
什么时候用它?
- 初始化外设的时候,先复位一遍,避免上次残留寄存器配置影响
- 运行过程中外设卡死,软件复位救一下(软件看门狗之外的一种手段)
- 写驱动、裸机寄存器版本,规范初始化流程必须带上
写1就是复位,写0就是无作用。标准操作流程:先写 1 复位 → 再写 0 释放复位
APB1外设复位寄存器 (RCC_APB1RSTR)
有2就有1,和APB2外设复位寄存器同理,复位寄存器用。
AHB外设时钟使能寄存器 (RCC_AHBENR)
给挂在 AHB 总线上的外设打开时钟(给心跳),1使能外设,0失能外设。
RCC_AHBENR → AHB 总线外设时钟
位定义(F1 最常用)
- bit0:DMA1EN — DMA1 时钟使能
- bit1:DMA2EN — DMA2 时钟使能(大容量才有)
- bit2:SRAMEN — SRAM 时钟(一般不用开,默认开启)
- bit3:FLITFEN — FLASH 闪存接口时钟
- bit4:CRCEN — CRC 校验模块时钟
- bit6:FSMCEN — 外部存储控制器(外接 SRAM、LCD、NOR Flash 才开)
APB1外设时钟使能寄存器(RCC_APB1ENR)
给挂在 APB1 总线上的外设打开时钟(给心跳),1使能外设,0失能外设。
APB2外设时钟使能寄存器(RCC_APB2ENR)
给挂在 APB2总线上的外设打开时钟(给心跳),1使能外设,0失能外设。
备份域控制寄存器(RCC_BDCR)
RCC_BDCR 是备份域控制寄存器,这一块由后备电池VBAT供电,主电源掉电还能继续跑时间。
控制 LSE 晶振、RTC 时钟源选择、RTC 时钟使能、备份域软件复位;属于 VBAT 备份域,普通系统复位不会清零;修改前必须打开 PWR 时钟、置位 PWR_CR 的 DBP 解除写保护;RTCSEL 选定后,只有备份域复位才能重新修改。
控制/状态寄存器(RCC_CSR)
主要管 LSI 内部低速振荡器 + 各种复位标志
| 位 | 名字 | 作用 |
|---|---|---|
| bit0 | LSION | LSI 内部低速 RC 振荡器开启:1 打开 |
| bit1 | LSIRDY | LSI 就绪标志(只读):1 代表稳定 |
| [23:28] 多个标志位 | 复位标志 | 记录上一次是因为什么复位 |
| bit31 | RMVF | 清除所有复位标志位,写 1 清零 |
三、时钟树结构
下面是在数据手册找到的一张时钟树的结构图,但是我还是更习惯看cubemx时钟树界面的结构图
这个是更方便理解的时钟树结构图。
四、时钟源
- HSI:高速内部 RC,8MHz内部自带,不用外部元件;精度差;复位默认时钟源
- HSE:高速外部晶振,常用 8MHz外部晶振,精度高;用来倍频出 72M 系统时钟(常用)
- LSE:低速外部,32.768K 晶振专门给 RTC 实时时钟
- LSI:低速内部 RC,约 40K给独立看门狗 IWDG,也可以给 RTC
PLL 锁相环:倍频器!把 HSE/HSI 放大,F1 最高倍频到 72MHz
五、三条总线
外设挂载在 AHB/APB1/APB2 不同总线上,用对应 ENR 寄存器打开时钟;例如GPIO 挂载 APB2 总线,时钟由 APB2ENR 控制。
时钟传递链路
SYSCLK(系统总时钟) → HPRE分频 → HCLK(AHB总线时钟) HCLK → PPRE2分频 → PCLK2(APB2总线时钟) HCLK → PPRE1分频 → PCLK1(APB1总线时钟)SYSCLK 可以理解成系统的总心跳,经过HPRE分频后传给AHB,AHB经过分频后传给自己的外设
然后 AHB 再把心跳经过PPRE1和PPRE2分频后分别传递给 APB1 和 APB2,这 2 条总线再把时钟分频之后,传给挂载在自己身上的外设,给他们当作心跳
AHB 总线(Advanced High-performance Bus 高级高性能总线)
SYSCLK (系统心跳)先送到 AHB,AHB 再分出 APB2、APB1;不同外设挂在不同总线上,总线最大时钟上限不一样
AHB 是高速主干总线,用来跑大批量数据搬运、存储器,带宽高; AHB 外设很少,我们初学最常碰到的就是 DMA。
挂载的设备有:
- DMA1、DMA2
- FLASH(闪存)、SRAM
- FSMC(外部存储,比如 LCD、SRAM)
- CRC 校验模块
- 内核的 SysTick 滴答定时器、NVIC 内核外设时钟也来自 HCLK
APB2 总线(Advanced Peripheral Bus 2,高速外设总线)
APB2 是高速外设口,放需要高速的外设:GPIO、ADC、SPI1、USART1。
时钟由AHB分频之后获得,挂载的设备有:
- GPIOA/GPIOB/GPIOC/GPIOD/GPIOE
- USART1
- SPI1
- ADC1、ADC2、ADC3
- AFIO(引脚重映射)
APB1 总线(低速外设总线)
时钟由AHB分频获得,最高不能超过36MHz(STM32F1 手册规定),包含的外设有:
- USART2、USART3、UART4、UART5
- SPI2、SPI3
- I2C1、I2C2
- 通用定时器 TIM2~TIM7
- 看门狗、CAN、USB
六、使用每一个外设的第一步:初始化时钟,给它心跳
所有的外设,启动的第一步永远是开启时钟:先开时钟,再配置寄存器!
- AHBENR:DMA
- APB2ENR:GPIO、USART1、SPI1、ADC、AFIO
- APB1ENR:USART2/3、I2C、TIM2~TIM7、CAN
RTC、看门狗:走低速时钟 LSE/LSI,不是 AHB/APB
例 1:GPIOB(APB2):
// 第一步:开GPIOB时钟 RCC->APB2ENR |= (1UL << 3); // 第二步:再配置GPIO寄存器(CRH、ODR) GPIOB->CRH &= ~(0xFUL << 20); GPIOB->CRH |= (0x8UL << 20); GPIOB->ODR |= (1UL << 13);例 2:USART1(串口 1,APB2):
//第一步:开USART1时钟 RCC->APB2ENR |= (1UL << 14); // 之后才配置波特率、控制寄存器等例 3:DMA1(AHB 总线!注意是 AHBENR):
//第一步:DMA1时钟,AHB总线,不是APB! RCC->AHBENR |= (1UL << 0);七、内核(CPU、NVIC 中断控制器、SCB 系统控制块)的时钟
内核(Cortex‑M3)的时钟就是 SYSCLK,不需要你手动去 “开时钟”,上电启动后由 RCC 负责给它送时钟。
内核心跳 SYSCLK 是【经过 RCC 多路选择器选出来之后的信号】
原始源头是 HSI / HSE / PLLCLK 这三个候选信号,送到一个多路选择开关(MUX)