本文主要从STM32F1平台出发,介绍时钟树的概念,结合时钟树的框图,详细讲解时钟树的基本原理和配置过程。

你可能会有的疑惑?

MCU的时钟树是跟着ARM的Cortex-M4架构走,还是跟着ST的F4系列走?
简单说,每款MCU的时钟树,都是芯片厂商为其“量身定制”的。ARM架构只是定义了内核需要哪些时钟信号以及如何与它们接口。而具体的时钟树配置,是由芯片厂商(ST)根据其具体的硬件资源和性能需求,进行定制的。

什么是时钟树?

MCU内部有许多外设,这些外设需要不同的时钟信号来工作。而我们的晶振只能产生单一频率的主时钟信号,
为了满足这些外设的不同时钟需求,我们需要对这个主时钟信号进行分频、倍频或相位调整,生成不同频率的时钟信号,供给不同的外设使用。最终各个时钟线呈现出来的结构就像一棵树一样,所以被称为时钟树。

时钟源

STM32F407时钟树

从图片可以看出来,STM32F4中有5个最重要的时钟源,为HSI、HSE、LSI、LSE、PLL。
其中PLL实际是分为两个时钟源,分别为主PLL和专用PLL。 讲解顺序是按图中蓝圈标示的顺序。
命名规则为:L代表Low,H代表High,S代表Speed,I代表Internal,E代表External。

LSI内部低速时钟

RC振荡器,频率为32kHz左右。供独立看门狗和自动唤醒单元使用。

LSE外部低速时钟

接频率为32.768kHz的石英晶体,这个主要是RTC的时钟源。

HSE外部高速时钟

可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~26MHz。HSE可以直接作为系统时钟或者PLL的输入。

HSI内部高速时钟

RC振荡器,频率为16MHz。可以直接作为系统时钟或者用作PLL输入。

PLL锁相环倍频输出

STM32F4有两个PLL:

  1. 主PLL(PLL)由HSE或者HSI提供时钟信号,并具有两个不同的输出时钟。
  • 第一个输出PLLP用于生成高速的系统时钟(最高168MHz)。
  • 第二个输出PLLQ用于生成USB OTG FS的时钟(48MHz),随机数发生器的时钟和SDIO时钟。
  • 专用PLL(PLLI2S)用于生成精确时钟,从而在I2S接口实现高品质音频性能。
    这里我们着重看看主PLL时钟第一个高速时钟输出PLLP的计算方法
  1. 大概分析:主PLL的输入先经过一个分频系数为M的分频器成为了VCO的时钟输入,
    (VCO是PLL的一部分,压控振荡器),然后再经过倍频系数为N的倍频器,
    最后再经过一个分频系数为P(系统时钟的)或者Q(外设时钟)的分频器之后才生成主PLL时钟。
  2. 举例分析
    (1)假设HSE = 8MHZ,我们选择了HSE作为PLL的时钟源,因为VCO的时钟必须要在1-2M之间,所以我们设置PLL_M = 8M,得到PLL_VCO = 1M.
    (2)接着VCO输入时钟经过VCO倍频因子N倍频之后,成为了VCO的时钟输出,VCO时钟必须在192-432M之间,我们配置N = 336,则VCO时钟输出为336M,VCO时钟输出后有3个分频因子。
  • PLLCLK 分频因子 P
  • 时钟分频因子 Q
  • 分频因子 R(F446 才有,F407 没有)。
  1. 有关 PLL 的配置有一个专门的 RCC PLL 配置寄存器RCC_PLLCFGR,具体描述看手册即可。
VCOCLK_IN = PLLCLK_IN / M = HSE / 8 = 1M
VCOCLK_OUT = VCOCLK_IN * N = 1M * 336 = 336M
PLLCLK_OUT=VCOCLK_OUT/P=336/2=168M

上面提到的系统时钟

系统时钟是MCU的主要时钟源,它提供给所有的外设。系统时钟来源可以是:HSI、PLLCLK、HSE,具体的由时钟配置寄存器RCC_CFGRSW位配置。
我们这里设置系统时钟:SYSCLK = PLLCLK = 168M。如果系统时钟是由 HSE 经过 PLL 倍频之后的 PLLCLK 得到,当 HSE 出现故障的时候,系统时钟会切换为 HSI=16M,直到 HSE 恢复正常为止。

AHB总线时钟HCLK

系统时钟 SYSCLK 经过 AHB 预分频器分频之后得到时钟叫 AHB 总线时钟,即 HCLK。
分频因子可以是:[1,2,4,8,16,64,128,256,512],具体的由时钟配置寄存器 RCC_CFGRHPRE位设置。
片上大部分外设的时钟都是经过 HCLK 分频得到,至于 AHB 总线上的外设的时钟设置为多少,得等到我们使用该外设的时候才设置,我们这里只需设置好 APB 的时钟即可。我们这里设置为 1 分频,即 HCLK=SYSCLK=168M。

APB2总线时钟PCLK2

APB2 总线时钟 PCLK2 由 HCLK 经过高速 APB2 预分频器得到。
分频因子可以 是:[1,2,4,8,16],具体由时钟配置寄存器RCC_CFGRPPRE2位设置。
HCLK2 属于高速的总线时钟,片上高速的外设就挂载到这条总线上,比如全部的 GPIO、USART1、SPI1 等。
至于 APB2 总线上的外设的时钟设置为多少,得等到我们使用该外设的时候才设置。
我们这里只需设置好 APB2 的时钟即可。我们这里设置为2分频,即PCLK2 = HCLK /2= 84M。

APB总线时钟PCLK1

APB1 总线时钟 PCLK1 由 HCLK 经过低速 APB 预分频器得到,分频因子可以是:[1,2,4,8,16]
具体由时钟配置寄存器RCC_CFGRPPRE1位设置。
HCLK1 属于低速的总线时钟,最高为 42M,片上低速的外设就挂载到这条总线上。
比如 USART2/3/4/5、SPI2/3,I2C1/2 等。
至于 APB1 总线上的外设的时钟设置为多少,得等到我们使用该外设的时候才设置。
我们这里只需设置好 APB1 的时钟即可。我们这里设置为4分频,即PCLK1 = HCLK/4 = 42M。

APBx定时器时钟

这个配置定时器的时候,需要特别注意
当APBx分频数为1的时候,对应定时器的时钟为APBx的时钟,否则对应定时器时钟都是APB总线的两倍。

SystemInit函数

在启动文件中,有一个名为 SystemInit 的函数,它是在单片机启动时被调用的。
这个函数的主要作用是初始化系统时钟,设置系统时钟源、分频器和倍频器。
在 SystemInit 函数中,我们可以个性化地配置系统时钟为我们需要的频率。