006 - STM32学习笔记 - RCC时钟树
本节内容一定要结合RCC时钟树和官方手册学习,如果看不明白的话,建议看一下野火官方的教程,火哥讲这节讲的很详细,看一遍基本就能理解了。
上节内容中分析了启动代码,在启动代码中看到开发板上电后,会先执行Reset_Handler复位程序,里面会调用SystemInit程序
; Reset handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
LDR R0, =SystemInit ;此处调用了SystemInit,此函数的实现实在system_stm32f4xx.c中
BLX R0
LDR R0, =__main
BX R0
ENDP
SystemInit函数原型
void SystemInit(void)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
#endif
/* 设置RCC_CR中HSION位,即启用HSI时钟*/
RCC->CR |= (uint32_t)0x00000001;
/* 复位CFGR寄存器*/
RCC->CFGR = 0x00000000;
/* 复位RCC_CR中HSEON、CSSON、PLLON位,在后面会用SetSysClock在重新设置*/
RCC->CR &= (uint32_t)0xFEF6FFFF;
/* 复位锁相环时钟配置器*/
RCC->PLLCFGR = 0x24003010;
/* 复位HSE旁路时钟 */
RCC->CR &= (uint32_t)0xFFFBFFFF;
/* 关闭所有中断 */
RCC->CIR = 0x00000000;
#if defined(DATA_IN_ExtSRAM) || defined(DATA_IN_ExtSDRAM)
SystemInit_ExtMemCtl();
#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
/* 配置系统时钟,锁相环时钟及分频因子,AHB/APBx预分频及Flash设置 */
SetSysClock(); //着重看这个函数实现,代码太长,这个函数原型就不往这贴了,下节会再把这个函数原型的学习笔记贴上来
/* 配置向量表*/
#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
}
1、HSE时钟
HSE:High Speed External Clock Signal,外部高速时钟。一般来源为有源晶振或无源晶振,其中有源晶振频率可以达到1-50M,而无源晶振频率在4-26M之间。在429芯片上,通过OSC_OUT和OSC_IN两个引脚输入。我用的野火F429开发板使用的是无源晶振(25MHz),启用HSE需要在RCC时钟控制器(RCC_CR)中将HSE_ON置位,如果此位未写1,则系统默认启动HSI时钟
2、HSI时钟
HSI:High Speed Internal Clock Signal,内部高速时钟,当设置使用HSE后,如果HSE发生故障没有起振,系统会自动切换到HSI,等到HSE启动成功后,则会切换回HSE,429的HSI是集成到芯片内部,频率为16HHz。启用HSI需要在RCC时钟控制器(RCC_CR)中将HSI_ON置位(未选择启用HSE或者HSE故障时,系统会强制启动,所以实际此位不用操作)。
3、PLL锁相环
不论是HSE还是HSI时钟,作为系统时钟来说远远不够,而外部晶振频率越高,其功耗也会增加,且误差也会增大,因此需要经过一系列操作,将HSE或HSI经过分频因子M分频后,在通过倍频因子N,之后在经过分频因子P,最后计算出锁相环时钟PLLCLK。
P
L
L
C
L
K
=
(
H
S
E
/
M
)
∗
N
/
P
PLLCLK = ( HSE / M ) * N / P
PLLCLK=(HSE/M)∗N/P
锁相环通过RCC_PLLCFGR中PLLSRC寄存器进行配置,写0:选择HSI时钟作为PLL和PLLI2S时钟输入,写1:选择HSE振荡器作为PLL和PLLI2S时钟输入。
M:主PLL和PLLI2S输入时钟分频系数,通过PLLM寄存器进行配置,可选配置数值可以从2-63;
这里需要注意在官方手册中,关于M的配置中有提示项,建议将VCO输入控制在1M-2M之间,因此此处M我们设置在选择为25,计算后25M/25 = 1MHz;
N:用于控制VCO的主PLL的倍频系数,通过PLLN寄存器配置,可选配置数值为2-432
这里官方提示VCO输出频率应该介于192-432MHz之间,后续计算方便,选择配置为360。
P:主系统时钟的主PLL分频系数
官方提示最终输出频率上限不能超过180MHz,因此这里选择分频因子p的值为2。
在以上数据选择完后,经过计算,最终PLLCLK的值为180MHz。
P
L
L
C
L
K
=
25
/
25
∗
/
360
/
2
=
180
M
H
z
PLLCLK = 25 / 25 * / 360 / 2 = 180MHz
PLLCLK=25/25∗/360/2=180MHz
4、系统时钟
SYSCLK,在429中,系统时钟最高为180MHz,F407最高为168MHz,其来源主要由HSI、HSE以及PLLCLK提供,当HSE以及PLLCLK发生故障时,硬件强制会自动强制使用HSI为SYSCLK提供时钟,此时系统运行将特别慢。此项选择由RCC时钟配置寄存器RCC_CFGR中SW位1:0选择可选配置如下:
-
00:选择由HSI振荡器作为系统时钟;
-
01:选择由HSE振荡器作为系统时钟;
-
10:选择由PLL作为i系统时钟
-
11:不选择。
这里由于配置了锁相环(PLLCLK),则选择配置为10。
HCLK时钟
HCLK:AHB高速总线时钟,在F429中频率最高为180MHz,其主要为AHB总线外设、系统定时器(Systick)、内核(FCLK)提供时钟。可配置为不分频/2/4/8/16/64/128/258/512分频。
PCLK1时钟
APB低速预分频器,最高为45MHz,主要为APB1总线外设提供时钟,2倍频后为APB1总线的定时器提供时钟,最大可达到90MHz。由RCC_CFGR时钟配置寄存器PPRE1位控制。可配置为不分频/2/4/8/16分频。
PCLK2时钟
APB高速预分频器,最高为90MHz,主要为APB2总线外设提供时钟,2倍频后为APB1总线的定时器提供时钟,最大可达到180MHz。由RCC_CFGR时钟配置寄存器PPRE2位控制。可配置为不分频/2/4/8/16分频。
在时钟树中,看到除了P之外,还有两个分频因子Q和R,其中Q主要为PLL48CK提供时钟,主要用于全速USB和随机数发生器以及SDIO提供时钟。
而R主要是在F446芯片中使用到,这里不做说明。
5、其他时钟
RTC时钟
RTC:为芯片内部的RTC提供时钟,来源于HSE_RTC(HSE分频得到)、LSE(外部32.768KHz晶振提供)、LSI(32KHz),由RCC备份域控制寄存器RCC_BDCR:RTCSEL位控制。
后面学到的看门狗时钟IWDGCLK就是由LSI提供的。
I2S时钟
由外部引脚I2S_CKIN或者PLLI2SCLK提供。
以太网PHY时钟
F429中没有集成PHY,所以只能外接PHY,野火F429上外接的是LAN8720,大小为50MHz。这里研究了一下野火的原理图,看到PHY芯片是由一个外部25MHz的晶振提供时钟,进入PHY芯片后,经过2倍频变为50HMz,在经过PA1引脚输入429中。
USB PHY时钟
同样429中没有集成PHY,野火上外接的是USB33000,USB PHY就由USB33000提供。
MCO时钟输出
MCO是将控制器的时钟通过外部的引脚输出,可以给外部设备提供时钟,在429上引脚为MCO1为PA8,由HSI、LSE、HSE、PLLCLK提供,MCO2为PC9,由HSE、PLLCLK、SYSCLK、PLLI2SCLK提供。这里可以通过MCO输出时钟到PHY芯片,可以省掉PHY所需的晶振,节约成本。软件中设置MCO输出后,可用示波器检测系统时钟是否配置正确。