news 2026/7/1 9:41:11

认识时钟树F1

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
认识时钟树F1

下面按 STM32F103ZET6,也就是 F1 系列常见 72MHz 配置 来讲。你可以把“时钟树”理解成:单片机内部所有模块的“节拍来源分配图”。

1. 什么是时钟树?

STM32 里面很多模块都需要时钟才能工作,比如:

CPU 内核运行需要时钟

GPIO 需要时钟

USART 串口需要时钟

TIM 定时器需要时钟

ADC 需要时钟

I2C、SPI、DMA 等也需要时钟

这些时钟不是随便来的,而是从几个源头开始,经过 选择、倍频、分频,最后送到不同外设。

这整套结构就叫 时钟树。

可以简单理解为:

时钟源 → 选择 → PLL倍频 → 系统时钟SYSCLK → AHB/APB分频 → 各个外设

2. F1 的几个主要时钟源

STM32F1 常见有 4 个时钟源:

① HSI:内部高速时钟

HSI = 8MHz

HSI 是芯片内部自带的 RC 振荡器,不需要外接晶振。

优点:

不需要外部硬件

上电就能用

启动快

缺点:

精度不如外部晶振

做串口、USB、精确计时不如 HSE 稳定

一般刚上电时,STM32 默认先用 HSI 8MHz 启动。

② HSE:外部高速时钟

HSE 常见 = 8MHz

你用的正点原子 STM32F103ZET6 板子,一般外部晶振是 8MHz。

HSE 是外部晶振提供的时钟。

优点:

精度高

稳定

常用于 PLL 倍频到 72MHz

缺点:

需要外部晶振

启动比 HSI 稍慢一点

F1 最常用的系统主频配置就是:

HSE 8MHz → PLL ×9 → 72MHz

③ LSI:内部低速时钟

LSI ≈ 40kHz

LSI 是内部低速 RC 时钟。

主要给:

独立看门狗 IWDG

RTC 可选时钟源

它不太准,但不需要外部晶振。

④ LSE:外部低速时钟

LSE = 32.768kHz

LSE 一般接 32.768kHz 的手表晶振。

主要给:

RTC 实时时钟

它比较准,适合做年月日、时分秒。

3. 最核心的一条:F1 常用 72MHz 是怎么来的?

对于 STM32F103,最大主频一般是:

72MHz

常用配置是:

HSE = 8MHz

PLL倍频 = ×9

8MHz × 9 = 72MHz

也就是:

外部晶振 HSE

PLL 倍频器

PLLCLK = 72MHz

SYSCLK = 72MHz

SYSCLK 就是系统时钟,可以理解成单片机的主时钟。

4. SYSCLK、HCLK、PCLK1、PCLK2 分别是什么?

这几个名字很容易混,重点记住下面这张关系图:

SYSCLK 系统时钟

AHB 分频器

HCLK

CPU / 内存 / DMA / AHB总线

APB1 分频器 → PCLK1 → 低速外设

APB2 分频器 → PCLK2 → 高速外设

① SYSCLK

SYSCLK 是系统时钟,可以来自:

HSI

HSE

PLLCLK

最常用:

SYSCLK = PLLCLK = 72MHz

② HCLK

HCLK 是 AHB 总线时钟,也就是 CPU、DMA、内存这些用的时钟。

通常配置:

HCLK = SYSCLK / 1 = 72MHz

所以 CPU 实际运行频率一般就是 72MHz。

③ PCLK1

PCLK1 是 APB1 总线时钟。

APB1 最大只能到:

36MHz

所以当 HCLK 是 72MHz 时,APB1 必须二分频:

PCLK1 = HCLK / 2 = 36MHz

APB1 上常见外设:

TIM2、TIM3、TIM4、TIM5

USART2、USART3

I2C1、I2C2

SPI2

CAN

DAC

你之前用的 TIM3 就挂在 APB1 上。

④ PCLK2

PCLK2 是 APB2 总线时钟。

APB2 最大可以到:

72MHz

所以常用配置:

PCLK2 = HCLK / 1 = 72MHz

APB2 上常见外设:

GPIOA、GPIOB、GPIOC...

USART1

SPI1

ADC1、ADC2

TIM1

AFIO

你之前用的 USART1、GPIOA、GPIOB 都和 APB2 有关。

5. 最经典的 F1 72MHz 时钟配置

你可以直接记这个:

HSE = 8MHz

PLL = ×9

SYSCLK = 72MHz

AHB = /1

HCLK = 72MHz

APB1 = /2

