眾所周知,時鐘是MCU能正常運行的基本條件,就好比心跳或脈搏,為所有的工作單元提供時間 基數(shù)。時鐘控制單元提供了一系列頻率的時鐘功能,包括多個內(nèi)部RC振蕩器時鐘(IRC)、一個外部 高速晶體振蕩器時鐘(HXTAL)、一個外部低速晶體振蕩器時鐘(LXTAL)、一個或多個鎖相環(huán)(PLL) 一個HXTAL時鐘和LXTAL時鐘監(jiān)視器、時鐘預分頻器、時鐘多路復用器和時鐘門控電路等。 本章,我們將通過一個“輸出HXTAL時鐘信號” 的實驗來熟悉RCU的工作流程。
1.1RCU 配置
GD32系列MCU在啟動后首先會執(zhí)行Reset Handler,緊接著就會執(zhí)行SystemInit()函數(shù),而時鐘的初始化,就是在這個函數(shù)中進行,其主要的功能是配置系統(tǒng)時鐘CK_SYS(即主頻),AHB、APB1以及APB2時鐘。SystemInit()函數(shù)由GD32官方庫提供,不同系列的MCU有一些差別,但實現(xiàn)方式基本相同:首先將RCU關(guān)于CK_SYS,AHB、APB1以及APB2時鐘配置的一些寄存器恢復到默認值,然后再執(zhí)行system_clock_config()函數(shù),用于具體的時鐘配置。
實際上用戶可以不用過于關(guān)心上述的實現(xiàn)方式,因為GD32庫已經(jīng)為您提供了多種時鐘源及時鐘選擇,您只需按照以下步驟即可將時鐘設置為您期望的值(以GD32F30x為例,其他系列類似):
(1) 在system_gd32f30x.c中,用戶可通過選擇宏來進行預設的時鐘配置,如下圖代碼清單時鐘配置選擇宏定義,選擇了HXTAL作為PLL時鐘源,且配置CK_SYS為120MHz。
/* system frequency define */ #define __IRC8M (IRC8M_VALUE) /* internal 8 MHz RC oscillator frequency */ #define __HXTAL (HXTAL_VALUE) /* high speed crystal oscillator frequency */ #define __SYS_OSC_CLK (__IRC8M) /* main oscillator frequency */ /* select a system clock by uncommenting the following line */ /* use IRC8M */ //#define __SYSTEM_CLOCK_IRC8M (uint32_t)(__IRC8M) //#define __SYSTEM_CLOCK_48M_PLL_IRC8M (uint32_t)(48000000) //#define __SYSTEM_CLOCK_72M_PLL_IRC8M (uint32_t)(72000000) //#define __SYSTEM_CLOCK_108M_PLL_IRC8M (uint32_t)(108000000) //#define __SYSTEM_CLOCK_120M_PLL_IRC8M (uint32_t)(120000000) /* use HXTAL(XD series CK_HXTAL = 8M, CL series CK_HXTAL = 25M) */ //#define __SYSTEM_CLOCK_HXTAL (uint32_t)(__HXTAL) //#define __SYSTEM_CLOCK_48M_PLL_HXTAL (uint32_t)(48000000) //#define __SYSTEM_CLOCK_72M_PLL_HXTAL (uint32_t)(72000000) //#define __SYSTEM_CLOCK_108M_PLL_HXTAL (uint32_t)(108000000) #define __SYSTEM_CLOCK_120M_PLL_HXTAL (uint32_t)(120000000)
但這種情況下您使用的外部晶振需要是默認值,此值由HXTAL_VALUE定義,如為8000000,那么您應該選擇8MHz的外部晶振。
當然,您可以使用其他規(guī)格的外部晶振,這種情況下就需要去修改RCU配置函數(shù)里面的一些參數(shù),主要是分頻和倍頻系數(shù),以達到期望的配置,具體如何修改,可以結(jié)合GD32的User manual中定義的RCU寄存器來對配置函數(shù)進行分析。
(2) 設置HXTAL_VALUE的值。
此數(shù)值和RCU的初始化其實并沒有太大關(guān)系,但如果您使用的外部晶振不是默認值,那么除了按照步驟(1)修改配置參數(shù)外,您還必須將此HXTAL_VALUE的值修改為實際的外部晶振頻率,這是因為在一些通信外設配置時,庫函數(shù)會調(diào)用HXTAL_VALUE值來設置波特率,如此值設置錯誤,會導致通信異常。
1.2.非默認外部晶振配置時鐘實例
GD32各系列固件庫都已提供配置系統(tǒng)時鐘的函數(shù)。需要注意的是,在使用外部晶振時,固件庫中HXTAL_VALUE值規(guī)定了 外部晶振的默認值,以 GD32F30x系列為例,如下圖代碼清單HXTAL_VALUE選擇宏定義所示,當芯片為非互聯(lián)型(GD32F303)時,默認使用的外部晶振頻率為8MHz,當芯片為互聯(lián)型(GD32F305/307)時,默認使用的外部晶振頻率為25MHz。
#ifdef GD32F30X_CL #define HXTAL_VALUE ((uint32_t)25000000) #else #define HXTAL_VALUE ((uint32_t)8000000)
那么,當我們使用非默認值的外部晶振時,該如何修改時鐘配置函數(shù)呢?以GD32F303為例,首先我們先看下GD32F303的時鐘樹,如圖所示。
預分頻器可以配置AHB、APB2和APB1域的時鐘頻率。 AHB、APB2、APB1域的最高時鐘頻率分別為120MHz、120MHz、60MHz。RCU通過AHB時鐘(HCLK)8分頻后作為Cortex系統(tǒng)定時器(SysTick)的外部時鐘。通過對SysTick控制和狀態(tài)寄存器的設置,可選擇上述時鐘或AHB(HCLK)時鐘作為SysTick時鐘。
ADC時鐘由APB2時鐘經(jīng)2、4、6、8、12、16分頻或由AHB時鐘經(jīng)5、6、10、20分頻獲得,它們是通過設置RCU_CFG0和RCU_CFG1寄存器的ADCPSC位來選擇。
SDIO, EXMC的時鐘由CK_AHB提供。
TIMER時鐘由CK_APB1和CK_APB2時鐘分頻獲得,如果APBx(x=0,1)的分頻系數(shù)不為1,則TIMER時鐘為CK_APBx(x=0,1)的兩倍。
USBD的時鐘由CK48M時鐘提供。通過配置 RCU_ADDCTL寄存器的CK48MSEL及PLL48MSEL位可以選擇CK_PLL時鐘或IRC48M時鐘做為CK48M的時鐘源。
CTC時鐘由IRC48M時鐘提供,通過CTC單元,可以實現(xiàn)IRC48M時鐘精度的自動調(diào)整。
I2S的時鐘由CK_SYS提供。
通過配置RCU_BDCTL寄存器的RTCSRC位, RTC時鐘可以選擇由LXTAL時鐘、IRC40K時鐘或HXTAL時鐘的128分頻提供。RTC時鐘選擇HXTAL時鐘的128分頻做為時鐘源后,當1.2V內(nèi)核電壓域掉電時,時鐘將停止。 RTC時鐘選擇IRC40K時鐘做為時鐘源后,當VDD掉電時,時鐘將停止。
RTC時鐘選擇LXTAL時鐘做為時鐘源后,當VDD和VBAT都掉電時,時鐘將停止。
當FWDGT啟動時, FWDGT時鐘被強制選擇由IRC40K時鐘做為時鐘源。
現(xiàn)在,我們結(jié)合圖GD32F303系統(tǒng)時鐘樹對時鐘樹進行分析:
(1) 標注A為CK_SYS,即系統(tǒng)主時鐘,它一條線連接至CK_I2S,給I2S外設提供時鐘,另一條線經(jīng)過AHB分頻器,輸出到CK_AHB,即標注B。
(2) CK_AHB為AHB總線時鐘,AHB總線時鐘或直連,或經(jīng)過APB1/APB2分頻,給標注C位置的外設提供時鐘。
(3) 那么,CK_SYS從何而來呢,我們看標注A的左邊,CK_SYS通過SCS位域選擇CK_IRC8M、CK_PLL、CK_HXTAL作為時鐘來源,其中CK_IRC8M來源于標注D,即IRC8M(MCU內(nèi)部8M RC時鐘);CK_HXTAL來源于標注F,即HXTAL(外部時鐘);CK_PLL的來源較復雜,我們單獨拿出來說。
(4) CK_PLL來源于鎖相環(huán)倍頻器輸出,倍頻系數(shù)通過PLLMF位域選擇,而PLLMF來源于兩個地方,一個為 IRC8M 的 2 分 頻 , 另 外 一 個 為 預 分 頻 器 PREDV0 , 而 PREDV0 來 源 于 標 注 E, 即CK_IRC48M(內(nèi)部48M RC時鐘)和標注F,即HXTAL(外部高速時鐘)。
(5) 通過以上分析可以得出結(jié)論,CK_PLL的時鐘源為D:IRC8M、E:IRC48M、F:HXTAL,用戶通過相關(guān)寄存器設置選擇時鐘線。
(6) 和前面分析相同,RTC的時鐘來自于F:HXTAL的128分頻、G:LXTAL(外部32.768K低速時鐘)、F:IRC40K(內(nèi)部40K RC時鐘);FWDGT的時鐘來源于F:IRC40K。
(7) 標注I位置為時鐘輸出線,它的作用是將MCU內(nèi)部的一些時鐘信號線輸出到特定IO口上(大部分系列MCU的PA8口都可被設置為時鐘輸出口0,有些系列MCU含有兩組輸出IO,具體IO配置請參考各系列MCU Datasheet)用來給其他器件提供基準時鐘。由圖中可看出通過設置位域CK_OUT0,輸出的時鐘包括CK_PLL、CK_IRC8M、CK_HXTAL、CK_PLL的2分頻。
結(jié)合以上分析,我們來看下GD32F30x固件庫時鐘配置函數(shù)(因篇幅有限,只貼出各分頻和倍頻配置部分),還是以GD32F303芯片為例,如下圖代碼清單時鐘配置部分代碼所示:
/* select HXTAL/2 as clock source */ RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0); /* CK_PLL = (CK_HXTAL/2) * 30 = 120 MHz */ RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); RCU_CFG0 |= RCU_PLL_MUL30;
可以看出,8MHz的HXTAL經(jīng)過預分頻器PREDV0分頻成4MHz,再通過鎖相環(huán)PLL倍頻30倍到了120MHz。
那么,當您選擇其他規(guī)格的外部晶振,比如12MHz,則可以先通過預分頻器PREDV0分頻成6MHz,再通過鎖相環(huán)PLL倍頻20倍即可,如代碼清單 0-4. 使用12MHz外部晶振配置120M系統(tǒng)時鐘所示。
/* select HXTAL/2 as clock source */ RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0); RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0); /* CK_PLL = (CK_HXTAL/2) * 20 = 120 MHz */ RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); RCU_CFG0 |= RCU_PLL_MUL20;
當然,在修改完配置函數(shù)后,別忘了將HXTAL_VALUE值改為12000000。
需要注意的是,在進行時鐘配置時,要嚴格按照Datasheet中規(guī)定的時鐘范圍進行配置,如GD32F303的 HXTAL的選 擇范 圍是4~32MHz, PLL的輸 入范 圍是 1~25MHz,輸出范圍是16~120Mhz,所以當使用32MHz的外部晶振時,不進行預分頻,而直接倍頻是不被允許的。
1.3.硬件連接說明
本章通過“輸出HXTAL時鐘信號”實驗來熟悉RCU的工作流程。
通過前面內(nèi)容講解可知,本章實驗為“輸出HXTAL時鐘信號”,即通過PA8口將HXTAL輸出,我們使用示波器,將探頭連接到PA8口,從示波器上讀取PA8口波形即可。
1.4.軟件配置說明
本小節(jié)講解RCU_Example例程中RCU的配置說明,主要包括外設時鐘配置、GPIO引腳配置、主函數(shù)介紹以及運行結(jié)果。
軟件設計的流程如下:
(1)使能GPIOA時鐘
(2)初始化PA8,將此端口設置為備用功能模式(AFIO)
(3)通過調(diào)用庫函數(shù)選擇HXTAL作為PA8時鐘信號源
外設時鐘配置
void rcu_config(void) { /* enable the GPIOA clock */ rcu_periph_clock_enable(RCU_GPIOA); }
GPIO 引腳配置
代碼清單 0-6. RCU 例程引腳配置
void gpio_config(void) { /* configure PA8 port */ #if defined GD32F10X_HD || GD32F30X_HD || GD32F20X_CL || GD32E10X gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8); #elif GD32F1X0 || GD32F4XX || GD32F3X0 || GD32E23X gpio_mode_set(GPIOA,GPIO_MODE_AF,GPIO_PUPD_NONE,GPIO_PIN_8); gpio_af_set(GPIOA,GPIO_AF_0,GPIO_PIN_8); #endif }
GPIO的配置說明,請參考GPIO章節(jié)。
主函數(shù)說明
代碼清單 0-7 . RCU 例程主函數(shù)
int main(void) { rcu_config(); gpio_config(); #if defined GD32F10X_HD || GD32F30X_HD || GD32E10X rcu_ckout0_config(RCU_CKOUT0SRC_HXTAL); #elif defined GD32F20X_CL || GD32F4XX rcu_ckout0_config(RCU_CKOUT0SRC_HXTAL,RCU_CKOUT0_DIV1); #elif GD32F1X0 || GD32F3X0 || GD32E23X rcu_ckout_config(RCU_CKOUTSRC_HXTAL,RCU_CKOUT_DIV1); #endif while(1){ } }
如代碼清單RCU例程主函數(shù),該主函數(shù)主要分成四部分,RCU時鐘配置、GPIO配置、RCU輸出相關(guān)庫函數(shù)調(diào)用和while(1)主循環(huán),其中RCU輸出相關(guān)庫函數(shù)請讀者結(jié)合各系列MCU Datasheet、User Manual進行RCU例程的分析。
注意:因為是輸出HXTAL,所以必須要使能HXTAL,否則PA8將無波形輸出。一個簡單的辦法是將HXTAL作為CK_SYS時鐘源,請參考本章第一節(jié)內(nèi)容。
1.5.運行結(jié)果
如圖所示 RCU 例程運行結(jié)果為 RCU 例程運行結(jié)果,可看出,PA8 口正確輸出了 HXTAL 波形。
本教程由GD32 MCU方案商聚沃科技原創(chuàng)發(fā)布,了解更多GD32 MCU教程,關(guān)注聚沃科技官網(wǎng)
-
單片機
+關(guān)注
關(guān)注
6035文章
44554瀏覽量
634621 -
mcu
+關(guān)注
關(guān)注
146文章
17123瀏覽量
350978 -
嵌入式
+關(guān)注
關(guān)注
5082文章
19104瀏覽量
304796 -
時鐘樹
+關(guān)注
關(guān)注
0文章
54瀏覽量
10741 -
rcu
+關(guān)注
關(guān)注
0文章
21瀏覽量
5446
發(fā)布評論請先 登錄
相關(guān)推薦
評論