內部時鐘
外部時鐘
鎖相環倍頻輸出時鐘

1.1 詳細介紹
HSI(內部高速時鐘)
它是RC振蕩器,頻率可以達到8MHZ,可作為系統時鐘和PLL鎖相環的輸入。
HSE(外部高速時鐘)
接入晶振范圍是4-16MHZ,可作為系統時鐘和PLL鎖相環的輸入,還可以經過128分頻之后輸入給RTC。
LSI(內部低速時鐘)
它是RC振蕩器,頻率大概為40KHZ,供給獨立看門狗或者RTC,并且獨立看門口只能依靠LSI作為時鐘源。
LSE(外部低速時鐘)
通常外接32.768MHZ晶振提供給RTC。
PLL(鎖相環)
用來倍頻輸出。因為開發板外部晶振只有8MHZ,而STM32最大工作頻率是72MHZ。他可以通過HSI輸入,HSE輸入或兩分頻輸入,通過PLL倍頻(2-16),倍頻之后輸入給系統時鐘。
MCO(時鐘輸出管腳)
通常對應STM32 PA8,它可以選擇一個時鐘信號輸出,給外部的系統提供時鐘源。
2. 標準庫的時鐘配置
2.1 stm32啟動文件
首先打開startup_stm32f10x_hd.s,該文件為stm32的啟動文件,在該文件內會發現有這么一塊用匯編寫的代碼。
?
??????Reset_Handler???PROC ????????????EXPORT??Reset_Handler????[WEAK] ????????????IMPORT??__main ????????????IMPORT??SystemInit ????????????LDR?????R0,?=SystemInit ????????????BLX?????R0??????????????? ????????????LDR?????R0,?=__main ????????????BX??????R0 ????????????ENDP
?
通過這段匯編代碼可以看出,程序在執行main函數之前,會先執行SystemInit函數。
2.2 SystemInit函數詳解
?
void?SystemInit?(void)
{
??/*?Reset?the?RCC?clock?configuration?to?the?default?reset?state(for?debug?purpose)?*/
??/*?Set?HSION?bit?*/
??RCC->CR?|=?(uint32_t)0x00000001;
??/*?Reset?SW,?HPRE,?PPRE1,?PPRE2,?ADCPRE?and?MCO?bits?*/
#ifndef?STM32F10X_CL
??RCC->CFGR?&=?(uint32_t)0xF8FF0000;
#else
??RCC->CFGR?&=?(uint32_t)0xF0FF0000;
#endif?/*?STM32F10X_CL?*/???
??/*?Reset?HSEON,?CSSON?and?PLLON?bits?*/
??RCC->CR?&=?(uint32_t)0xFEF6FFFF;
??/*?Reset?HSEBYP?bit?*/
??RCC->CR?&=?(uint32_t)0xFFFBFFFF;
??/*?Reset?PLLSRC,?PLLXTPRE,?PLLMUL?and?USBPRE/OTGFSPRE?bits?*/
??RCC->CFGR?&=?(uint32_t)0xFF80FFFF;
#ifdef?STM32F10X_CL
??/*?Reset?PLL2ON?and?PLL3ON?bits?*/
??RCC->CR?&=?(uint32_t)0xEBFFFFFF;
??/*?Disable?all?interrupts?and?clear?pending?bits??*/
??RCC->CIR?=?0x00FF0000;
??/*?Reset?CFGR2?register?*/
??RCC->CFGR2?=?0x00000000;
#elif?defined?(STM32F10X_LD_VL)?||?defined?(STM32F10X_MD_VL)?||?(defined?STM32F10X_HD_VL)
??/*?Disable?all?interrupts?and?clear?pending?bits??*/
??RCC->CIR?=?0x009F0000;
??/*?Reset?CFGR2?register?*/
??RCC->CFGR2?=?0x00000000;??????
#else
??/*?Disable?all?interrupts?and?clear?pending?bits??*/
??RCC->CIR?=?0x009F0000;
#endif?/*?STM32F10X_CL?*/
#if?defined?(STM32F10X_HD)?||?(defined?STM32F10X_XL)?||?(defined?STM32F10X_HD_VL)
??#ifdef?DATA_IN_ExtSRAM
????SystemInit_ExtMemCtl();?
??#endif?/*?DATA_IN_ExtSRAM?*/
#endif?
??/*?Configure?the?System?clock?frequency,?HCLK,?PCLK2?and?PCLK1?prescalers?*/
??/*?Configure?the?Flash?Latency?cycles?and?enable?prefetch?buffer?*/
??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?
}
?
打開內部8M時鐘
?
RCC->CR?|=?(uint32_t)0x00000001
?
通過查看寄存器手冊可知,這段代碼為打開內部8M時鐘。