PCLK1 = 36MHz

APB2 = /1

PCLK2 = 72MHz

ADC = PCLK2 /6 = 12MHz

整理成表格:

项目

配置结果HSE

8MHz8MHzPLL

×972MHzSYSCLK

PLLCLK72MHzAHB

/1HCLK = 72MHzAPB1

/2PCLK1 = 36MHzAPB2

/1PCLK2 = 72MHzADC

/6ADCCLK = 12MHz

6. 重点:定时器时钟有一个特殊规则

这个地方很重要,很多人学 PWM 会搞混。

规则是:

如果 APB 分频系数 = 1

定时器时钟 = PCLK

如果 APB 分频系数 > 1

定时器时钟 = PCLK × 2

例如你常用的 TIM3:

TIM3 在 APB1 上。

常用配置:

HCLK = 72MHz

APB1 = /2

PCLK1 = 36MHz

因为 APB1 分频系数是 2,大于 1,所以:

TIM3CLK = PCLK1 × 2 = 36MHz × 2 = 72MHz

也就是说,虽然 APB1 是 36MHz,但是 TIM3 的输入时钟还是 72MHz。

这就是为什么很多 PWM 计算时用的是 72MHz,而不是 36MHz。

7. 结合你之前的 TIM3_PWM_Init(7199, 1)

你之前代码里有:

TIM3_PWM_Init(7199, 1);

一般意思是:

ARR = 7199

PSC = 1

定时器 PWM 频率公式:

PWM频率 = 定时器时钟 / (PSC + 1) / (ARR + 1)

TIM3 时钟是 72MHz,所以:

PWM频率 = 72MHz / (1 + 1) / (7199 + 1)

= 72MHz / 2 / 7200

= 36MHz / 7200

= 5000Hz

所以你的 PWM 频率是:

5kHz

也就是说 TIM3 每秒输出 5000 个 PWM 周期。

8. PSC 和 ARR 分别控制什么?

定时器可以理解为一个自动计数器。

TIMxCLK → PSC预分频 → CNT计数 → 到ARR溢出

PSC:预分频器

PSC 负责先把时钟降下来。

公式:

计数频率 = TIMxCLK / (PSC + 1)

比如:

TIMxCLK = 72MHz

PSC = 71

那么:

计数频率 = 72MHz / 72 = 1MHz

也就是计数器 1 微秒加 1。

ARR:自动重装载值

ARR 决定计数器数到多少清零。

如果:

ARR = 999

计数器就是:

0, 1, 2, 3 ... 999

一共 1000 个数。

如果计数频率是 1MHz,那么一个 PWM 周期就是:

1000 × 1us = 1ms

频率就是:

1kHz

9. CCR 控制占空比

PWM 里面还有一个重要寄存器:

CCR

CCR 决定高电平持续多久。

在 PWM 模式 1 下,可以简单理解为:

CNT < CCR 时输出有效电平

CNT >= CCR 时输出无效电平

占空比公式:

占空比 = CCR / (ARR + 1)

比如:

ARR = 7199

CCR = 3600

那么:

占空比 = 3600 / 7200 = 50%

如果:

CCR = 7200

接近 100%。

如果:

CCR = 0

就是 0%。

你之前电机调速本质就是改 CCR。

10. CubeMX / HAL 里时钟树怎么看?

在 STM32CubeMX 里面,时钟树大概这样设置:

第一步:选择 HSE

RCC → High Speed Clock HSE → Crystal/Ceramic Resonator

意思是使用外部晶振。

第二步:PLL Source 选择 HSE

PLL Source Mux = HSE

第三步:PLL 倍频选择 ×9

PLL MUL = ×9

如果 HSE 是 8MHz:

8MHz × 9 = 72MHz

第四步:SYSCLK 选择 PLLCLK

System Clock Mux = PLLCLK

这样系统主频就是 72MHz。

第五步:设置总线分频

AHB Prescaler = /1

APB1 Prescaler = /2

APB2 Prescaler = /1

ADC Prescaler = /6

最后得到:

SYSCLK = 72MHz

HCLK = 72MHz

PCLK1 = 36MHz

PCLK2 = 72MHz

ADC = 12MHz

11. HAL 代码里时钟树怎么写?

HAL 工程里一般有一个函数:

void SystemClock_Config(void)

{

}

F103 72MHz 常见写法大概是:

void SystemClock_Config(void)

