前言
本系列文章統(tǒng)一圍繞STM32F103C8T6最小系統(tǒng)開(kāi)發(fā)板進(jìn)行記錄,如涉及其他開(kāi)發(fā)板將會(huì)特別說(shuō)明。
STM32時(shí)鐘的概念
時(shí)鐘對(duì)于STM32而言是驅(qū)動(dòng)源,相當(dāng)于人類的心臟。有了時(shí)鐘,STM32才能運(yùn)行,并給片上的所有外設(shè)模塊提供時(shí)鐘使其正常工作。
STM32中系統(tǒng)時(shí)鐘為什么有這么多的時(shí)鐘源?
- 提供STM32系統(tǒng)內(nèi)核、各種總線和外設(shè)所需要的工作頻率。
- 增加抗電磁干擾能力,提高穩(wěn)定性。
- 考慮掉電情況(外部高/低速時(shí)鐘無(wú)法正常供電時(shí),內(nèi)部高/低速時(shí)鐘可以提供時(shí)鐘源)。
時(shí)鐘源
以stm32f1系列為例:
-
外部高速時(shí)鐘(HSE)
- 來(lái)源:可接石英 / 陶瓷諧振器,或者接外部時(shí)鐘源。
- 頻率范圍是 4MHz – 16MHz。
- 可以直接作為系統(tǒng)時(shí)鐘或PLL輸入。
-
內(nèi)部高速時(shí)鐘(HSI)
- 來(lái)源:內(nèi)部RC振蕩器。
- 頻率為8MHz(用此時(shí)鐘源,系統(tǒng)時(shí)鐘SYSCLK的最大頻率不超過(guò)64MHz,8/2*16 = 64MHz)。
- 可以直接作為系統(tǒng)時(shí)鐘或PLL輸入。
-
外部低速時(shí)鐘(LSE)
- 來(lái)源:外接石英晶體。
- 頻率為 32.768KHz。
- 主要是RTC的時(shí)鐘源。
-
內(nèi)部低速時(shí)鐘(LSI)
- 來(lái)源:內(nèi)部RC 振蕩器。
- 頻率為 40KHz左右(30K-60KHz)。
- 供獨(dú)立看門狗和自動(dòng)喚醒單元使用。
-
鎖相環(huán)時(shí)鐘(PLL):鎖相環(huán)倍頻輸出,可作為系統(tǒng)的時(shí)鐘源,嚴(yán)格的來(lái)說(shuō)并不算一個(gè)獨(dú)立的時(shí)鐘源。
- 來(lái)源:HSI/2 、 HSE 或者 HSE/2 。
- PLL倍頻因子:2 – 16 倍。
- 輸出頻率最大不得超過(guò) 72MHz。
-
系統(tǒng)時(shí)鐘源(SYSTICK):
- 最大頻率為72MHz。
- 來(lái)源:PLL倍頻輸出、HSI或者HSE。
- 輸出:AHB分頻器。

-
AHB總線時(shí)鐘(HCLK):將系統(tǒng)時(shí)鐘頻率進(jìn)行分頻并提供給各模塊使用。
- 分頻因子:1、2、4、8、16、64、128、256、512。
- 主要輸出:
- AHB總線、內(nèi)核、內(nèi)存和DMA使用的HCLK時(shí)鐘。
- 通過(guò)8分頻后送給Cortex的系統(tǒng)定時(shí)器時(shí)鐘。
- Cortex的自由運(yùn)行時(shí)鐘FCLK。
- APB1預(yù)分頻器。
- APB2預(yù)分頻器 。
-
APB1總線時(shí)鐘(PCLK1):低速總線時(shí)鐘,最大為36MHz。
- 來(lái)源:由AHB分頻而得。
- 分頻因子:1、2、4、8、16。
- 輸出:APB1外設(shè)、通用定時(shí)器2~7。
-
APB2總線時(shí)鐘(PCLK2):高速總線時(shí)鐘,最大為72MHz。
- 來(lái)源:由AHB分頻而得。
- 分頻因子:1、2、4、8、16。
- 輸出:APB2外設(shè)、高級(jí)定時(shí)器1和定時(shí)器8。

RCC寄存器
-
RCC_CR 時(shí)鐘控制寄存器
- 內(nèi)外部高速時(shí)鐘的使能和就緒標(biāo)志(含內(nèi)部高速時(shí)鐘校準(zhǔn)調(diào)整)。
- 外部高速時(shí)鐘旁路。
- 時(shí)鐘安全系統(tǒng)CSS使能。
- PLL使能和PLL就緒標(biāo)志。
-
RCC_CFGR 時(shí)鐘配置寄存器
- 系統(tǒng)時(shí)鐘源切換及狀態(tài)。
- AHB、APB1、APB2、ADC、USB預(yù)分頻選擇。
- PLL輸入時(shí)鐘源選擇及HSE輸入PLL分頻選擇,PLL倍頻系數(shù)選擇。
- MCO(PA8)引腳微控制器時(shí)鐘輸出。
-
RCC_APBxRSTR 外設(shè)復(fù)位寄存器
- LSI、LSE、HIS、HSE、PLL就緒中斷標(biāo)志。
- HSE時(shí)鐘失效導(dǎo)致時(shí)鐘安全系統(tǒng)中斷標(biāo)志。
- LSI、LSE、HIS、HSE、PLL就緒中斷使能。
- 清除LSI、LSE、HIS、HSE、PLL就緒中斷。
- 清除時(shí)鐘安全系統(tǒng)中斷。
-
RCC_AHBENR/APBxENR外設(shè)時(shí)鐘使能寄存器
- 主要功能:使能AHB、APB1、APB2總線下的各外設(shè)
-
RCC_APBxRSTR 外設(shè)復(fù)位寄存器
- 主要功能:APB1、APB2總線下的各外設(shè)復(fù)位
系統(tǒng)時(shí)鐘的配置
以stm32f1系列為例:官方提供的啟動(dòng)文件startup_stm32f10x_hd.s中,在執(zhí)行main函數(shù)前會(huì)調(diào)用system_stm32f10x.c文件下的SystemInit函數(shù)對(duì)系統(tǒng)時(shí)鐘進(jìn)行配置。
在SystemInit函數(shù)下的SetSysClock函數(shù),會(huì)對(duì)系統(tǒng)時(shí)鐘頻率、HCLK、PCLK等進(jìn)行具體配置。
/**
* @brief Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers.
* @param None
* @retval None
*/
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
設(shè)置系統(tǒng)時(shí)鐘頻率為72MHz的基本流程:
- 使能HSE時(shí)鐘并等待完成。
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
- 設(shè)置HCLK、PCLK1、PCLK2頻率。
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
- 使能PLL鎖相環(huán)時(shí)鐘并設(shè)置倍頻因子為9(9*8MHz = 72MHz),使能并選擇其為系統(tǒng)的時(shí)鐘源。
/* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{
}
至此,成功將系統(tǒng)時(shí)鐘頻率設(shè)置為72MHz,其中PCLK1為36MHz,PCLK2為72MHz。