GD32官方提供的固件库中使用的晶振配置一般为8M或25M,如果读者使用其他频率的晶振如何修改配置呢?本文为大家讲解如何修改。
以GD32F303为例,官方固件库中的晶振及时钟配置代码如下,改配置代码为使用外部8M晶振倍频到120M时钟。
/* 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该如何配置,主要修改以下两点:
修改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 */
修改时钟倍频到120M.如下图红色底纹部分,配置15倍频,计算公式为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固件库中修改使用内部时钟非常方便,只要打开内部时钟的宏定义就可以啦。
/* 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)
发表评论 取消回复