以STM32F103C8T6为例,参考《技术手册》,《数据手册》,《标准库函数手册》,个人学习笔记,供参考和指正。
·STM32103C8T6共5个时钟源,HSE,HSI,PLL,LSE,LSI,前三者为系统时钟源,LSE和LSI用于驱动RTC,LSI用于喂养看门狗
·AHB域和APB2域的最大为72MHZ;APB1域最大允许频率为36MHZ;
·如果HSE晶体振荡器失效,HSI时钟会被作为备用时钟源;
·HSI通常不会作为系统时钟,因为即使在校准之后它的时钟频率精度仍较差
·附录,库函数表
1)为什么一句APB2外设时钟使能,一个GPIO初始化,就可以运行,在这之前,你并没有配置时钟?
2)如果HSE晶体振荡器失效,HSI时钟会被作为备用时钟源?
3)如果我想要配置HSI_PLL系统时钟频率为64MHZ该怎么操作?
4)如果我想要配置HSE_PLL系统时钟频率为48MHZ该怎么操作?
1)为什么一句APB2外设时钟使能,一个GPIO初始化,就可以运行,在这之前,你并没有配置时钟?
因为在启动文件中已经默认配置时钟为72MHZ;每次设备复位后,先开启HSI(因为它的启动时间较短为什么要配置外部时钟,因为HSI不太稳定通常易受到干扰),然后再由HSE经PLL倍频为72MHZ。在system_stm32f103x.c文件中查到
After each device reset the HSI (8 MHz) is used as system clock source.
Then SystemInit() function is called, in "startup_stm32f10x_xx.s" file,
to configure the system clock before to branch to main program.
在启动文件的SystemInit函数中首先开启了HSI时钟
RCC->CR |= (uint32_t)0x00000001;/* Set HSION bit */
在 SystemInit函数中的SetSysClock函数,继续初始化时钟
static void SetSysClock(void)
{
#ifdef SYSCLK_FREQ_HSE
SetSysClockToHSE();
#elif defined SYSCLK_FREQ_24MHz
SetSysClockTo24();
#elif defined SYSCLK_FREQ_36MHz
SetSysClockTo36();
#elif defined SYSCLK_FREQ_48MHz
SetSysClockTo48();
#elif defined SYSCLK_FREQ_56MHz
SetSysClockTo56();
#elif defined SYSCLK_FREQ_72MHz
SetSysClockTo72();
#endif
/* If none of the define above is enabled, the HSI is used as System clock
source (default after reset重置后的默认值),如果以上定义都没有启用, HSI将用作系统时钟,也就是8MHZ的系统时钟*/
}
在system_stm32f103x.c文件中。如果宏定义STM32F10X_LD_VL或STM32F10X_MD_VL或 STM32F10X_HD_VL,系统频率被选为24MHZ,如果没有,将宏定义SYSCLK_FREQ_72MHz,系统时钟会被选择为72MHZ,然后会在上面执行 SetSysClockTo72();
#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
/* #define SYSCLK_FREQ_HSE HSE_VALUE */
#define SYSCLK_FREQ_24MHz 24000000
#else
/* #define SYSCLK_FREQ_HSE HSE_VALUE */
/* #define SYSCLK_FREQ_24MHz 24000000 */
/* #define SYSCLK_FREQ_36MHz 36000000 */
/* #define SYSCLK_FREQ_48MHz 48000000 */
/* #define SYSCLK_FREQ_56MHz 56000000 */
#define SYSCLK_FREQ_72MHz 72000000
#endif
默认选项为 SYSCLK_FREQ_72MHz,执行SetSysClockTo72()
{HSE使能—等待HSE稳定,如果超时则退出—配置FLASH—配置HCLK为系统主频(1分频), PCLK2为系统主频(1分频) ,PCLK1为36MHZ(2分频)—锁相环配置 PLLCLK = HSE * 9 = 72 MHz—使能锁相环—等待锁相环稳定—选择锁相环时钟为系统时钟源—等待锁相环被用于系统时钟源},在调试窗口中查看频率,SYS和APB2域和HCLK为72MHZ,APB1域为36MHZ
2)如果HSE晶体振荡器失效,HSI时钟会被作为备用时钟源?
If HSE fails to start-up, the application will have wrong clock configuration. User can add here some code to deal with this error
在system_stm32f103x.c文件中可以看到上图中的注释,在HSE启用失败后,PLL无法锁定成功。SetSysClockTo72函数中让我们自己添加处理办法,如果没有添加,系统时钟将仍然是SystemInit中配置的HSI的8MHZ。
3)如果我想要配置系统时钟源为HSI_PLL,频率为64MHZ该怎么操作?
/*********************************************************
* @data : 2024/4/15-4/17
* @MCU: STM32F103C8T6
*********************************************************/
#include "stm32f10x.h"
int main()
{ /*初始化RCC*/
RCC_DeInit();
/*使能HSI,此步骤可以省略,在RCC_DeInit()中已经打开了HSI*/
RCC_HSICmd(ENABLE);
/*配置PLL时钟源为HSI的2分频的16倍频*/
RCC_PLLConfig(RCC_PLLSource_HSI_Div2,RCC_PLLMul_16);
/*使能PLL*/
RCC_PLLCmd(ENABLE);
/*等待PLL稳定,就位后相应标志位被置SET*/
/*只有当目标时钟源准备就绪了(经过启动稳定阶段的延迟或PLL稳定),从一个时钟源到另一个时 钟源的
切换才会发生。在被选择时钟源没有就绪时,系统时钟的切换不会发生。直至目标时钟 源就绪,才发生切
换。*/
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET);
/*SW选择系统时钟源为PLL*/
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
/*AHB分频*/
RCC_HCLKConfig(RCC_SYSCLK_Div1);
/*APB12分频*/
RCC_PCLK1Config(RCC_HCLK_Div2);
/*APB21分频*/
RCC_PCLK2Config(RCC_HCLK_Div1);
/*检查目标时钟源是否设置成功*/
while (RCC_GetSYSCLKSource() != 0x08);
/*返回时钟频率,便于在调试窗口查看频率值*/
while(1);
}
在调试窗口中查看,各频率的值均符合预期,系统频率为64MHZ,HCLK分频后的频率为64MHZ,APB1域的频率为32MHZ,APB2域的频率为64MHZ;
使用RCC_DeInit()后的几个值,在参考手册RCC_CFGR寄存器中描述到PCLK,HCLK1,HCLK2的复位值,使用该函数复位后,HSI直接作为系统时钟,PCLK,HCLK1,HCLK2均不分频
在调试窗口中查看使用RCC_DeInit()后各频率的值,前4者的频率均为8MHZ;
4)如果我想要配置HSE_PLL系统时钟频率为48MHZ该怎么操作?
4.1.system_stm32f103x.c文件中修改。如果你的文件上带了一把钥匙,找到文件所在地,右键单击点击属性取消勾选只读;
修改注释即可,如要配置48MHZ修改为如图
在调试窗口中查看,系统频率和APB2域和HCLK为48MHZ,APB1域为24MHZ;
4.2.在主函数中单独配置
/*********************************************************
* @data : 2024/4/15-4/17
* @MCU: STM32F103C8T6
*********************************************************/
#include "stm32f10x.h"
int main()
{
RCC_DeInit();/*将外设 RCC 寄存器重设为缺省值*/
RCC_HSEConfig(RCC_HSE_ON); /*设置外部高速晶振*/
while(RCC_WaitForHSEStartUp() != SUCCESS);/*等待 HSE 起振*/
while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) != SET);/*HSE 晶振就绪*/
RCC_HCLKConfig(RCC_SYSCLK_Div1);/*设置 AHB 时钟*/
RCC_PCLK1Config(RCC_HCLK_Div2);/*设置低速 AHB 时钟*/
RCC_PCLK2Config(RCC_HCLK_Div1);/*设置高速 AHB 时钟*/
RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_6);/*设置 PLL 时钟源及倍频系数*/
RCC_PLLCmd(ENABLE);/*使能PLL*/
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) != SET);/*PLL 就绪*/
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);/*设置系统时钟*/
while(RCC_GetSYSCLKSource() != 0X08);/*检查PLL是否作为系统时钟源*/
//RCC_ClocksTypeDef RCC_Clocksstructure;
//RCC_GetClocksFreq(&RCC_Clocksstructure);
while(1);
}
调试窗口中,系统频率和APB2域和HCLK为48MHZ,APB1域为24MHZ;