[研电赛技术支持] GD32与STM32时钟树配置对比

[复制链接]
177|0
小海师 发表于 2025-11-6 08:39 | 显示全部楼层 |阅读模式
配置GD32和STM32的时钟树是硬件初始化的核心步骤,直接影响系统主频、外设工作频率及稳定性。两者均基于Cortex-M内核,但时钟管理模块(GD32的RCU vs STM32的RCC)的寄存器定义、分频逻辑和配置流程存在差异。以下分别说明两者的配置方法及核心注意事项。

一、时钟树基本组成(共性)
无论是GD32还是STM32,时钟树的核心组成部分一致,包括:

高速时钟源:HSE(外部高速晶振,通常8MHz/12MHz)、HSI(内部高速时钟,通常8MHz);
PLL锁相环:将输入时钟倍频后作为系统主时钟(如72MHz/108MHz/168MHz);
低速时钟源:LSE(外部低速晶振,32.768kHz,用于RTC)、LSI(内部低速时钟,约40kHz,备用);
时钟分配:通过AHB分频器、APB1/APB2分频器将主时钟分配到外设(如GPIO、UART、SPI等)。
二、GD32时钟树配置(以GD32F1x0系列为例,基于标准库)
GD32的时钟管理由RCU(Reset and Clock Unit) 模块负责,配置步骤如下:

1. 明确目标时钟需求
以“使用HSE(8MHz)作为PLL输入,配置系统主频为72MHz”为例:

系统时钟(SYSCLK)= 72MHz;
AHB时钟(HCLK)= SYSCLK(不分频)= 72MHz;
APB1时钟(PCLK1)= HCLK/2 = 36MHz(APB1外设最大支持36MHz);
APB2时钟(PCLK2)= HCLK(不分频)= 72MHz(APB2外设支持72MHz)。
2. 配置步骤(代码示例)
#include "gd32f1x0.h"

void rcu_config(void) {
    // 步骤1:使能HSE并等待稳定
    rcu_osci_on(RCU_HSE);                  // 使能HSE
    while(rcu_osci_stab_wait(RCU_HSE) == ERROR);  // 等待HSE稳定(超时返回ERROR)

    // 步骤2:配置PLL(输入源为HSE,倍频系数9 → 8MHz × 9 = 72MHz)
    rcu_pll_config(RCU_PLLSOURCE_HSE_DIV1, RCU_PLL_MUL9);  // HSE不分频作为PLL输入,倍频9
    rcu_osci_on(RCU_PLL);                  // 使能PLL
    while(rcu_osci_stab_wait(RCU_PLL) == ERROR);  // 等待PLL稳定

    // 步骤3:配置AHB/APB1/APB2分频
    rcu_hclk_div_config(RCU_SYSCLK_DIV1);   // AHB = SYSCLK / 1 → 72MHz
    rcu_ppre1_div_config(RCU_HCLK_DIV2);    // APB1 = HCLK / 2 → 36MHz
    rcu_ppre2_div_config(RCU_HCLK_DIV1);    // APB2 = HCLK / 1 → 72MHz

    // 步骤4:选择系统时钟源为PLL
    rcu_system_clock_source_config(RCU_CKSYSSOURCE_PLLCLK);  // SYSCLK = PLL输出(72MHz)

    // 步骤5:验证系统时钟频率(可选)
    while(rcu_system_clock_source_get() != RCU_CKSYSSOURCE_PLLCLK);  // 等待时钟源切换完成
}



3. 关键函数说明
rcu_osci_on(RCU_HSE):使能指定时钟源(HSE/HSI/PLL/LSE/LSI);
rcu_pll_config():配置PLL输入源(HSE分频后或HSI分频后)和倍频系数(如RCU_PLL_MUL9表示×9);
分频配置函数:rcu_hclk_div_config()(AHB分频)、rcu_ppre1_div_config()(APB1分频)、rcu_ppre2_div_config()(APB2分频);
时钟源切换:rcu_system_clock_source_config()需在PLL稳定后调用。
三、STM32时钟树配置(以STM32F103系列为例,基于标准外设库SPL)
STM32的时钟管理由RCC(Reset and Clock Control) 模块负责,配置步骤与GD32类似,但函数接口不同。

1. 目标时钟需求(同GD32)
系统时钟(SYSCLK)= 72MHz(HSE 8MHz → PLL ×9);
HCLK = 72MHz,PCLK1=36MHz,PCLK2=72MHz。
2. 配置步骤(代码示例)
#include "stm32f10x.h"