{

RCC_OscInitTypeDef RCC_OscInitStruct = {0};

RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

// 1. 配置外部高速晶振 HSE 和 PLL

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;

RCC_OscInitStruct.HSEState = RCC_HSE_ON;

RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;

RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;

RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;

HAL_RCC_OscConfig(&RCC_OscInitStruct);

// 2. 配置 SYSCLK、HCLK、PCLK1、PCLK2

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK |

RCC_CLOCKTYPE_SYSCLK |

RCC_CLOCKTYPE_PCLK1 |

RCC_CLOCKTYPE_PCLK2;

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;

RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;

RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;

RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);

}

重点看这几句:

RCC_OscInitStruct.HSEState = RCC_HSE_ON;

开启外部晶振。

RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;

PLL 使用 HSE 作为输入。

RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;

PLL 倍频 9 倍。

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;

系统时钟选择 PLL 输出。

RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;

APB1 分频为 2,所以 PCLK1 是 36MHz。

RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

APB2 不分频,所以 PCLK2 是 72MHz。

FLASH_LATENCY_2

72MHz 下 Flash 需要 2 个等待周期,这个很重要。

12. 为什么要设置 Flash 延迟?

CPU 跑到 72MHz 后,取指令速度很快。

Flash 读取速度跟不上 CPU,就需要加等待周期。

所以 72MHz 一般配置:

FLASH_LATENCY_2

如果这个设置不对,可能会出现:

程序跑飞

下载后不稳定

中断异常

代码莫名卡死

所以时钟配置不是只改 PLL,还要配 Flash 延迟。

13. 外设时钟和 RCC 有什么关系?

你之前经常看到这种代码:

__HAL_RCC_GPIOA_CLK_ENABLE();

__HAL_RCC_TIM3_CLK_ENABLE();

__HAL_RCC_USART1_CLK_ENABLE();

或者标准库版本:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

这就是给外设开时钟。

STM32 为了省电,外设默认很多是关闭时钟的。

比如 GPIOA 没开时钟,你就算配置 PA9、PA10,也没用。

可以理解为:

外设没有时钟 = 外设没通电 = 配置无效

14. 常见外设挂在哪条总线上?

你需要重点记这些。

APB2 外设

GPIOA

GPIOB

GPIOC

GPIOD

AFIO

USART1

SPI1

ADC1

ADC2

TIM1

所以 GPIO 初始化经常看到:

__HAL_RCC_GPIOA_CLK_ENABLE();

USART1 初始化会开:

__HAL_RCC_USART1_CLK_ENABLE();

APB1 外设

TIM2

TIM3

TIM4

TIM5

USART2

USART3

I2C1

I2C2

SPI2

CAN

你的小车 PWM 用 TIM3,所以它在 APB1 上:

__HAL_RCC_TIM3_CLK_ENABLE();

15. 为什么 APB1 不能直接 72MHz?

STM32F1 里面 APB1 属于低速外设总线,最大频率是:

36MHz

而 APB2 可以到:

72MHz

所以 72MHz 系统主频下,必须这样分:

APB1 = 72MHz / 2 = 36MHz

APB2 = 72MHz / 1 = 72MHz

如果 APB1 不分频,可能超出芯片手册限制,导致外设不稳定。

16. 串口波特率和时钟的关系

USART1 挂在 APB2:

USART1 时钟 = PCLK2 = 72MHz

USART2、USART3 挂在 APB1:

USART2/3 时钟 = PCLK1 = 36MHz

所以如果你用 USART1 蓝牙通信,波特率 9600 是根据 72MHz 算出来的。

如果系统时钟配置不对,比如本来以为是 72MHz,实际还是 8MHz,那么串口就会出现:

乱码

接收异常

蓝牙通信失败

所以串口乱码有时候不一定是接线错,也可能是系统时钟没配对。

17. ADC 时钟为什么要单独分频?

ADC 在 F1 里面最大时钟一般不能超过:

14MHz

如果 PCLK2 是 72MHz,ADC 不能直接用 72MHz。

所以常用:

ADC Clock = PCLK2 / 6 = 12MHz

或者:

ADC Clock = PCLK2 / 8 = 9MHz

所以 ADC 这一路一般要单独分频。

18. USB 为什么要求 48MHz?

STM32F103 如果使用 USB,USB 时钟要求:

48MHz

当 PLL 输出是 72MHz 时,可以通过:

USBCLK = PLLCLK / 1.5 = 48MHz

所以 F103 用 USB 时,72MHz 主频也很常见。

19. RTC 和看门狗的时钟

RTC 不走 SYSCLK 主时钟,而是可以从低速时钟来。

