1. 程式人生 > >STM32的時鐘樹解析

STM32的時鐘樹解析

STM32時鐘樹         對於廣大初次接觸STM32的讀者朋友(甚至是初次接觸ARM器件的讀者朋友)來說,在熟悉了開發環境的使用之後,往往“栽倒”在同一個問題上。這問題有個關鍵字叫:時鐘樹。         眾所周知,微控制器(處理器)的執行必須要依賴週期性的時鐘脈衝來驅動——往往由一個外部晶體振盪器提供時鐘輸入為始,最終轉換為多個外部裝置的週期性運作為末,這種時鐘“能量”擴散流動的路徑,猶如大樹的養分通過主幹流向各個分支,因此常稱之為“時鐘樹”。在一些傳統的低端8位微控制器諸如51,AVR,PIC等微控制器,其也具備自身的一個時鐘樹系統,但其中的絕大部分是不受使用者控制的,亦即在微控制器上電後,時鐘樹就固定在某種不可更改的狀態(假設微控制器處於正常工作的狀態)。比如
51微控制器
使用典型的12MHz晶振作為時鐘源,則外設如IO口、定時器、串列埠等裝置的驅動時鐘速率便已經是固定的,使用者無法將此時鐘速率更改,除非更換晶振。         而STM32微控制器的時鐘樹則是可配置的,其時鐘輸入源與最終達到外設處的時鐘速率不再有固定的關係,本文將來詳細解析STM32微控制器的時鐘樹。圖1是STM32微控制器的時鐘樹,表1是圖中各個標號所表示的部件。標號            圖1標號釋義1       內部低速振盪器(LSI,40Khz)2       外部低速振盪器(LSE,32.768Khz)3     外部高速振盪器(HSE,3-25MHz)4     內部高速振盪器(HIS,8MHz)5      PLL輸入選擇位6      RTC時鐘選擇位7     PLL1分頻數暫存器8     PLL1倍頻暫存器9     系統時鐘選擇位10             USB分頻暫存器11             AHB分頻暫存器12             APB1分頻暫存器13             AHB
匯流排
14             APB1外設匯流排15             APB2分頻暫存器16       APB2外設匯流排17             ADC預分頻暫存器18             ADC外設19             PLL2分頻數暫存器20             PLL2倍頻暫存器21             PLL時鐘源選擇暫存器22             獨立看門狗裝置23         RTC裝置 圖1  STM32的時鐘樹         在認識這顆時鐘樹之前,首先要明確“主幹”和最終的“分支”。假設使用外部8MHz晶振作為STM32的時鐘輸入源(這也是最常見的一種做法),則這個8MHz便是“主幹”,而“分支”很顯然是最終的外部裝置比如通用輸入輸出裝置(GPIO)。這樣可以輕易找出第一條時鐘的“脈絡”:3——5——7——21——8——9——11——13對此條時鐘路徑做如下解析:對於3,首先是外部的3-25MHz(前文已假設為8MHz)輸入;對於5,通過PLL選擇位預先選擇後續PLL分支的輸入時鐘(假設選擇外部晶振);對於7,設定外部晶振的分頻數(假設1分頻);對於21,選擇PLL倍頻的時鐘源(假設選擇經過分頻後的外部晶振時鐘);對於8,設定PLL倍頻數(假設9倍頻);對於9,選擇系統時鐘源(假設選擇經過PLL倍頻所輸出的時鐘);對於11,設定AHB匯流排分頻數(假設1分頻);對於13,時鐘到達AHB匯流排;在上一章節中所介紹的GPIO外設屬於APB2裝置,即GPIO的時鐘來源於APB2匯流排,同樣在圖1中也可以尋獲GPIO外設的時鐘軌跡:3——5——7——21——8——9——11——15——16對於3,首先是外部的3-25MHz(前文已假設為8MHz)輸入;對於5, 通過PLL選擇位預先選擇後續PLL分支的輸入時鐘(假設選擇外部晶振);對於7,設定外部晶振的分頻數(假設1分頻);對於21,選擇PLL倍頻的時鐘源(假設選擇經過分頻後的外部晶振時鐘);對於8,設定PLL倍頻數(假設9倍頻);對於9,選擇系統時鐘源(假設選擇經過PLL倍頻所輸出的時鐘);對於11,設定AHB匯流排分頻數(假設1分頻);對於15,設定APB2匯流排分頻數(假設1分頻);對於16,時鐘到達APB2匯流排;現在來計算一下GPIO裝置的最大驅動時鐘速率(各個條件已在上述要點中假設):1)   由3所知晶振輸入為8MHz,由5——21知PLL的時鐘源為經過分頻後的外部晶振時鐘,並且此分頻數為1分頻,因此首先得出PLL的時鐘源為:8MHz / 1 = 8MHz。2)   由8、9知PLL倍頻數為9,且將PLL倍頻後的時鐘輸出選擇為系統時鐘,則得出系統時鐘為 8MHz * 9 = 72MHz。3)   時鐘到達AHB預
分頻器
,由11知時鐘經過AHB預分頻器之後的速率仍為72MHz。4)   時鐘到達APB2預分頻器,由15經過APB2預分頻器後速率仍為72MHz。5)   時鐘到達APB2匯流排外設。因此STM32的APB2匯流排外設,所能達到的最大速率為72MHz。依據以上方法讀者可以搜尋出APB1匯流排外設時鐘、RTC外設時鐘、獨立看門狗等外設時鐘的來龍去脈。接下來從程式的角度分析時鐘樹的設定,程式清單如下:void RCC_Configuration(void){        ErrorStatus HSEStartUpStatus;                                                                                                     (1)        RCC_DeInit();                                                                                                                                     (2)        RCC_HSEConfig(RCC_HSE_ON);                                                                                                   (3)        HSEStartUpStatus = RCC_WaitForHSEStartUp();                                                                     (4)        if(HSEStartUpStatus == SUCCESS)                                                                                                (5)        {                   RCC_HCLKConfig(RCC_SYSCLK_Div1);                                                                              (6)                     RCC_PCLK2Config(RCC_HCLK_Div1);                                                                               (7)                     RCC_PCLK1Config(RCC_HCLK_Div2);                                                                                (8)                    FLASH_SetLatency(FLASH_Latency_2);                                                                             (9)                    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);                                      (10)                  RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);                                         (11)                  RCC_PLLCmd(ENABLE);                                                                                                              (12)                  while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);                                                       (13)                  RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);                                                               (14)                  while(RCC_GetSYSCLKSource() != 0x08);                                                                               (15)        }}以上是ST官方所提供的STM32時鐘樹配置函式,讀者首先要知道3點1、ST所提供的庫函式在函式和變數命名上有非常良好的規範性和易讀性(雖然有點冗長),即便沒有註釋,也可從函式名和變數名來大致判斷該函式或變數所包含的意義。2、其次,讀者應從上圖區分出各個匯流排和對應的時鐘:其中PLLCLK表示PLL鎖相環的輸出時鐘,SYSCLK表示系統時鐘,HCLK表示AHB匯流排的時鐘,PCLK1表示APB1匯流排的時鐘,PCLK2則表示APB2匯流排的時鐘。3、9、10兩句程式碼的作用是設定STM32內部FLASH的等待週期。做如下解釋:STM32的內部使用者FLASH用以儲存程式碼指令供CPU存取以執行,STM32的CPU的最大速率已知為72MHz,但FLASH無法達到這麼高的速度,因此要在CPU存取FLASH的過程中插入所謂的“等待週期”,顯然CPU速度越快,所要插入的等待週期個數越多,原則是        1)當CPU速率為0 ~ 24MHz時,不需要插入等待週期,即等到週期個數為0;        2)當CPU速率為24 ~ 48MHz時,插入1個等待週期;        3)當CPU速率為48MHz ~ 72MHz時,插入2個等待週期;有以上三點準備之後,開始解析這段程式:(1)定義一個ErrorStatus型別的變數HSEStartUpStatus;(2)將時鐘樹復位至預設設定;(3)開啟HSE晶振;(4)等待HSE晶振起振穩定,並將起振結果儲存至HSEStartUpStatus變數中;(5)判斷HSE晶振是否起振成功(假設成功了,進入if內部);(6)設定HCLK時鐘為SYSCLK的1分頻;(7)設定PLCK2時鐘為SYSCLK的1分頻;(8)設定PLCK1時鐘為SYSCLK的2分頻;(11)選擇PLL輸入源為HSE時鐘經過1分頻,並進行9倍頻;(12)使能PLL輸出;(13)等待PLL輸出穩定;(14)選擇系統時鐘源為PLL輸出;(15)等待系統時鐘穩定;上述程式碼中對時鐘樹的配置順序為(對應圖中標號):3——11——14——15——7——21——8——9通過對比發現,程式中對時鐘樹的配置順序並不是依次從圖中由左到右、由上到下配置的,這是為什麼呢?事實上這個問題相信大部分讀者都可以自己解釋:電子設計世界的思維和操作方式,其順序往往和日常生活是不一樣的,比如人們經常先給電視機連線電源,再開啟電視機開關;先把大水管的總閘開啟,再開啟小水龍頭;總而言之是一種由“主”到“次”的順序。轉移到最常見的51微控制器的開發平臺,開發人員往往先把定時器的分頻數,過載值等引數配置好,最後才啟動定時器計數;先把各個外設的中斷開啟,最後再開啟總中斷;這和人們的生活習慣其實恰好相反,是一種先“次”後“主”的順序。         至此,理解STM32的時鐘樹就是輕而易舉的事情了。