1.1 實驗內(nèi)容
通過本實驗主要學(xué)習(xí)以下內(nèi)容:
? RCU時鐘原理及配置;
? RCU時鐘輸出驗證。
1.2 實驗原理
1.2.1 RCU時鐘樹原理
GD32F303系列MCU的時鐘樹如下圖所示,由該圖可知,GD32F303系列MCU的時鐘樹可大致分為三個部分:1、主系統(tǒng)時鐘以及外設(shè)時鐘配置,如下圖所示,GD32F303系列MCU最高主頻為120MHz(CK_SYS),該系統(tǒng)時鐘根據(jù)SCS[1:0]控制位進(jìn)行選擇,可選擇來源于HSI8M、PLL或者HXTAL,PLL時鐘源可根據(jù)PLLSEL控制位選擇來自于HSI8M/2或者HXTAL以及HSI48M,之后經(jīng)過2-63倍頻(PLLMF)得到PLL時鐘,PLL時鐘可以通過USB分頻輸出給USB模塊,系統(tǒng)時鐘會直接輸出給IIS外設(shè)使用,AHB時鐘可由系統(tǒng)時鐘分頻而來,AHB時鐘最高120M,AHB時鐘會輸出給內(nèi)核以及外設(shè)使用;2、RTC以及獨立看門狗時鐘配置,如圖中2所示,RTC時鐘可選擇HXTAL/128分頻、LXTAL或者IRC40K,獨立看門狗僅可選擇IRC40K使用;3、時鐘輸出配置,如圖中3所示,內(nèi)部系統(tǒng)時鐘、IRC8M、HXTAL以及PLL/2可通過CKOUT0SEL控制位控制輸出到CKOUT引腳。
1.2.2 外部高速晶振原理
外部高速晶振可選擇4-32M時鐘,若系統(tǒng)應(yīng)用中有異步通信以及高精度定時等應(yīng)用建議選擇使用外部高速晶振,外部高速晶振具有更高的精度,在GD32F303應(yīng)用系統(tǒng)中建議選擇8M/16M/24M晶振,因為外部晶振輸入給PLL的時鐘源僅可進(jìn)行1分頻或者2分頻,選擇其他頻率的晶振難以配置到最高120M系統(tǒng)時鐘。
HXTAL具有時鐘監(jiān)測的功能,置位CKMEN控制位將會使能該功能,使能后一旦監(jiān)測到HXTAL失效,HXTAL將自動被禁止,中斷寄存器RCU_INT中的HXTAL時鐘阻塞中斷標(biāo)志位CKMIF將被置‘1’,并產(chǎn)生NMI不可屏蔽中斷,使用者可在NMI中斷中切換到內(nèi)部時鐘并重新進(jìn)行時鐘配置,可用于HXTAL失效情況下的異常處理。
1.2.3 內(nèi)部高速時鐘原理
GD32F303系列MCU的內(nèi)部高速時鐘有IRC8M和IRC48M,IRC8M較為常用,且具有更高的精度,另外需注意內(nèi)部高速時鐘并非晶振,電路上為RC振蕩器,因而比較容易受外部環(huán)境的影響,如下圖所示,常溫下IRC8M的精度約為1%。
1.2.4 內(nèi)部低速時鐘原理
GD32F303系列MCU內(nèi)部有IRC40K低速時鐘,該低速時鐘可以為RTC或FWDG使用,如下圖所示,據(jù)測試IRC40K精度較差,如果作為RTC時鐘源可能存在較大偏差的情況,如果使用者使用RTC建議可以選擇LXTAL外部低頻晶振,或者使用內(nèi)部高速時鐘對IRC40K進(jìn)行校準(zhǔn)(校準(zhǔn)方法為使用內(nèi)部高速時鐘對IRC40K進(jìn)行捕獲,然后調(diào)整IRC40K的trim值)。
1.2.5 外部低速晶振原理
外部低速晶振一般選擇32.768KHZ的晶振,外部低速晶振可以選擇作為RTC時鐘,在這種情況下,RTC可以在VDD掉電以及VBAT不掉電的情況下工作。
1.2.6 時鐘輸出功能
時鐘輸出功能可以輸出4-120MHz的時鐘,具體通過配置CKOUT0SEL控制位進(jìn)行實現(xiàn),另外需要將CKOUT引腳(一般為PA8引腳)配置為推挽輸出的模式,有關(guān)時鐘輸出選擇配置如下表所示。
1.3 硬件設(shè)計
本節(jié)主要介紹開發(fā)板外掛高速晶振以及低速晶振電路。
1.3.1 外部高速晶振電路設(shè)計
外部高速晶振電路如下圖所示,其中外部高速晶振選擇8MHZ,匹配電容選擇20pf,該匹配電容可以參考以下公式:C1=C2=2*(Cload-CS),其中Cload為晶體負(fù)載電容,Cs為PCB以及MCU引腳的雜散電容,典型值為10pf,因而可以選擇負(fù)載電容約為20pf的晶振,匹配電容即可選擇20pf,需要注意晶振盡量靠近MCU引腳擺放,且晶振引腳走線盡量等長,PCB區(qū)域盡量禁空,走線可以包地,另外若走線不等長,匹配電容可以適當(dāng)選擇不同的匹配電容以適配不同的雜散電容。R28的1M歐姆為晶振引腳的反饋電阻,該反饋電阻的作用為減少晶振輸出波形的諧波分量,提高晶振穩(wěn)定性,該電阻并非必須,MCU內(nèi)部也有400K的反饋電阻,從筆者使用來看,并不影響晶振起振及使用,但建議電路上可以選擇保留。R29的100R電阻為晶振引腳串聯(lián)電阻,用于限流以及引腳保護(hù)。另外測量晶振引腳波形時可能存在OSC_IN腳波形為較好的正弦波,OSC_OUT引腳波形可能存在畸變,該現(xiàn)象為正常現(xiàn)象,不影響使用,MCU內(nèi)部使用的為OSC_IN引腳的波形,并通過內(nèi)部整形方波供給MCU使用。
1.3.2 外部低速晶振電路設(shè)計
外部低速晶振電路如下圖所示,外部低速晶振選擇32.768KHz,匹配電容選擇10pf,C1 = C2 = 2*(CLOAD - CS),其中CS為PCB和MCU引腳的雜散電容, 經(jīng)驗值在2pF-7pF之間,建議以5pF為參考值計算。推薦選用外部晶體時,盡量選擇晶體負(fù)載電容在10pF左右的,這樣外部所接匹配電容C1和C2電容值為10pF即可,且PCB Layout時盡可能近地靠近晶振引腳。
1.4 代碼解析
本節(jié)主要進(jìn)行例程代碼解析,主要分成兩個部分:時鐘配置以及CKOUT時鐘輸出驗證。
1.4.1 時鐘配置代碼解析
時鐘配置是一個MCU系統(tǒng)的基礎(chǔ),讀者在開發(fā)MCU項目時需要首先明確當(dāng)前系統(tǒng)所運行的主頻具體是多少,這樣才能夠準(zhǔn)確的進(jìn)行外設(shè)時鐘配置,定時器定時才會準(zhǔn)確,ADC采樣率才會準(zhǔn)確,通信的速率才會準(zhǔn)確等等,系統(tǒng)超頻也會帶來不可預(yù)料的風(fēng)險,因而建議開發(fā)者在開發(fā)初期就需要明確系統(tǒng)主頻配置,有條件的情況下可以通過定時或者時鐘輸出進(jìn)行校驗。
本例程中時鐘配置函數(shù)代碼如以下所示,該代碼實現(xiàn)通過外部8M晶振進(jìn)行PLL倍頻,實現(xiàn)120MHz主系統(tǒng)時鐘的功能。
C
void rcu_system_clk_config_120M(void)
{
uint32_t timeout = 0U;
uint32_t stab_flag = 0U;
/* 使能外部8M晶振 */
RCU_CTL |= RCU_CTL_HXTALEN;
/* 等待外部晶振ready,或者外部晶振未ready情況下超時退出 */
do{
timeout++;
stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
}while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
/* 如果外部晶振未ready,程序卡死進(jìn)入while(1),讀者若避免卡死可在此處切換到內(nèi)部振蕩器使用 */
if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
while(1){
}
}
RCU_APB1EN |= RCU_APB1EN_PMUEN;
PMU_CTL |= PMU_CTL_LDOVS;
/* AHB一分頻,系統(tǒng)時鐘等于AHB時鐘 */
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
/* APB2一分頻,APB2高速外設(shè)時鐘等于AHB時鐘 */
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
/* APB1 二分頻,APB1低速外設(shè)時鐘等于AHB時鐘/2 */
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
/* 選擇HXTAL/2作為PLL時鐘源,開發(fā)板外部晶振為8M,即8/2=4M作為PLL時鐘源*/
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 */
/* 若希望調(diào)整系統(tǒng)時鐘,可以調(diào)整RCU_PLL_MUL30倍頻因子即可 */
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
RCU_CFG0 |= RCU_PLL_MUL30;
/* 使能 PLL */
RCU_CTL |= RCU_CTL_PLLEN;
/* 等待PLL Ready */
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
}
/* 使能PLL高驅(qū)模式 */
PMU_CTL |= PMU_CTL_HDEN;
while(0U == (PMU_CS & PMU_CS_HDRF)){
}
/* 選擇PLL高驅(qū)模式 */
PMU_CTL |= PMU_CTL_HDS;
while(0U == (PMU_CS & PMU_CS_HDSRF)){
}
/* 選擇PLL作為系統(tǒng)時鐘 */
RCU_CFG0 &= ~RCU_CFG0_SCS;
RCU_CFG0 |= RCU_CKSYSSRC_PLL;
/* 等待PLL被選擇作為系統(tǒng)時鐘 */
while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
}
}
如果讀者使用的是其他頻率的晶振,可以選擇修改PLL倍頻因子以及HXTAL的宏定義即可,比如若讀者選擇16MHz晶振,可以將歷程中RCU_PLL_MUL30的倍頻因子修改為RCU_PLL_MUL15,且將HXTAL_VALUE宏定義修改為16000000。
1.4.2 CKOUT時鐘輸出代碼解析
CKOUT時鐘輸出配置代碼如下所示,該函數(shù)無形參輸入,首先將PA8配置為推挽輸出,然后將系統(tǒng)時鐘配置為CKOUT輸出。
C
void ckout_config(void)
{
/* 以下兩句配置PA8作為推挽輸出,即作為CKOUT功能輸出 */
rcu_periph_clock_enable(RCU_GPIOA);
gpio_init(GPIOA,GPIO_MODE_AF_PP,GPIO_OSPEED_MAX,GPIO_PIN_8);
/* 以下語句為配置系統(tǒng)時鐘輸出到CKOUT引腳,若希望輸出其他時鐘可以修改該函數(shù)形參,
在GD32F303上僅可以輸出以下時鐘:RCU_CKOUT0SRC_CKSYS,RCU_CKOUT0SRC_IRC8M,RCU_CKOUT0SRC_HXTAL,RCU_CKOUT0SRC_CKPLL_DIV2*/
rcu_ckout0_config(RCU_CKOUT0SRC_CKSYS);
}
1.4.3 主函數(shù)代碼解析
本例程主函數(shù)如下所示,首先使用外部8M晶振倍頻配置系統(tǒng)時鐘為120MHZ,然后通過PA8將系統(tǒng)時鐘輸出。
C
int main(void)
{
bsp_uart_init(&BOARD_UART); ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????/* 板載UART初始化 */
printf("Example ofClock configuration and output.\r\n");
rcu_system_clk_config_120M(); ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????/*使用外部8M晶振進(jìn)行倍頻,將系統(tǒng)時鐘配置為120M*/
ckout_config(); ???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????/*通過PA8(CKOUT)將系統(tǒng)時鐘輸出*/
while (1)
{}
}
1.5 實驗結(jié)果
首先將PA8外接示波器,然后將本例程編譯通過后,燒錄到紅楓派開發(fā)板中,通過示波器可以觀察到系統(tǒng)時鐘輸出,如下圖所示,本例程中系統(tǒng)時鐘輸出為120MHz。
紅楓派開發(fā)板使用手冊:??????????????????????????????????????????????????GD32F303紅楓派使用手冊 - 飛書云文檔 (feishu.cn)