void RCC_Configuration(void) {
    // 步骤1:使能HSE并等待稳定
    RCC_HSEConfig(RCC_HSE_ON);                      // 使能HSE
    ErrorStatus HSEStartUpStatus = RCC_WaitForHSEStartUp();  // 等待HSE稳定
    if(HSEStartUpStatus != SUCCESS) {
        // HSE启动失败,可切换到HSI处理
    }

    // 步骤2:配置PLL(HSE作为输入,不分频,倍频9 → 8MHz ×9=72MHz)
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);  // 配置PLL源和倍频

    // 步骤3:配置AHB/APB1/APB2分频
    RCC_HCLKConfig(RCC_SYSCLK_Div1);     // AHB = SYSCLK /1 →72MHz
    RCC_PCLK1Config(RCC_HCLK_Div2);      // APB1 = HCLK /2 →36MHz
    RCC_PCLK2Config(RCC_HCLK_Div1);      // APB2 = HCLK /1 →72MHz

    // 步骤4:使能PLL并等待稳定,切换系统时钟源为PLL
    RCC_PLLCmd(ENABLE);                  // 使能PLL
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);  // 等待PLL稳定

    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);  // SYSCLK = PLL输出(72MHz)

    // 步骤5:验证时钟频率(可选)
    while(RCC_GetSYSCLKSource() != 0x08);  // 0x08表示PLL作为系统时钟源
}



3. 关键函数说明
RCC_HSEConfig():使能/关闭HSE;
RCC_PLLConfig():配置PLL输入源(RCC_PLLSource_HSE_Div1表示HSE不分频)和倍频系数(RCC_PLLMul_9表示×9);
分频配置:RCC_HCLKConfig()(AHB)、RCC_PCLK1Config()(APB1)、RCC_PCLK2Config()(APB2);
时钟源切换:RCC_SYSCLKConfig()需在PLL稳定后调用,通过RCC_GetSYSCLKSource()验证。
四、STM32 HAL库配置(以STM32F103为例)
HAL库封装了更简洁的接口,通过HAL_RCC_OscConfig()和HAL_RCC_ClockConfig()完成配置:

#include "stm32f1xx_hal.h"

void SystemClock_Config(void) {
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

    // 配置HSE和PLL
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;  // 8MHz ×9=72MHz
    if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
        Error_Handler();
    }

    // 配置系统时钟、AHB、APB1、APB2
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) {
        Error_Handler();
    }
}



注意:HAL库需配置Flash等待周期(FLASH_LATENCY_2),因72MHz主频下需2个等待周期。
五、核心差异与注意事项
PLL输入源选择

GD32:部分型号支持HSE分频(如RCU_PLLSOURCE_HSE_DIV2)或HSI分频作为PLL输入;
STM32F1:PLL输入源可为HSE(分频或不分频)或HSI/2,需根据手册确认。
外设时钟限制

APB1外设(如UART2、I2C)最大频率:GD32和STM32均为36MHz,需确保PCLK1 ≤36MHz;
APB2外设(如GPIO、SPI1)最大频率:通常为72MHz(GD32F1x0/STM32F103),部分高性能型号支持更高频率(如STM32F4支持168MHz)。
低速时钟配置

LSE(32.768kHz)用于RTC,配置时需使能对应引脚(如STM32的PC14/PC15);
若无需RTC,可跳过LSE配置,使用LSI作为备用。
时钟稳定等待

必须等待HSE/PLL稳定后再切换时钟源(通过rcu_osci_stab_wait或RCC_GetFlagStatus验证),否则可能导致系统异常。
Flash等待周期

当系统主频超过一定值(如STM32F1在48~72MHz时需2个等待周期),需配置Flash latency,否则CPU无法正确读取Flash数据(GD32同样需配置)。
六、调试建议
配置完成后,通过库函数获取实际时钟频率(如GD32的rcu_system_clock_freq_get(),STM32的RCC_GetClocksFreq()),验证是否与预期一致;
若外设工作异常(如UART波特率错误),优先检查对应外设的时钟源(如UART1挂在APB2,时钟为PCLK2);
参考芯片参考手册(RM) 的“时钟树”章节,明确外设与APB1/APB2的映射关系(如SPI1在APB2,SPI2在APB1)。
通过以上步骤,可正确配置GD32和STM32的时钟树,确保系统和外设稳定工作。实际配置时需根据具体芯片型号(如GD32F4xx、STM32L0系列)的手册调整参数,因不同系列的时钟树细节可能存在差异。
————————————————
版权声明:本文为CSDN博主「Shylock_Mister」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Shylock_Mister/article/details/153481184

您需要登录后才可以回帖 登录 | 注册

本版积分规则

97

主题

300

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部