在數(shù)字電路中時鐘是整個電路的心臟,電路的的一舉一動都是根據(jù)時鐘節(jié)拍下進(jìn)行的,隨著信息量逐漸提高,對硬件信息處理能力提出了更大的需求,時鐘作為數(shù)字硬件的關(guān)鍵成員,其性能需要我們關(guān)注,尤其在高速電路設(shè)計中對模擬轉(zhuǎn)換芯片對時鐘性能有很高的需求,因此正確選擇時鐘是很關(guān)鍵的一步,前提是我們要了解時鐘的關(guān)鍵參數(shù)咯。在數(shù)字電路中最常見的時鐘元件有晶振和鎖相環(huán)、時鐘緩沖器等,本節(jié)對系統(tǒng)時鐘進(jìn)行重點講解。
時鐘對于整個硬件系統(tǒng)來說是十分重要的,每一個外設(shè)包括CPU,如果沒有外部時鐘的驅(qū)動就無法工作,時鐘就相當(dāng)于硬件的脈搏,在時鐘驅(qū)動下完成指令執(zhí)行。CPU和外設(shè)工作的快慢和工作效率常用時鐘周期,主頻來進(jìn)行評定。為了讓每一個外設(shè)包括CPU的工作效率達(dá)到最高,我們必須要對時鐘系統(tǒng)進(jìn)行設(shè)置。頻率越高,系統(tǒng)越快。
時鐘系統(tǒng)是由振蕩器(時鐘源)、定時喚醒器、分頻器等組成的電路。常用的信號源有晶體振蕩器和RC振蕩器。
時鐘是嵌入式系統(tǒng)的脈搏,處理器內(nèi)核在時鐘驅(qū)動下完成指令執(zhí)行,狀態(tài)變換等動作,外設(shè)部件在時鐘的驅(qū)動下完成各種工作,比如串口數(shù)據(jù)的發(fā)送、A/D轉(zhuǎn)換、定時器計數(shù)等等。因此時鐘對于計算機(jī)系統(tǒng)是至關(guān)重要的,通常時鐘系統(tǒng)出現(xiàn)問題也是致命的,比如振蕩器不起振、振蕩不穩(wěn)、停振等。
時鐘源的頻率一般是比較小的,需要使用倍頻器倍頻后共給CPU和外設(shè)使用,而外設(shè)的頻率很多都沒有CPU的頻率高,所以又需要分頻器進(jìn)行降頻,以適應(yīng)外設(shè)的工作頻率。
振蕩器是用來產(chǎn)生重復(fù)電子訊號的電子元件。其構(gòu)成的電路叫振蕩電路,能將直流電轉(zhuǎn)換為具有一定頻率交流信號輸出的電子電路或裝置。
晶體振蕩器:
石英晶體振蕩器是高精度和高穩(wěn)定度的振蕩器,被廣泛應(yīng)用于彩電、計算機(jī)、遙控器等各類振蕩電路中,以及通信系統(tǒng)中用于頻率發(fā)生器、為數(shù)據(jù)處理設(shè)備產(chǎn)生時鐘信號和為特定系統(tǒng)提供基準(zhǔn)信號。其優(yōu)點是相對來說振蕩頻率比較穩(wěn)定,精度也較高,精度不易受溫度、濕度等環(huán)境的影響,但價格相對較高,使用時還必須配備兩個起振電容。
STM32中主要有四個時鐘源:
HSI:高速內(nèi)部時鐘,RC振蕩器,頻率為16MHz;該時鐘在系統(tǒng)一上電的時候暫時使用,此時外部管腳還沒有初始化,還無法使用外部高速時鐘,等系統(tǒng)初始化之后,通過配置時鐘就可以切換到外部時鐘源HSE,此后一直使用,倘若系統(tǒng)故障或癱瘓,仍然可以切換到HSI暫時使用,所謂內(nèi)部是指在STM32芯片內(nèi)部已經(jīng)集成了時鐘源。
HSE:高速外部時鐘,可接石英/陶瓷諧振器,或者接外部時鐘源,頻率范圍為4MHz~26MHz,我們開發(fā)板是25MHz,所謂外部是指通過管腳外接一個時鐘源
LSI:低速內(nèi)部時鐘,RC 振蕩器,頻率為 32kHz 左右。供獨(dú)立看門狗和自動喚醒單元使用。
LSE:低速外部時鐘,接頻率為 32.768kHz(非常精確)的石英晶體。這個主要是 RTC(Real_Time Clock,實時時鐘)的時鐘源,保證時間的精確性,如我們?nèi)粘5氖录幻胍幻氲挠嫊r,都用此時鐘。
由此看出,低速的時鐘源都是給一些特定的外設(shè)使用的,而高速的時鐘源供系統(tǒng)以及大部分外設(shè)使用
復(fù)位和時鐘控制RCC( restoration and clock control)單元:主要是配置時鐘系統(tǒng)的分頻、倍頻,以及使能外設(shè)時鐘(即打開外設(shè)時鐘的開關(guān))等,所有的控制都在RCC單元中。
時鐘樹:
1:低速內(nèi)部時鐘,主要給獨(dú)立看門狗進(jìn)行使用
2:低速外部時鐘,外接晶振,大小精確,主要供RTC使用
3:高速內(nèi)部時鐘,16MHz,SW是一個通道選擇器,如果選擇的是HSI,那么該時鐘就被使用稱為SYCCLK。SW作為選擇器,有三種選擇,即HSE、HSI、PLLCLK(經(jīng)過倍頻后的時鐘),芯片正常工作以后常選擇PLLCLK(HSE倍頻后)作為時鐘源,進(jìn)入系統(tǒng)后還可以經(jīng)過分頻系統(tǒng)降頻
4:高速外部時鐘,通常范圍是4-26MHz,STM32f407接的是一個25MHz的晶振,也可以通過SW進(jìn)行選擇成為SYCCLK
5:STM32f407的CPU可以承受的最大主頻為168MHz,如果高速時鐘源直接接入CPU,那么CPU的使用效率是很低的,所以應(yīng)當(dāng)經(jīng)過PLL倍頻因子倍頻后再接入,使CPU工作效率達(dá)到最高,高速內(nèi)部時鐘和高速外部時鐘都可以經(jīng)過PLL單元的倍頻再進(jìn)入CPU,因此某些參考書中認(rèn)為PLL單元也是一個時鐘源是有道理的
可通過多個預(yù)分頻器配置 AHB 頻率、高速 APB (APB2) 和低速 APB (APB1)。AHB 域的最大頻率為 168 MHz。高速 APB2 域的最大允許頻率為 84 MHz。低速 APB1 域的最大允許頻率為 42 MHz。
APB和AHB總線,類似于個人PC系統(tǒng)里的北橋和南橋總線。南橋總線上掛接的都是鼠標(biāo)、鍵盤這些慢速的設(shè)備,北橋上掛接顯卡等高速設(shè)備。南橋頻率低,北橋頻率高。另外,南橋最后也要接到北橋上。這些感覺都類似于APB和AHB。AHB,是Advanced High performance Bus的縮寫,譯作高級高性能總線,這是一種“系統(tǒng)總線”。AHB主要用于高性能模塊(如CPU、DMA和DSP等)之間的連接。AHB 系統(tǒng)由主模塊、從模塊和基礎(chǔ)結(jié)構(gòu)(Infrastructure)3部分組成,整個AHB總線上的傳輸都由主模塊發(fā)出,由從模塊負(fù)責(zé)回應(yīng)。APB,是Advanced Peripheral Bus的縮寫,這是一種外圍總線。APB主要用于低帶寬的周邊外設(shè)之間的連接,例如UART、1284等,它的總線架構(gòu)不像 AHB支持多個主模塊,在APB里面唯一的主模塊就是APB 橋。再往下,APB2(高速APB)負(fù)責(zé)AD,I/O,高級TIM,串口1;APB1(低速APB)負(fù)責(zé)DA,USB,SPI,I2C,CAN,串口2345,普通TIM。
STM32時鐘配置實例:
配置外部時鐘:
在時鐘配置界面進(jìn)行外部高速時鐘配置時,發(fā)現(xiàn)該配置不可使用(文字圖標(biāo)體現(xiàn)為灰色),那是因為連接外部晶振的管腳還未進(jìn)行初始化,因此先配置管腳。
在RCC配置頁面選擇外部高速時鐘,選擇晶振,之后連接晶振的管腳會自動高亮,如下圖所示。
根據(jù)計算,設(shè)置分頻和倍頻參數(shù)的值,使得外設(shè)和內(nèi)核都可以達(dá)到自己的最大工作頻率。
系統(tǒng)剛上電時啟動時使用的是內(nèi)部高速時鐘源HSI,此設(shè)置在剛上電產(chǎn)生的復(fù)位中斷處理函數(shù)中進(jìn)行,即“=SystemInit”在這個函數(shù)中配置了一些列RCC的寄存器就是為了使用初始時鐘的,之后跳轉(zhuǎn)到main函數(shù)中,即“=mian”,才進(jìn)行外部高速時鐘源的配置。
在SystemClock_Config();函數(shù)中會進(jìn)行電源的使能以及分頻和倍頻參數(shù)的設(shè)置,以及對系統(tǒng)定時器的重載數(shù)值寄存器進(jìn)行填值等功能,來操控RCC的寄存器實現(xiàn)功能。
SysTick定時器:能夠定時、計數(shù)的器件稱為定時器
SysTick, 稱作系統(tǒng)滴答定時器,簡稱滴答定時器。是一個定時設(shè)備,位于Cortex內(nèi)核中,可以對輸入的時鐘進(jìn)行計數(shù),當(dāng)然,如果時鐘信號是周期性的,計數(shù)也就是計時。
系統(tǒng)定時器一般用于操作系統(tǒng),用于產(chǎn)生時基,維持操作系統(tǒng)的心跳。根據(jù)這個中斷,系統(tǒng)就可以實現(xiàn)時間片的計算從而切換進(jìn)程。
滴答定時器是一個24位定時器,也就是最多能計數(shù)2^24。在使用的時候,我們一般給計數(shù)器送一個初始的計數(shù)值,計數(shù)器向下計數(shù),每來一個時鐘信號,計數(shù)初值就減一,計數(shù)值減到0的時候,就會發(fā)出一次中斷。然后重新從計數(shù)初值再減一計數(shù),循環(huán)不斷。
SysTick定時器的時鐘來源是HCLK(168MHz),到達(dá)定時器的時鐘可以選擇分頻,也可以選擇不分頻。默認(rèn)情況下不進(jìn)行分頻,是168MHz。
重載數(shù)值寄存器需要用戶自己填寫,系統(tǒng)上電后,重載數(shù)值寄存器會將自己的value賦給定時器,重載數(shù)值寄存器的值設(shè)定好后,系統(tǒng)整個工作過程中中不會被改變。定時器每接收到一個CLK,就會將重載數(shù)值寄存器賦給自己的value值減1,一般時鐘源越快,減到0的速度也越快。減到0經(jīng)歷的時長為vaue值常以一個CLK周期,在168MHz的情況下,一個CLK的周期為1/(169x1000000)秒。一旦減到0后就可以觸發(fā)異常中斷,同時重載數(shù)值寄存器會再一次將自己的value賦給定時器。所有的定時器的工作原理基本相同,SysTick定時器是系統(tǒng)使用的定時器,而用戶專門使用的定時器為Timer。
需要注意的是系統(tǒng)定時器的中斷配置在一初始化時就默認(rèn)使能了,且默認(rèn)1ms觸發(fā)一次中斷,因為系統(tǒng)的定時器常被操作系統(tǒng)使用,而且我們也不會去屏蔽它。如圖,在初始化外部時鐘源時,在SystemClock_Config();函數(shù)中會自動填充重載數(shù)值寄存器的值為時鐘源頻率除以1000,換算后可得系統(tǒng)每1ms觸發(fā)一次中斷。
系統(tǒng)定時器觸發(fā)異常中斷時會進(jìn)入異常處理函數(shù)SysTick_Handler(),此函數(shù)入口在中斷向量表中存在,本質(zhì)上上調(diào)用HAL_SYSTICK_IRQHandler () ;是真正的中斷處理函數(shù)。而HAL_SYSTICK_IRQHandler ()調(diào)用了一個回調(diào)函數(shù),而該回調(diào)函數(shù)是弱生成的,用戶可以使用,在函數(shù)內(nèi)部用戶可以重寫邏輯功能,若是帶有操作系統(tǒng),操作系統(tǒng)會重寫這個回調(diào)函數(shù),維持系統(tǒng)的時基,對多任務(wù)的進(jìn)程進(jìn)行計數(shù)。
由于系統(tǒng)默認(rèn)每1ms觸發(fā)一次中斷,用戶想要想要達(dá)到1s后進(jìn)行中斷處理功能,可讓系統(tǒng)中斷觸發(fā)1000次,因此在重寫HAL_SYsTICK_Callback ( void)回調(diào)函數(shù)時可進(jìn)行如下編程:
void HAL_SYsTICK_Callback (void){
static uint32_t i=0;
i++;
if(i==1000){
printf("systick IRQn");//此處可改為用戶目標(biāo)處理函數(shù)
}
}
補(bǔ)充知識:static關(guān)鍵字在C語言中的用法:
在修飾變量時,static修飾的靜態(tài)局部變量只執(zhí)行一次,而且延長了局部變量的生命周期,直到程序運(yùn)行結(jié)束以后才釋放。以上述代碼為例,每次觸發(fā)中斷進(jìn)入回調(diào)函數(shù)中,i的值不為0,而是保留位上次回調(diào)函數(shù)中i的值。
static修飾全局變量的時,這個全局變量只能在本文件中訪問,不能在其它文件中訪問,即便是extern外部聲明也不可以。
static修飾一個函數(shù),則這個函數(shù)的只能在本文件中調(diào)用,不能被其他文件調(diào)用。Static修飾的局部變量存放在全局?jǐn)?shù)據(jù)區(qū)的靜態(tài)變量區(qū)。
HAL_Delay()的實現(xiàn):
//利用SysTick實現(xiàn)精準(zhǔn)的延時
__weak void HAL_Delay(uint32_tDelay) {
uint32_t tickstart = HAL_GetTick();//獲取當(dāng)前的uwTick值賦值給tickstart
uint32_t wait = Delay;將用戶要延時的值(單位ms)賦值給wait
while((HAL_GetTick() - tickstart) < wait)
//只有當(dāng)條件為假的時候退出,否則一直循環(huán)
//當(dāng)最新的uwTick值與用戶想要進(jìn)入延時獲得的uwTick的差小于
//用戶輸入的延時時間,說明延時時間未到,繼續(xù)循環(huán)
{ }
}
//下面代碼均在文件 stm32f4xx_hal.c 中
static __IO uint32_t uwTick; //定義計數(shù)全局變量
__weak uint32_t HAL_GetTick(void){
return uwTick;
}
//全局變量 uwTick 遞增
__weak void HAL_IncTick(void) {
uwTick++;
}
//Systick 中斷服務(wù)函數(shù):文件 stm32f4xx_it.c 中
void SysTick_Handler(void) {
HAL_IncTick();
HAL_SYSTICK_IRQHandler();
}
每隔 1ms,uwTick增加 1
由于系統(tǒng)默認(rèn)的值每1ms會進(jìn)行一次系統(tǒng)時中斷,
也就是每1ms會進(jìn)行一次時鐘中斷處理
在中斷處理函數(shù)中,系統(tǒng)每次都會調(diào)用函數(shù)HAL_IncTick();
而函數(shù)HAL_IncTick();的功能是將uwTick的值加1
由于系統(tǒng)默認(rèn)的值每1ms會進(jìn)行一次系統(tǒng)時中斷,也就是每1ms會進(jìn)行一次時鐘中斷處理,在中斷處理函數(shù)SysTick_Hanqler ()中,系統(tǒng)每次都會調(diào)用函數(shù)HAL_IncTick();,而函數(shù)HAL_IncTick();的功能是將uwTick的值加1,由此可知,uwTick的值的單位是1ms。
由此可見,HAL_Delay()功能實現(xiàn)的本質(zhì)就是要保障SysTick_Hanqler ()的正常運(yùn)行以更新uwTick的值,因此一定要保證系統(tǒng)時鐘中斷的優(yōu)先級在整個系統(tǒng)中處于足夠的高的地位,不能有外部中斷的優(yōu)先級比系統(tǒng)時鐘中斷的優(yōu)先級高。
HAL_Delay() 的局限:HAL庫的延時函數(shù)有一個局限性,在中斷服務(wù)函數(shù)中使用HAL_Delay會引起混亂,因為它是通過中斷方式實現(xiàn),而 Systick 的中斷在一般操作系統(tǒng)優(yōu)先級是最低的,所以在中斷中運(yùn)行 HAL_Delay會導(dǎo)致死鎖的現(xiàn)象。
-
晶體振蕩器
+關(guān)注
關(guān)注
9文章
613瀏覽量
29014 -
模擬轉(zhuǎn)換器
+關(guān)注
關(guān)注
0文章
42瀏覽量
12678 -
陶瓷諧振器
+關(guān)注
關(guān)注
0文章
22瀏覽量
9526 -
時鐘控制
+關(guān)注
關(guān)注
0文章
17瀏覽量
6804 -
STM32F407
+關(guān)注
關(guān)注
15文章
187瀏覽量
29332
發(fā)布評論請先 登錄
相關(guān)推薦
評論