RTC 常见来源:

LSE 32.768kHz

LSI 40kHz

HSE / 128

独立看门狗 IWDG 通常使用:

LSI

这也是为什么有时候系统主时钟停了,看门狗还可以继续工作。

20. 用一张图总结 F1 时钟树

HSI 8MHz

├── 可直接作为 SYSCLK

└── HSI/2 → PLL

HSE 8MHz

├── 可直接作为 SYSCLK

└── PLL ×9

PLLCLK = 72MHz

SYSCLK = 72MHz

AHB /1

HCLK = 72MHz

│ │

│ ├── CPU

│ ├── DMA

│ └── 存储器

├── APB1 /2

│ ↓

│ PCLK1 = 36MHz

│ ↓

│ TIM2/3/4/5 实际可为 72MHz

│ USART2/3、I2C、SPI2

└── APB2 /1

PCLK2 = 72MHz

GPIO、USART1、SPI1、ADC、TIM1

21. 你现在最应该记住的版本

对于你现在做 STM32F103 小车、PWM、电机、蓝牙、OLED,先记这个就够了:

外部晶振 HSE = 8MHz

8MHz × 9 = 72MHz

SYSCLK = 72MHz

HCLK = 72MHz

PCLK1 = 36MHz

PCLK2 = 72MHz

TIM3CLK = 72MHz

USART1CLK = 72MHz

GPIO 时钟在 APB2

TIM3 时钟在 APB1

你之前 TIM3 PWM:

TIM3_PWM_Init(7199, 1);

对应:

TIM3CLK = 72MHz

PSC = 1

ARR = 7199

PWM频率 = 72MHz / 2 / 7200 = 5kHz

22. 一句话理解

STM32F1 时钟树的核心就是:

先用 HSE 8MHz 经过 PLL 倍频到 72MHz,

再把 72MHz 分给 CPU、总线和外设。

APB1 慢一点,最多 36MHz;

APB2 快一点,可以 72MHz;

定时器在 APB 分频不为 1 时,时钟会自动翻倍。

你学 PWM、串口、ADC、定时器的时候,基本都绕不开这棵时钟树。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/30 5:16:19

轻量化 5G 核心网:中小通信主体低成本建网最优方案

随着 5G SA 规模化落地&#xff0c;政企专网、区域运营商、MVNO、园区通信等市场需求持续释放&#xff0c;但传统一体化大型 5G 核心网设备投入高、部署周期长、运维门槛高&#xff0c;并不适配体量偏小的运营主体。在此背景下&#xff0c;轻量化 5G 核心网凭借集约架构、弹性扩…

作者头像 李华
网站建设 2026/7/1 8:30:26

用户画像化技术数据源整合与标签体系构建

用户画像化技术数据源整合与标签体系构建 在数字化时代&#xff0c;用户画像技术已成为企业精准营销、个性化推荐和用户行为分析的核心工具。通过整合多源数据并构建科学的标签体系&#xff0c;企业能够更全面地理解用户需求&#xff0c;提升服务体验。本文将围绕数据源整合与…

作者头像 李华
网站建设 2026/6/30 5:11:26

区块链应用架构设计

区块链应用架构设计&#xff1a;构建可信数字世界的基石 区块链技术正重塑金融、供应链、医疗等领域的信任机制&#xff0c;其核心在于通过去中心化、不可篡改和智能合约等特性&#xff0c;构建安全高效的应用架构。一个优秀的区块链应用架构设计不仅能解决传统系统的痛点&…

作者头像 李华
网站建设 2026/6/30 5:08:31

内部钓鱼演练误判为APT攻击的归因分析与治理路径设计

1. 项目概述&#xff1a;一次“乌龙”引发的深度思考最近在复盘我们团队去年的安全运营记录时&#xff0c;翻到了一个让我印象深刻的案例&#xff1a;一次精心策划的内部钓鱼邮件演练&#xff0c;在初期被安全运营中心&#xff08;SOC&#xff09;的同事高度紧张地判定为“疑似…

作者头像 李华
网站建设 2026/6/30 5:07:59

操作系统内存分配:伙伴系统与Slab分配器的结合

操作系统内存分配&#xff1a;伙伴系统与Slab分配器的结合 现代操作系统的内存管理需要兼顾效率与灵活性。伙伴系统&#xff08;Buddy System&#xff09;通过二分法快速分配连续物理页&#xff0c;但难以处理小对象&#xff1b;Slab分配器则针对高频小内存请求优化&#xff0…

作者头像 李华