STM32开发笔记48:STM32F4+DP83848以太网通信指南系列(二):系统时钟
本章為系列指南第二章,主要是介紹一下STM32F4的時鐘配置。時鐘是一個嵌入式產品從零開始開發的基石,一切邏輯都在時鐘的節奏中安靜地彈奏著,時鐘為整個電路帶來了歡快的「心跳」。開發者如果對時鐘沒有控制能力,就會把脈不準整個旋律的節奏,從而導致諸如通信波特率、通信時序、延時操作等關鍵功能全都紊亂,系統的構建也就無從談起。
時鐘如此重要,那么普通開發者,需要對時鐘有多深的認知呢?STM32F4的時鐘配置到底復不復雜?幾行代碼能搞定?
不要著急,我下面將用最簡單的白話文來剖析STM32的時鐘系統。不過在這之前,我們應該先吃一顆定心丸,因為在STM32中配置時鐘是非常簡單的,簡單到我們甚至不需要寫一行代碼就能配置好,因為從標準庫3.5版本以后,SystemInit()這一重要函數,已經默認幫你在上電后執行了,都不需要你手動調用就幫你配置好時鐘了。
一切根據原理圖
剛才提到,SystemInit()這一配置系統時鐘的重要函數,不需要我們手動調用,STM32會幫我們上電后,嵌入到main函數開頭部分自動執行,將我們的系統時鐘配置到168MHz。那為什么我們還要來學習配置時鐘呢?
因為不同的原理圖使用的器件,引腳接法不一樣,所以如果我們直接使用默認的SystemInit()函數,可能并不能按照我們預期的頻率配置系統時鐘,這時候就需要我們對STM32的時鐘概念做一個了解,然后根據我們實際使用的電路原理圖來修改系統默認的SystemInit()函數,從而達到一切可控,一切按預期的配置。
下圖是我手上這塊開發板的原理圖局部特寫,特寫位置為23、24引腳:
圖中,標明23、24腳為OSC_IN,OSC_OUT,OSC是oscillation的縮寫,中文是「振蕩器」的意思,表示這兩個引腳接外部晶振。閑來無事,我們去ST官網下載編號為DS8626的STM32F40x的datasheet求證一下看看。
可以看到,我們的原理圖上,外部晶振使用的是8MHz的,問題來了,STM32官方默認的外部晶振是25MHz的,也就是說,如果我們完全不改配置文件,系統默認調用了SystemInit()函數,直接就會導致系統的「心律失常」。
時鐘樹
關于時鐘樹,我個人認為對于新手來說有些復雜了,但幾乎用不到其中的很多功能,這里我就懶得貼出完整的時鐘樹圖片了,我們只需要了解下面幾個知識點:
每個芯片都有一個自己的最大頻率,這是一個芯片的固有屬性,這個最大頻率代表著這顆芯片處理能力的速度上限,比如STM32F407一般是168MHz。我們可以通過不同的方案配制出這個最大頻率(沒有人愿意自己的芯片降頻使用吧)。最最最常用的方式就是使用外部晶振提供一個基礎的頻率,然后在這個頻率上進行加工,最終得到一個168MHz的時鐘出來。給系統提供基礎頻率的外部晶振,一般是MHz級別的,我們稱之為高速外部晶振(HSE),這里我們開發板上配置的是一顆8MHz的晶振。此外如果系統需要用到RTC時鐘,還需要一個低速外部晶振(LSE),一般是額定頻率32.768KHz,這是后話,此處不表。從8MHz的HSE提高變成168MHz最大頻率的過程,我們叫做「倍頻」,相反從一個高速頻率降成低速頻率的過程,稱之為「分頻」。STM32F4內部通過鎖相環進行倍頻,其原理我沒高興去了解,我們知道有一種叫鎖相環的東西可以倍頻就行。倍頻時涉及到三個常量需要定義,分別是:PLL_M, PLL_N, PLL_P,最終得到系統頻率的公式請牢記:SYSCLOCK = HSE / PPL_M * PPL_N / PPL_P,這個公式對于具體的系統來說,這么用:168MHz = 8MHz / PPL_M * PPL_N / PPL_P,因此一個合理的配置就是:
PPL_M = 8; PPL_N = 336; PPL_P = 2;如果有另一塊開發板,系統原理圖上標明OSC_IN和OSC_OUT處接的是25MHz晶振,聰明的你一定知道把上面的PPL_M值修改為25就可以了。時鐘配置時,還有一個宏定義需要定義:PPL_Q,這個是用來配置USB、SD卡讀寫時的頻率的,計算公式是USBClock = HSE / PPL_M * PPL_N /PLL_Q,一般約定USB時鐘頻率小于等于48MHz,因此PPL_Q的范圍也很好確定,如果項目中沒有用到USB和SD卡讀寫,一般這個宏可以忽略,保持默認值(事實上,默認值是7,336/7=48,剛剛好可以把USB頻率設置為48MHz)。
倍頻宏定義
根據我們對原理圖,以及對時鐘樹的認知,下面我們就要著手來配置系統時鐘了。之前已經說過,SystemInit()不需要開發者手動調用,那么時鐘樹上的那些參數怎么配置入參呢。原來是通過宏定義的方式實現的,文件名為:system_stm32f4xx.c,呃。。。如果你不知道這個文件,那可得去看一看Keil5創建STM32工程的步驟了,這個文件在Std標準庫的樣例模板中,具體的路徑為:\STM32F4xx_DSP_StdPeriph_Lib_V1.4.0\Project\STM32F4xx_StdPeriph_Templates,我們一般在Keil中創建STM32的工程,都是復制這個模板工程,標準庫下載地址:http://www.stmicroelectronics.com.cn/en/embedded-software/stsw-stm32065.html。OK,我們打開這個文件,看看里面都有啥:
* 5. This file configures the system clock as follows:*=============================================================================*=============================================================================* Supported STM32F40xxx/41xxx devices*-----------------------------------------------------------------------------* System Clock source | PLL (HSE)*-----------------------------------------------------------------------------* SYSCLK(Hz) | 168000000*-----------------------------------------------------------------------------* HCLK(Hz) | 168000000*-----------------------------------------------------------------------------* AHB Prescaler | 1*-----------------------------------------------------------------------------* APB1 Prescaler | 4*-----------------------------------------------------------------------------* APB2 Prescaler | 2*-----------------------------------------------------------------------------* HSE Frequency(Hz) | 25000000*-----------------------------------------------------------------------------* PLL_M | 25*-----------------------------------------------------------------------------* PLL_N | 336*-----------------------------------------------------------------------------* PLL_P | 2*-----------------------------------------------------------------------------* PLL_Q | 7*-----------------------------------------------------------------------------看,ST寫的注釋非常漂亮是不是,同時我們也注意到官方使用默認HSE確實是25MHz的,如果我們的開發板不做任何配置,直接使用這個配置,時鐘就亂掉了。接下來,我們就不管這些注釋了,直接去修改對應的宏定義吧(搜索關鍵字,重新定義宏):
#define HSE_BYPASS_INPUT_FREQUENCY 8000000/************************* PLL Parameters *************************************/ #if defined (STM32F40_41xxx) || defined (STM32F427_437xx) || defined (STM32F429_439xx) || defined (STM32F401xx) /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */ #define PLL_M 8 //HSE是8MHz晶振,PLL分頻系數設置為8 #else /* STM32F411xE */ #if defined (USE_HSE_BYPASS) #define PLL_M 8 #else /* STM32F411xE */ #define PLL_M 16 #endif /* USE_HSE_BYPASS */ #endif /* STM32F40_41xxx || STM32F427_437xx || STM32F429_439xx || STM32F401xx */ /* USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLLQ */ #define PLL_Q 7#if defined (STM32F40_41xxx) #define PLL_N 336 //倍頻系數,SYSCLOCK = HSE / PPLM * PPLN / PPLP = 8MHz / 8 * 336 / 2 = 168MHz /* SYSCLK = PLL_VCO / PLL_P */ #define PLL_P 2 #endif /* STM32F40_41xxx */簡單測試
OK,經過以上的步驟,我們已經將系統時鐘調整為168MHz了,但是成功了嗎?確實是168MHz嗎?我們來做個實驗就可以了,實驗非常簡單,弄個GPIO控制LED小燈,系統里設置每隔1秒鐘交替閃爍,觀測小燈亮滅的間隙是否差不多為1秒鐘。因為是簡單測試,延時功能我們就不使用定時器或者SysTick了,我們直接用步進法來做延時測試,弄個vu32類型的變量,從0一直累加,直到達到68,000,000,這期間的過程就是1秒鐘。偽代碼如下:
vu32 i = 0; int main(){GPIOInit()...while(1){LED = 1;i = 0;while(i < 168000000)i++;LED = 0;i = 0;while(i < 168000000)i++;} }如果LED小燈能預期按照大概1秒的間隙亮滅的話,就說明我們對STM32的時鐘配置正確了。
?
?
?
?
?
?
?
總結
以上是生活随笔為你收集整理的STM32开发笔记48:STM32F4+DP83848以太网通信指南系列(二):系统时钟的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: xp 无法关闭计算机,xp系统不能关机了
- 下一篇: java信息管理系统总结_java实现科