理解GD32的时钟树并掌握其配置方法,是嵌入式开发的重要基础。下面是GD32时钟树的核心要点,并提供一个清晰的内部和外部时钟源配置流程。
一、GD32时钟树核心概述
GD32的时钟树是一个多源、多路径的分配网络,负责将各种时钟源灵活、安全地分配给内核、存储器和各个外设。
主要时钟源
GD32微控制器提供了丰富的内外部时钟源,以满足不同应用对精度、速度和功耗的需求。
时钟树关键路径
系统时钟 (SYSCLK) 选择:系统时钟 (CK_SYS) 是微控制器内核(Cortex-M)的心脏,其时钟源可以三选一:内部高速 RC 振荡器 (IRC8M/IRC16M)、外部高速晶振 (HXTAL) 或锁相环输出 (PLL)。
锁相环 (PLL) 配置:PLL 用于对输入时钟(如 HXTAL 或 IRC8M)进行倍频,以得到更高的系统时钟频率。其配置公式通常为:PLL输出频率 = (输入时钟频率 / PLL_PS) * PLL_N / PLL_P。
总线时钟分配:系统时钟 (SYSCLK) 通过分频产生不同总线的时钟。AHB 总线时钟通常与 SYSCLK 相同或通过分频获得,APB1 和 APB2 总线时钟则由 AHB 时钟分频而来。外设的时钟速率受其所在总线限制。
外设时钟门控:GD32 的每个外设都有一个时钟门控开关。在初始化外设前,必须先使能其时钟;不需要时,可关闭其时钟以节省功耗。
二、时钟配置流程(以HXTAL经PLL倍频为例)
以下是配置外部高速晶振(HXTAL)并通过PLL倍频获得更高系统时钟的通用步骤,以及切换到内部时钟源的基本方法。
/**
* @brief 配置系统时钟至最高性能状态(使用HXTAL和PLL)
* @NOTE 假设使用8MHz外部晶振,目标配置为168MHz系统时钟(公式仅供参考,请以具体型号手册为准)
* 例: PLL输出 = (HXTAL / PLL_PS) * PLL_N / PLL_P = (8MHz / 8) * 336 / 2 = 168MHz
*/
void SystemClock_Config(void)
{
uint32_t timeout = 0U;
uint32_t stab_flag = 0U;
/* 1. 使能HXTAL */
RCU_CTL |= RCU_CTL_HXTALEN; // 使能外部高速晶振
/* 等待HXTAL稳定 */
do {
timeout++;
stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
} while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); // 超时等待
/* 2. 配置PLL */
/* 选择HXTAL作为PLL时钟源,并配置预分频PLL_PS、倍频PLL_N、后分频PLL_P等参数 */
RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF | RCU_CFG0_PLLMF4 | RCU_CFG0_PLLPREDV); // 清除相关位
RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | (RCU_PLL_MUL21 & (~RCU_CFG1_PLLMF5))); // 配置PLL源和倍频系数等
RCU_CFG1 |= (RCU_PLLPRESEL_HXTAL | RCU_PLL_PREDV4); // 设置预分频系数
/* 3. 使能PLL并等待就绪 */
RCU_CTL |= RCU_CTL_PLLEN; // 使能PLL
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)) { // 等待PLL稳定
}
/* 4. 配置总线分频器 */
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; // AHB 不分频
RCU_CFG0 |= RCU_APB2_CKAHB_DIV2; // APB2 2分频
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; // APB1 2分频
/* 5. 切换系统时钟源到PLL */
RCU_CFG0 &= ~RCU_CFG0_SCS;
RCU_CFG0 |= RCU_CKSYSSRC_PLL; // 选择PLL作为系统时钟源
/* 等待时钟源切换完成 */
while(0U == (RCU_CFG0 & RCU_SCSS_PLL)) { // 等待PLL成为系统时钟
}
}
/**
* @brief 切换到内部时钟源(IRC8M/IRC16M)
* @note 可在需要降低功耗或HXTAL失效时使用
*/
void SwitchTo_IRC8M(void)
{
/* 1. 切换系统时钟源到IRC8M */
RCU_CFG0 &= ~RCU_CFG0_SCS;
RCU_CFG0 |= RCU_CKSYSSRC_IRC8M; // 选择IRC8M作为系统时钟源
/* 等待时钟源切换完成 */
while(0U == (RCU_CFG0 & RCU_SCSS_IRC8M)) {
}
/* 2. (可选)关闭不再使用的时钟源以节能,如HXTAL、PLL */
RCU_CTL &= ~RCU_CTL_HXTALEN; // 关闭HXTAL
RCU_CTL &= ~RCU_CTL_PLLEN; // 关闭PLL
}
三、配置注意事项
时钟启动与稳定:使能 HXTAL/LXTAL 或 PLL 后,务必通过循环查询状态位等待其稳定。若长时间未就绪,需检查硬件连接(晶振、负载电容)或配置参数。
频率匹配与限制:
PLL 配置:仔细计算 PLL 的输入、VCO 及输出频率,确保所有参数均在芯片手册规定的范围内。
总线频率:注意 APB1 等总线的最大允许频率,超过可能导致外设工作异常。
Flash 等待周期:系统时钟频率较高时,需根据芯片要求设置正确的 Flash 读取等待周期 (WS),否则可能导致程序执行失败。
外设时钟使能:在初始化任何外设(如 UART、SPI、TIMER)之前,必须首先在 RCU 中使能该外设的时钟。
低功耗考虑:在低功耗应用中,应及时关闭未使用的外设时钟和不需要的时钟源(如 HXTAL、PLL)以降低动态功耗。
四、总结与建议
理解GD32时钟树的关键在于掌握 “源-路-目的” 的逻辑:
源 (Source):多种内部和外部时钟源。
路 (Path):通过 PLL 倍频/分频,以及多级分频器形成路径。
目的 (Destination):最终将合适的时钟频率安全地送达内核、存储器和各个外设。
————————————————
版权声明:本文为CSDN博主「蜀黍@猿」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_58087444/article/details/151855767
|
|