RCC即复位和时钟配置,今天主要写一下RCC时钟配置。
下图为我从用户手册中截图截取出来的时钟树,
由图可以看出:
STM32中共有5个时钟源,其中三个主要用作于系统时钟来源,另外两个分别供RTC实时时钟和IWDGCLK独立看门狗时钟。
系统时钟源:
HSI:高速内部时钟,内部的RC振荡器产生,频率为8MHz。默认启动,但精度不高。
HSE:高速外部时钟,外部晶振产生,可直接作为系统时钟,频率范围为4MHz~16MHz
PLL:锁相环倍频输出,其时钟输入源可选择为HSI的二分频、HSE的一分频或二分频。倍频可选择为2~16倍,但是其输出频率最大不得超过72MHz。
多采用HSE高速外部时钟经过PLL倍频作为系统时钟。
LSE:低速外部时钟,时钟来源外部的晶振或者外部的时钟信号。多用于给RTC(实时时钟)供电。
LSI:低速内部时钟,精度不高(内部的RC时钟一般不稳定),多用做独立看门狗时钟。
配置时钟流程:
1、将RCC寄存器重新设置为默认值 RCC_DeInit
2、打开外部高速时钟晶振 HSE RCC_HSEConfig(RCC_HSE_ON);
3、等待外部高速时钟晶振工作 HSEStartUpStatus =RCC_WaitForHSEStartUp();
4、设置AHB时钟 RCC_HCLKConfig;
5、设置高速APB2时钟 RCC_PCLK2Config;
6、设置低速APB1时钟 RCC_PCLK1Config
7、设置PLL RCC_PLLConfig
8、打开PLL RCC_PLLCmd(ENABLE);
9、等待PLL工作 while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
10、设置系统时钟 RCC_SYSCLKConfig
11、判断是否PLL是系统时钟 while(RCC_GetSYSCLKSource() != 0x08)
12、打开要使用的外设时钟 RCC_APB2PeriphClockCmd()/RCC_APB1PeriphClockCmd()
以下为设置HSE高速外部时钟经PLL倍频器9倍频后作为系统时钟的设置过程:
1 void RCC_Configuration(void) 2 { 3 ErrorStatus HSEStartUpStatus; /*定义枚举类型变量HSEStartUpStatus*/ 4 RCC_DeInit(); /*复位系统时钟设置*/ 5 RCC_HSEConfig(RCC_HSE_ON); /*开启HSE*/ 6 HSEStartUpStatus = RCC_WaitForHSEStartUp(); /*等待HSE起振并达到稳定*/ 7 if(HSEStartUpStatus == SUCCESS) /*判断HSE是否起振成功,起振成功了则开始执行后面的配置*/ 8 { 9 RCC_HCLKConfig(RCC_SYSCLK_Div1); /*选择HCLK(AHB)时钟源作为SYSCLK1分频*/ 10 RCC_PCLK2Config(RCC_HCLK_Div1); /*选择PCLK2(APB2)时钟源为HCLK(AHB)1分频*/ 11 RCC_PCLK1Config(RCC_HCLK_Div2); /*选择PCLK1(APB1)时钟源为HCLK(AHB)2分频*/ 12 FLASH_SetLatency(FLASH_Latency_2); /*设置Flash延时周期数为2*/ 13 FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); /*使能Flash预取缓存*/ 14 RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9); /*选择PLL时钟源为HSE1分频,倍频数为9,即PLL=8MHz×9=72MHz*/ 15 RCC_PLLCmd(ENABLE); /*使能PLL*/ 16 while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); /*等待PLL输出稳定*/ 17 RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); /*选择SYSCLK时钟源为PLL*/ 18 while(RCC_GetSYSCLKSource()!=0x08); /*等待PLL成为SYSCLK时钟源*/ 19 } 20 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); /*打开APB2总线上的GPIOB时钟*/ 21 }
在V3.5版本的库函数中,对时钟频率的选择进行了优化,官方库函数默认使用了8MHz的高速外部晶振,在启动文件中直接定义了 硬件频率、系统时钟、AHB总线频率、APB1总线频率、APB2总线频率,所以在使用3.5版本的库函数时,无需再写前面的那些众多的配置,可以直接根据需要打开相应位置的时钟,就像上面就可以简化成:
1 void RCC_Configuration(void) 2 { 3 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE); 4 }
此一来就将RCC时钟配置简化了许多。