設置時鐘配置寄存器
?
#ifndef?STM32F10X_CL ??RCC->CFGR?&=?(uint32_t)0xF8FF0000; #else ??RCC->CFGR?&=?(uint32_t)0xF0FF0000; #endif?/*?STM32F10X_CL?*/???
?
對應寄存器說明可查看《STM32中文參考手冊_V10》的6.3.2 時鐘配置寄存器(RCC_CFGR)章節。
后續代碼,有興趣可根據《STM32中文參考手冊_V10》手冊,查看代碼具體作用。
2.3 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
}
?
system_stm32f10x.c文件中會根據芯片的型號定義對應的宏
?
#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
?
3. 時鐘配置函數
3.1 時鐘初始化配置函數
?
void?SystemInit(void); SYSCLK(系統時鐘)=72MHZ; AHB總線時鐘(HCLK=SYSCLK)=72MHZ; APB1總線時鐘(PCLK1=SYSCLK/2)=36MHZ; APB2總線時鐘(PCLK1=SYSCLK/1)=72MHZ; PLL主時鐘=72MHZ;
?
3.2 外設時鐘使能配置函數
?
void?RCC_AHBPeriphClockCmd(uint32_t?RCC_AHBPeriph,?FunctionalState?NewState); void?RCC_APB2PeriphClockCmd(uint32_t?RCC_APB2Periph,?FunctionalState?NewState); void?RCC_APB1PeriphClockCmd(uint32_t?RCC_APB1Periph,?FunctionalState?NewState);
?
3.3 時鐘源使能函數
?
void?RCC_HSICmd(FunctionalState?NewState); void?RCC_LSICmd(FunctionalState?NewState); void?RCC_PLLCmd(FunctionalState?NewState); void?RCC_RTCCLKCmd(FunctionalState?NewState);
?
3.4 時鐘源和倍頻因子配置函數
?
void?RCC_HSEConfig(uint32_t?RCC_HSE); void?RCC_SYSCLKConfig(uint32_t?RCC_SYSCLKSource); void?RCC_HCLKConfig(uint32_t?RCC_SYSCLK); void?RCC_PCLK1Config(uint32_t?RCC_HCLK); void?RCC_PCLK2Config(uint32_t?RCC_HCLK);
?
3.5 外設時鐘復位函數
?
void?RCC_APB2PeriphResetCmd(uint32_t?RCC_APB2Periph,?FunctionalState?NewState); void?RCC_APB1PeriphResetCmd(uint32_t?RCC_APB1Periph,?FunctionalState?NewState);
?
3.6 自定義系統時鐘
?
void?RCC_HSE_Config(u32?div,u32?pllm)
{
????RCC_DeInit();
????RCC_HSEConfig(RCC_HSE_ON);
????if(RCC_WaitForHSEStartUp()==SUCCESS)
????{???
????????RCC_HCLKConfig(RCC_SYSCLK_Div1);
????????RCC_PCLK1Config(RCC_HCLK_Div2);
????????RCC_PCLK2Config(RCC_HCLK_Div1);
????????RCC_PLLConfig(div,pllm);
????????RCC_PLLCmd(ENABLE);?????
????while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)
????????RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK)
????while(RCC_GetSCLKSource()!=0x08);
????}
}
?
審核編輯:湯梓紅
電子發燒友App






















評論