GD32官方提供的固件庫中使用的晶振配置一般為8M或25M,如果讀者使用其他頻率的晶振如何修改配置呢?本文為大家講解如何修改。
以GD32F303為例,官方固件庫中的晶振及時(shí)鐘配置代碼如下,改配置代碼為使用外部8M晶振倍頻到120M時(shí)鐘。
/* 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)#if !defined HXTAL_VALUE#ifdef GD32F30X_CL#define HXTAL_VALUE ((uint32_t)25000000) /*!< value of the external oscillator in Hz */#else#define HXTAL_VALUE ((uint32_t)8000000) /* !< from 4M to 32M *!< value of the external oscillator in Hz*/#endif /* HXTAL_VALUE */#endif /* high speed crystal oscillator value */static void system_clock_120m_hxtal(void){ uint32_t timeout = 0U; uint32_t stab_flag = 0U; /* enable HXTAL */ RCU_CTL |= RCU_CTL_HXTALEN; /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ do{ timeout++; stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); /* if fail */ if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ while(1){ } } RCU_APB1EN |= RCU_APB1EN_PMUEN; PMU_CTL |= PMU_CTL_LDOVS; /* HXTAL is stable */ /* AHB = SYSCLK */ RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; /* APB2 = AHB/1 */ RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; /* APB1 = AHB/2 */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; #if (defined(GD32F30X_HD) || defined(GD32F30X_XD)) /* 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; #elif defined(GD32F30X_CL) /* CK_PLL = (CK_PREDIV0) * 30 = 120 MHz */ RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_PLL_MUL30); /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); RCU_CFG1 |= (RCU_PLLPRESRC_HXTAL | RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); /* enable PLL1 */ RCU_CTL |= RCU_CTL_PLL1EN; /* wait till PLL1 is ready */ while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){ } #endif /* GD32F30X_HD and GD32F30X_XD */ /* enable PLL */ RCU_CTL |= RCU_CTL_PLLEN; /* wait until PLL is stable */ while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ } /* enable the high-drive to extend the clock frequency to 120 MHz */ PMU_CTL |= PMU_CTL_HDEN; while(0U == (PMU_CS & PMU_CS_HDRF)){ } /* select the high-drive mode */ PMU_CTL |= PMU_CTL_HDS; while(0U == (PMU_CS & PMU_CS_HDSRF)){ } /* select PLL as system clock */ RCU_CFG0 &= ~RCU_CFG0_SCS; RCU_CFG0 |= RCU_CKSYSSRC_PLL; /* wait until PLL is selected as system clock */ while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ } }
在此我們舉例,若外部晶振使用16M該如何配置,主要修改以下兩點(diǎn):
修改HXTAL_VALUE為16M,如下紅色底紋部分。
#if !defined HXTAL_VALUE #ifdef GD32F30X_CL #define HXTAL_VALUE ((uint32_t)25000000) /*!< value of the external oscillator in Hz */ #else#define HXTAL_VALUE ((uint32_t)16000000) /* !< from 4M to 32M *!< value of the external oscillator in Hz*/#endif /* HXTAL_VALUE */ #endif /* high speed crystal oscillator value */
修改時(shí)鐘倍頻到120M.如下圖紅色底紋部分,配置15倍頻,計(jì)算公式為16M/2*15=120M.
/* 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) * 15 = 120 MHz */ RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); RCU_CFG0 |= RCU_PLL_MUL15;
PS:GD固件庫中修改使用內(nèi)部時(shí)鐘非常方便,只要打開內(nèi)部時(shí)鐘的宏定義就可以啦。
/* 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)