stm32學習2:系統時鐘
STM32學習2:系統時鐘介紹與配置
鄙人是在淘寶購置了一套STM32開發板,跟著隨帶的光碟學習起來的。碰到不懂的就在CSDN上瀏覽學習高手的部落格,大神們不僅技術很好還樂於分享,蒙其惠澤,未感忘恩,所以自己開始寫部落格慢慢積累。
如果您是初學者,看到該系列文章後有所幫助,鄙人深感榮幸。如果您是大神,請您指出不足指出。如果沒人看到,權當積累與記錄了。
鄙人使用普中科技公司的開發板,在淘寶可以找到。晶片是STM32F103ZET6,韌體庫是V3.5,編譯環境是Keil uVision4。
轉載請註明完整出處。
1,時鐘簡介
上篇介紹瞭如何建立一個STM32的空模板。搭建好編譯環境後,還需要對stm32晶片本身有一定了解,這樣才可以配置好晶片跑程式。本篇介紹的是STM32的系統時鐘部分,學過數位電路的朋友就知道,時鐘對於電路來說就好比是人體的心臟。詳細的時鐘配置與說明可以參見下面連結中的:《STM32中文參考手冊》
https://download.csdn.net/download/huagengpai1994/10809289
整個時鐘體系可以由下圖來表述:
可以看到圖中有藍色和綠色兩種顏色的方塊。藍色方塊代表時鐘訊號源,綠色訊號代表訊號處理(分頻、倍頻)與輸出。初學只要構建時鐘大體的框架就好。
時鐘訊號源有四個部分(可忽略PLL)分別是:
- HSI RC:高速內部RC振盪時鐘源,8MHZ。H表示高速,S表示源,I表示內部,RC表示是振盪器。內部時鐘源是在晶片(小方塊)裡面的,外部時鐘源是在晶片外部通過PCB佈線連線到晶片裡。
- LSI RC:低速內部RC振盪時鐘源,大約為40KHZ。
- HSE Osc: 高速外部晶體振盪時鐘源,8MHZ。
- LSE Osc:低速外部晶體振盪時鐘源,32.768KHZ。
圖中倆高速的在上面,倆低速的在下面。
PLL也被認為是一個時鐘源,不過它從原理上來看並不提供時鐘源訊號,只是對接受的訊號倍頻後輸出。可以從圖中看到PLL的時鐘路徑有兩條:HSI RC 2分頻、HSE Osc 直接到達、HSE Osc 2分頻到達。
同樣的,可以看看下方的RTC時鐘,它的時鐘源也有三條:HSE Osc 128分頻到,LSE Osc 直接到達、LSI RC 直接到達。
LSI RC還直接供給看門狗獨立時鐘。
接著看上面的部分,SYSCLK系統時鐘源有三條路徑:HSI RC直接到達,PLL到達,HSE Osc 直接到達。CSS如圖中的解釋,是一個時鐘監視,如果HSE失效則自動切換到SYSCLK=HSI。
SYSCLK系統時鐘的頻率最高為72MHZ,經過AHB分頻後供給AHB1和AHB2。APB1和APB2還要繼續分頻才能供給外設與計時器,其中APB1是低速的,最高為36MHZ;APB2為高速的,最高為72MHZ。
中間部分的MCO是將經過晶片的時鐘輸出出去,輸出源如圖中所示有四個:SYSCLK、HSI、HSE和PLLCLK2分頻。
總結一下:系統時鐘SYSCLK是最核心的部分,圖示左上部分無論怎麼走都是為了到達系統時鐘,然後調配到APB1和APB2為外設輸出時鐘。
經過時鐘源的選擇、分頻/倍頻,就可以到HCLK(高效能匯流排AHB用)、FCLK(供給cpu核心的用,常說的cpu主頻)、PCLK(高效能外設匯流排APB)、USBCLK、TIMXCLK、TIM1CLK、RTCCLK等,外設是掛載STM32的總線上的,具體哪個外設掛載哪個匯流排,看下圖:
2,時鐘配置
在程式設計中,我們要做的也無非是設定閘電路以選擇時鐘源輸入、倍頻/分頻係數和開啟/關閉對應外設所在匯流排的時鐘。這些設定是通過暫存器進行設定的,但是直接設定暫存器會有點較複雜,所以可以用SystemInit()庫函式直接進行設定。庫函式的設定方法如下所示:
const uint32_t SystemFrequency = SYSCLK_FREQ_72MHz;
const uint32_t SystemFrequency_SysClk =SYSCLK_FREQ_72MHz;
const uint32_t SystemFrequency_AHBClk = SYSCLK_FREQ_72MHz;
const uint32_t SystemFrequency_APB1Clk = (SYSCLK_FREQ_72MHz/2);
const uint32_t SystemFrequency_APB2Clk = SYSCLK_FREQ_72MHz;
這就是在定義了CPU跑72M的時候,各個系統的速度.他們分別是:硬體頻率,系統時鐘,AHB匯流排頻率,APB1匯流排頻率,APB2匯流排頻率.
如果需要更加靈活的配置,可以呼叫這個函式:
void RCC_HSE_Configuration(void) //HSE作為PLL時鐘,PLL作為SYSCLK
{
RCC_DeInit(); /*將外設RCC暫存器重設為預設值 */
RCC_HSEConfig(RCC_HSE_ON);/*設定外部高速晶振(HSE) HSE晶振開啟(ON)*/
if(RCC_WaitForHSEStartUp() == SUCCESS) /*等待HSE起振, SUCCESS:HSE晶振穩定且就緒*/
{
RCC_HCLKConfig(RCC_SYSCLK_Div1);/*設定AHB時鐘(HCLK)RCC_SYSCLK_Div1——AHB時鐘 = 系統時鐘*/
RCC_PCLK2Config(RCC_HCLK_Div1); /*設定高速AHB時鐘(PCLK2)RCC_HCLK_Div1——APB2時鐘 = HCLK*/
RCC_PCLK1Config(RCC_HCLK_Div2); /*設定低速AHB時鐘(PCLK1)RCC_HCLK_Div2——APB1時鐘 = HCLK / 2*/
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);/*設定PLL時鐘源及倍頻係數*/
RCC_PLLCmd(ENABLE); /*使能PLL */
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) ;/*檢查指定的RCC標誌位(PLL準備好標誌)設定與否*/
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); /*設定系統時鐘(SYSCLK) */
while(RCC_GetSYSCLKSource() != 0x08); /*0x08:PLL作為系統時鐘 */
}
}
如果使用void RCC_HSE_Configuration(void),可以將其作為一個.C檔案獨立編寫,然後再主函式直接呼叫。