stm32时钟初始化分析
要想了解stm32时钟配置,我们首先当了解其时钟树,以下是一张经典的stm32系统频率为72M的时钟树图
在系统启动时会首先调用SystemInit()函数,并在其中进行系统的一系列初始化,SystemInit()函数相关代码如下
void SystemInit (void)
{
/* Reset the RCC clock configuration to the default reset state(for debug purpose) */
/* Set HSION bit */
//置位HSION(Internal high-speed clock enable),开启内部8M高速时钟(HSI)
RCC->CR |= (uint32_t)0x00000001;
/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#ifndef STM32F10X_CL
//将SW(System clock switch)系统时钟切换为HSI,且将MCO(Microcontroller clock output)微控制器时钟输出置为没有时钟输出,
//将HPRE, PPRE1, PPRE2, ADCPRE(AHB PRESCALER,APB1 PRESCALER,APB2 PRESCALER, ADC PRESCALER)设置为0(不分频)
RCC->CFGR &= (uint32_t)0xF8FF0000;
#else
RCC->CFGR &= (uint32_t)0xF0FF0000;
#endif /* STM32F10X_CL */
/* Reset HSEON, CSSON and PLLON bits */
//关闭HSE,时钟安全系统(CSSON:Clock security system enable,如果外部4-16MHz振荡器就绪,时钟监测器开启),关闭PLL(重要)
RCC->CR &= (uint32_t)0xFEF6FFFF;
/* Reset HSEBYP bit */
//关闭HSE旁路模式(旁路模式:外部时钟信号(50%占空比的方波、正弦波或三角波)连到OSC_IN引脚,此时OSC_OUT为高阻态),有源晶振(加电就能输出,贵!!!)适用该模式。)
//然而大部分情况使用无源晶振,此处关了也没见再打开了
RCC->CR &= (uint32_t)0xFFFBFFFF;
/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
//初始化PLLSRC(PLL entry clock source)为0(HSI振荡器时钟经2分频后作为PLL输入时钟)
//PLLXTPRE (HSE divider for PLL entry HSE输入分频)为0(HSE不分频)
//PLLMUL(PLL multiplication factor,PLL输出倍频系数)为0000(PLL 2倍频输出),在初始化这三项前必须保证PLL关闭(此处PLL关闭了,系统时钟为HSI,所以初始化后PLL也没有工作)
//初始化USB分频系数
RCC->CFGR &= (uint32_t)0xFF80FFFF;
#ifndef STM32F10X_CL
/* Disable all interrupts and clear pending bits */
//该寄存器为与CSS,PLL,HSE,HSI,LSE,LSI相关中断,作用依次为清除对应中断标志位,使能中断和中断标志位状态(不打开中断当事件发生时interrupt flag会置1吗?)
RCC->CIR = 0x009F0000;
#else
/* Reset PLL2ON and PLL3ON bits */
RCC->CR &= (uint32_t)0xEBFFFFFF;
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x00FF0000;
/* Reset CFGR2 register */
RCC->CF