STM32系统时钟默认设置
“我們一直都說STM32有一個非常復雜的時鐘系統,然而在原子或者野火的例程中,只要涉及到時鐘,我們卻只能看到類似的庫函數調用,如RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);這個僅僅只是起到開啟掛載在APB2線上的USART1時鐘的作用罷了,APB2的時鐘頻率是多少我們并不知道”
我們先來了解一些stm32的時鐘結構。- 1
- 2
,
這個圖說明了STM32的時鐘走向,從圖的左邊開始,從時鐘源一步步分配到外設時鐘。?
從時鐘頻率來說,又分為高速時鐘和低速時鐘,高速時鐘是提供給芯片主體的主時鐘,而低速時鐘只是提供給芯片中的RTC(實時時鐘)及獨立看門狗使用。
從芯片角度來說,時鐘源分為內部時鐘與外部時鐘源 ,內部時鐘是在芯片內部RC振蕩器產生的,起振較快,所以時鐘在芯片剛上電的時候,默認使用內部高速時鐘。而外部時鐘信號是由外部的晶振輸入的,在精度和穩定性上都有很大優勢,所以上電之后我們再通過軟件配置,轉而采用外部時鐘信號。
所以,STM32有以下4個時鐘源:?
高速外部時鐘(HSE):以外部晶振作時鐘源,晶振頻率可取范圍為4~16MHz,我們一般采用8MHz的晶振。?
高速內部時鐘(HSI): 由內部RC振蕩器產生,頻率為8MHz,但不穩定。?
低速外部時鐘(LSE):以外部晶振作時鐘源,主要提供給實時時鐘模塊,所以一般采用32.768KHz。?
低速內部時鐘(LSI):由內部RC振蕩器產生,也主要提供給實時時鐘模塊,頻率大約為40KHz。
時鐘頻率當然是可以通過代碼來配置的,然而main函數中我們卻沒看到配置時鐘的相關代碼。這說明了我們一直用的是默認的設置,也就是說,在進入main函數之前時鐘頻率就已經被設置好了。這時候,大家應該都已經想到了,就是stm32的啟動文件,startup_stm32f10x_hd.s。于是我們打開這個文件,會發現有這么一塊用匯編寫的代碼。
Reset_Handler PROCEXPORT Reset_Handler [WEAK]IMPORT __mainIMPORT SystemInitLDR R0, =SystemInitBLX R0 LDR R0, =__mainBX R0ENDP- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
從這里我們可以看到,我們的程序在進入到main函數之前,先要執行systeminit,跳轉到這個函數的定義。里面的代碼是對寄存器直接進行操作了,我查找了用戶手冊,寄存器的相關配置說明寫在了注釋里面(IDE里面文字設置為ANSI格式了,直接復制過來會出現亂碼,大家將就下看看圖片吧)
這里涉及到了兩個寄存器RCC_CR,與RCC_CFGR,分別是時鐘控制寄存器與時鐘配置寄存器,它們的作用顧名思義,就是起到了控制和配置時鐘的作用。想具體了解寄存器每一位的功能,請查閱用戶手冊。?
這段代碼實現了時鐘的初始化,也就是所謂的默認設置了。?
執行完后,我們繼續往下走
- 1
- 2
- 3
我們可以看到,這里還有一個函數,看它的命名,顯然就是對時鐘進行設置的函數。?
我們看一下它的實現過程。
因為我們并沒有這些宏定義,所以相當于執行了一個nop函數。顯然,在這個程序中,這個函數并沒有起到改變時鐘配置的作用,我們用的還是初始化的默認配置。?
到這里,關于stm32系統時鐘的默認設置就已經結束了。?
對照著時鐘樹,我們結合代碼來回顧一下。
首先從左端的OSC_OUT和OSC_IN開始,假設我們外接的是8MHz的晶振,兩個引腳分別接到外部晶振的兩端。
8MHz的時鐘遇到了第一個分頻器PLLXTPRE(HSE divider for PLL entry),在這個分頻器中,可以通過寄存器配置,選擇它的輸出。它的輸出時鐘可以是對輸入時鐘的二分頻或不分頻。本例子中,我們選擇不分頻,所以經過PLLXTPRE后,還是了8MHz的時鐘。
8MHz的時鐘遇到開關PLLSRC(PLL entry clock source),我們可以選擇其輸出,輸出為外部高速時鐘(HSE)或是內部高速時鐘(HSI)。這里選擇輸出為HSI(HSE經二分頻后變成了4MHz的時鐘),接著遇到鎖相環PLL,具有倍頻作用,在這里我們可以輸入倍頻因子PLLMUL(PLL multiplication factor),經過PLL的時鐘稱為PLLCLK。倍頻因子我們設定為2倍頻,也就是說,經過PLL之后,我們的時鐘從原來4MHz的 HSE變為8MHz的PLLCLK。
緊接著又遇到了一個開關SW,經過這個開關之后就是STM32的系統時鐘(SYSCLK)了。通過這個開關,可以切換SYSCLK的時鐘源,可以選擇為HSI、PLLCLK、HSE。我們選擇為HSI時鐘,所以SYSCLK就為8MHz了。
PLLCLK在輸入到SW前,還流向了USB預分頻器,這個分頻器輸出為USB外設的時鐘(USBCLK),在本例子中我們的USB預分頻系數為1.5,此時USBCLK為5.33MHz。
回到SYSCLK,SYSCLK經過AHB預分頻器,分頻后再輸入到其它外設。如輸出到稱為HCLK、FCLK的時鐘,還直接輸出到SDIO外設的SDIOCLK時鐘、存儲器控制器FSMC的FSMCCLK時鐘,和作為APB1、APB2的預分頻器的輸入端。本例子設置AHB預分頻器不分頻,即輸出的頻率為8MHz。
GPIO外設是掛載在APB2總線上的, APB2的時鐘是APB2預分頻器的輸出,而APB2預分頻器的時鐘來源是AHB預分頻器。因此,把APB2預分頻器設置為不分頻,那么我們就可以得到GPIO外設的時鐘也等于HCLK,為8MHz了。
APB2的時鐘為8MHz,ADC預分頻系數為2,所以,ADCCLK為4MHz。
STM32的時鐘系統確實是很復雜,不僅有倍頻,分頻,還有一系列的外設時鐘開關。倍頻是考慮到了電磁兼容性,如果外部直接提供一個72MHz的晶振,太高的震蕩頻率會給電路板的制作帶來一定的難度。分頻則是因為STM32既有高速外設,也有低速外設,各外設的工作頻率不相同,需要分開來管理。最后,每個外設時鐘還有自己獨立的開關(在圖上可以看到,在外設時鐘之前需要經過一個與門,這就是它們的開關)在我們不使用該外設時,需要把時鐘關閉以減少STM32的功耗。
總結
以上是生活随笔為你收集整理的STM32系统时钟默认设置的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: STM32初识——中断初始化过程(by
- 下一篇: stm32外设初始化和设置过程