GD32固件库学习(二)—时钟配置
1.背景
利用stm32编程的时候,会涉及到时钟树的配置,根据硬件设计中使用的外部晶振频率来配置,GD32的时钟配置只能通过配置代码实现。
2.GD32F4时钟树
其中红圈部分是需要关注的。
3.代码部分
3.1 外部时钟频率
进入gd43f4xx.h,找到外部晶振定义代码
/* define value of high speed crystal oscillator (HXTAL) in Hz */
#if !defined (HXTAL_VALUE)
#define HXTAL_VALUE ((uint32_t)25000000)
#endif /* high speed crystal oscillator value */
因为我参考开发板电路设计,所以这里是25MHz。
3.2 设置外部晶振作为系统时钟来源
/* system frequency define */
#define __IRC16M (IRC16M_VALUE) /* internal 16 MHz RC oscillator frequency */
#define __HXTAL (HXTAL_VALUE) /* high speed crystal oscillator frequency */
#define __SYS_OSC_CLK (__HXTAL) /* main oscillator frequency */
将__SYS_OSC_CLK修改为外部晶振。
3.3 选择合适的主频,最高支持240MHZ,因为以前stm32用的是168,这里我继续用168.
/* select a system clock by uncommenting the following line */
//#define __SYSTEM_CLOCK_IRC16M (uint32_t)(__IRC16M)
//#define __SYSTEM_CLOCK_HXTAL (uint32_t)(__HXTAL)
//#define __SYSTEM_CLOCK_120M_PLL_IRC16M (uint32_t)(120000000)
//#define __SYSTEM_CLOCK_120M_PLL_8M_HXTAL (uint32_t)(120000000)
//#define __SYSTEM_CLOCK_120M_PLL_25M_HXTAL (uint32_t)(120000000)
//#define __SYSTEM_CLOCK_168M_PLL_IRC16M (uint32_t)(168000000)
//#define __SYSTEM_CLOCK_168M_PLL_8M_HXTAL (uint32_t)(168000000)
#define __SYSTEM_CLOCK_168M_PLL_25M_HXTAL (uint32_t)(168000000)
//#define __SYSTEM_CLOCK_200M_PLL_IRC16M (uint32_t)(200000000)
//#define __SYSTEM_CLOCK_200M_PLL_8M_HXTAL (uint32_t)(200000000)
//#define __SYSTEM_CLOCK_200M_PLL_25M_HXTAL (uint32_t)(200000000)
//#define __SYSTEM_CLOCK_240M_PLL_IRC16M (uint32_t)(240000000)
//#define __SYSTEM_CLOCK_240M_PLL_8M_HXTAL (uint32_t)(240000000)
//#define __SYSTEM_CLOCK_240M_PLL_25M_HXTAL (uint32_t)(240000000)
3.4 通过预分频器配置AHB,APB2,APB1域的时频率。
/*!
\brief configure the system clock to 168M by PLL which selects HXTAL(25M) as its clock source
\param[in] none
\param[out] none
\retval none
*/
static void system_clock_168m_25m_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 */**
** RCU_CFG0 |= RCU_APB2_CKAHB_DIV2;**
** /* APB1 = AHB */**
** RCU_CFG0 |= RCU_APB1_CKAHB_DIV4;**
/* Configure the main PLL, PSC = 25, PLL_N = 336, PLL_P = 2, PLL_Q = 7 */
RCU_PLL = (25U | (336U << 6U) | (((2U >> 1U) - 1U) << 16U) |
(RCU_PLLSRC_HXTAL) | (7U << 24U));
/* 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 168 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_PLLP;
/* wait until PLL is selected as system clock */
while(0U == (RCU_CFG0 & RCU_SCSS_PLLP)){
}
}
如上述加粗部分所示,分别是不分频,2分频,和4分频。
关于这部分代码的详细解释可以参考连接:> https://blog.csdn.net/weixin_40913720/article/details/118251911
配置时钟的几个要点是:
*** 修改使用的外部晶振频率**
*** 将外部晶振作为系统时钟**
*** 取消注释,选择合适的系统时钟频率,取消注释后会有对应的函数进行配置处理,不需要自己操心,详细过程见上面的链接。**