参考资料:《 STM32F4xx 中文参考手册》 RCC 章节。
STM32时钟可大致分为系统时钟和其它时钟两大类,总共包含5个时钟源 HSI(High Speed Internal Clock)、HSE(High Speed External Clock)、LSI(low Speed Internal Clock)、LSE(Low Speed External Clock )、PLL(Phase Locked Loop Clock)。
下图即为STM32时钟树,黄色标识部分即为系统时钟部分,橙色即为其它时钟部分。
一、系统时钟
①HSE(High Speed External Clock)高速外部时钟信号
HSE 是高速的外部时钟信号,可以由有源晶振或者无源晶振提供,频率从 4-26MHZ不等。当使用有源晶振时,时钟从 OSC_IN
引脚进入,OSC_OUT 引脚悬空,当选用无源晶振时,时钟从 OSC_IN 和 OSC_OUT 进入,并且要配谐振电容。HSE 我们使用
25M 的无源晶振。如果我们使用 HSE 或者 HSE 经过 PLL倍频之后的时钟作为系统时钟 SYSCLK,当 HSE 故障时候,不仅
HSE 会被关闭,PLL也会被关闭,此时高速的内部时钟时钟信号HSI 会作为备用的系统时钟,直到 HSE 恢复正常,HSI=16M。
HSI(High Speed Internal Clock)高速内部时钟信号
由芯片内部RC振荡器提供,大小为16MHZ,当HSE故障时,系统时钟会自动切换到HSI,直到HSE 启动成功。
②锁相环 PLL(Phase Locked Loop )
PLL的主要作用是对时钟进行倍频,然后把时钟输出到各个功能部件。PLL有两个,一个是主 PLL(黄色部分,为系统时钟部
分),另外一个是专用的 PLLI2S(橙色部分),他们均由 HSE 或者 HSI 提供时钟输入信号。
主 PLL有两路的时钟输出,第一个输出时钟 PLLCLK用于系统时钟,第二个输出用于 USB OTG FS 的时钟、RNG 和 SDIO 时
钟。专用的 PLLI2S 用于生成精确时钟,给 I2S 提供时钟。
HSE 或者 HSI 经过 PLL 时钟输入分频因子 M分频后,成为 VCO 的时钟输入,VCO 的时钟必须在 1~2M 之间,我们选择
HSE=25M 作为 PLL 的时钟输入,M 设置为 25,那么 VCO输入时钟就等于 1M。VCO 输入时钟经过 VCO倍频因子 N 倍频之
后,成为 VCO时钟输出,VCO时钟必须在 192~432M 之间。我们配置 N 为 360,则 VCO的输出时钟等于 360M。VCO 输出时
钟之后有三个分频因子:PLLCLK分频因子 p,USB OTG FS/RNG/SDIO时钟分频因子 Q,分频因子R
具体公式如下
PLLCLK = HSE(HSI) / M *N /P
PLL48CK = HSE(HSI) / M *N /Q
③系统时钟 SYSCLK
系统时钟来源可以是:HSI、PLLCLK、HSE,具体的由时钟配置寄存器 RCC_CFGR的 SW位配置。如果系统时钟是由HSE 经
过 PLL倍频之后的 PLLCLK 得到,当 HSE 出现故障的时候,系统时钟会切换为HSI=16M,直到 HSE 恢复正常为止。
④AHB 总线时钟 HCLK
系统时钟 SYSCLK 经过 AHB 预分频器分频之后得到时钟叫 AHB 总线时钟,即 HCLK,分频因子可以是:[1,2,4,8,16,64,
128,256,512],具体的由时钟配置寄存器RCC_CFGR 的 HPRE 位设置。片上大部分外设的时钟都是经过 HCLK 分频得到,
至于 AHB总线上的外设的时钟设置为多少,得等到我们使用该外设的时候才设置。这里只需粗线条的设置好AHB的时钟即可。
⑤APB2总线时钟 PCLK2
APB2总线时钟 PCLK2 由 HCLK经过高速 APB2预分频器得到,分频因子可以是:[1,2,4,8,16],具体由时钟配置寄存器
RCC_CFGR 的 PPRE2位设置。HCLK2属于高速的总线时钟,片上高速的外设就挂载到这条总线上,比如全部的 GPIO、
USART1、SPI等。至于 APB2总线上的外设的时钟设置为多少,得等到我们使用该外设的时候才设置。这里只需粗线条的设置好
APB2的时钟即可。
⑥APB1总线时钟 PCLK1
APB1 总线时钟 PCLK1 由 HCLK经过低速 APB预分频器得到,分频因子可以是:[1,2,4,8,16],具体由时钟配置寄存器
RCC_CFGR的 PPRE1位设置。HCLK1属于低速的总线时钟,最高为 45M,片上低速的外设就挂载到这条总线上,比如
USART2/3/4/5、SPI2/3,I2C1/2等。至于 APB1总线上的外设的时钟设置为多少,得等到我们使用该外设的时候才设置。
这里只需粗线条的设置好APB的时钟即可。
系统初始化时钟过程如下
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
这是一个启动文件,当我们单片机上电后,首先执行的启动文件,会进入SystemInit函数
void SystemInit(void)
{
/* FPU设置 ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
#endif
/* 复位RCC时钟配置到默认的初始化状态 ------------*/
/* Set HSION bit */
RCC->CR |= (uint32_t)0x00000001;
/* Reset CFGR register */
RCC->CFGR = 0x00000000;
/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= (uint32_t)0xFEF6FFFF;
/* Reset PLLCFGR register */
RCC->PLLCFGR = 0x24003010;
/* Reset HSEBYP bit */
RCC->CR &= (uint32_t)0xFFFBFFFF;
/* Disable all interrupts */
RCC->CIR = 0x00000000;
#if defined(DATA_IN_ExtSRAM) || defined(DATA_IN_ExtSDRAM)
SystemInit_ExtMemCtl();
#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
/* 配置系统时钟 ----------------------------------*/
SetSysClock();
/* Configure the Vector Table location add offset address ------------------*/
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif
}
在SystemInit中会配置系统时钟
配置系统时钟的代码如下
下面是CMSIS Cortex-M4设备外围设备访问层系统源文件中的设置系统时钟函数SetSysClock(void)
static void SetSysClock(void)
{
/******************************************************************************/
/* 使用HSE作为PLL的输入来配置系统时钟 */
/******************************************************************************/
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* 一、使能HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* 等待HSE使能稳定,如果时间超时,则跳出 */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
/*二、HSE稳定后,开始配置HCLK、PCLK2、PCLK1、PLL各自的预分频因子与倍频因子 */
if (HSEStatus == (uint32_t)0x01)
{
/* 配置HCLK为1分频,即HCLK = 系统时钟 HCLK = SYSCLK / 1 */
RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
/*配置APB2总线时钟为2分频 PCLK2 = HCLK / 2 */
RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
/*配置APB1总线时钟为4分频PCLK1 = HCLK / 4 */
RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
/* 配置主PLL */
RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
(RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
/* 三、使能主PLL */
RCC->CR |= RCC_CR_PLLON;
/*等待主PLL稳定 */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/*------------------------------------------------------------------------------------------*/
/* 使能Over-drive 模式来达到更高的时钟频率 */
PWR->CR |= PWR_CR_ODEN;
while((PWR->CSR & PWR_CSR_ODRDY) == 0) //判断Over-drive模式是否已经成功启动
{
}
PWR->CR |= PWR_CR_ODSWEN;
while((PWR->CSR & PWR_CSR_ODSWRDY) == 0)
{
}
/*选择FLASH预取指缓存的模式, 指令缓存, 数据缓存和等待缓存 */
FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
/*------------------------------------------------------------------------------------------*/
/* 四、选择主PLL作为系统时钟源 */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= RCC_CFGR_SW_PLL;
/*判断系统时钟是否已经稳定 */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
{
}
}
else
{ /* 如果HSE启动失败,那么时钟就会被错误的配置,用户可以在这里添加一些代码来处理错误 */
}
}
系统时钟配置主要就是以上部分,系统时钟初始化就进行的是上述操作.
二、其它时钟
A、RTC时钟
RTCCLK 时钟源可以是 HSE 1 MHz( HSE 由一个可编程的预分频器分频)、 LSE 或者 LSI 时钟。选择方式是编程 RCC 备份
域控制寄存器 (RCC_BDCR) 中的 RTCSEL[1:0] 位和 RCC时钟配置寄存器 (RCC_CFGR) 中的 RTCPRE[4:0] 位。所做的选择只
能通过复位备份域的方式修改。我们通常的做法是由 LSE 给 RTC提供时钟,大小为 32.768KHZ。LSE由外接的晶体谐振器产生,
所配的谐振电容精度要求高,不然很容易不起震。
B、独立看门狗时钟
独立看门狗时钟由内部的低速时钟 LSI 提供,大小为 32KHZ。
C、I2S 时钟
I2S 时钟可由外部的时钟引脚 I2S_CKIN 输入,也可由专用的 PLLI2SCLK提供,具体的由 RCC 时钟配置寄存器 (RCC_CFGR)
的 I2SSCR位配置。
D、PHY以太网时钟
F429要想实现以太网功能,除了有本身内置的 MAC之外,还需要外接一个 PHY 芯片,常见的 PHY 芯片有 DP83848和
LAN8720,其中 DP83848支持 MII 和 RMII 接口,LAN8720只支持 RMII 接口。野火 F429 开发板用的是 RMII 接口,选择的
PHY 芯片是LAB8720。使用 RMII 接口的好处是使用的 IO 减少了一半,速度还是跟 MII 接口一样。当使用 RMII 接口时,PHY
芯片只需输出一路时钟给 MCU 即可,如果是 MII 接口,PHY 芯片则需要提供两路时钟给 MCU。
E、USB PHY 时钟
F429 的 USB 没有集成 PHY,要想实现 USB 高速传输的话,必须外置 USB PHY 芯片,常用的芯片是 USB3300。当外接 USB
PHY 芯片时,PHY 芯片需要给 MCU 提供一个时钟。
F、MCO时钟输出
MCO 是 microcontroller clock output 的缩写,是微控制器时钟输出引脚,主要作用是可以对外提供时钟,相当于一个有源晶振。
F429中有两个 MCO,由 PA8/PC9复用所得。MCO1所需的时钟源通过 RCC 时钟配置寄存器 (RCC_CFGR) 中MCO1PRE[2:0]
和MCO1[1:0]位选择。MCO2所需的时钟源通过 RCC 时钟配置寄存器 (RCC_CFGR) 中的MCO2PRE[2:0] 和 MCO2位选择。
以上就是STM32f429的时钟树讲解,理解之后,以此类推,对于学习STM32其它时钟树有很大的帮助。