这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » STM32 » 【原创】STM32的时钟树配置----fromwan

共1条 1/1 1 跳转至页

【原创】STM32的时钟树配置----fromwan

工程师
2026-10-19 18:11:13     打赏

每次看到新人拿开发板跑例程,时钟配置直接复制ST的Example代码就跑,出了事也不知道哪里的问题。时钟系统是STM32的根基,根没扎好上面全歪。今天把STM32的时钟树好好捋一捋。

一、STM32F1的时钟源有哪些

STM32F103有4个时钟源:

1. HSI:8MHz内部高速RC振荡器,精度1%左右,不用外部元件但精度差

2. HSE:外部高速时钟,接晶振通常用8MHz

3. LSI:32.768kHz内部低速RC,给看门狗和RTC用

4. LSE:32.768kHz外部晶振,给RTC用

二、时钟树结构

简单说一下信号流:

HSE(8MHz) --> PLL(锁相环) --> SYSCLK(72MHz) --> AHB --> APB2(72MHz) --> USART1, SPI1, ADC(最大72MHz)
                                      --> APB1(36MHz) --> USART2/3, SPI2, I2C, USB(48MHz需要分频)

关键点:

• SYSCLK最高72MHz(F103的极限)

• AHB时钟 = SYSCLK

• APB2最高72MHz

• APB1最高36MHz(注意!APB1不能超过36MHz)

• ADC时钟 = PCLK2 / 分频系数,最大72MHz但推荐6-9MHz

三、PLL配置(最关键的一步)

STM32F1的PLL只能锁相到HSE或HSI/2。一般我们用HSE做输入。

PLL输入时钟 = HSE / PLL预分频器 PLL输出时钟 = PLL输入时钟 × PLL倍频系数

要求:PLL输入时钟必须在1-16MHz之间,PLL输出时钟(SYSCLK)最大72MHz。

举例:HSE = 8MHz,要得到72MHz SYSCLK

• PLL预分频器 = 1(不加分频),PLL输入 = 8MHz

• PLL倍频 = 9,PLL输出 = 8MHz × 9 = 72MHz ✓

如果HSE = 12MHz呢?

• PLL预分频器 = 2,PLL输入 = 6MHz

• PLL倍频 = 12,PLL输出 = 6MHz × 12 = 72MHz ✓

四、配置步骤(以HSE=8MHz为例)

void SystemClock_Config(void)
{
    // 1. 使能HSE
    RCC_HSEConfig(RCC_HSE_ON);
    while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);

    // 2. 配置Flash等待周期(72MHz需要2个等待周期)
    FLASH_SetLatency(FLASH_Latency_2);
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

    // 3. 配置AHB分频器(SYSCLK不分频 -> HCLK = 72MHz)
    RCC_HCLKConfig(RCC_SYSCLK_Div1);

    // 4. 配置APB2分频器(HCLK不分频 -> PCLK2 = 72MHz)
    RCC_PCLK2Config(RCC_HCLK_Div1);

    // 5. 配置APB1分频器(HCLK 2分频 -> PCLK1 = 36MHz)
    RCC_PCLK1Config(RCC_HCLK_Div2);

    // 6. 配置ADC分频器(PCLK2 6分频 -> ADC_CLK = 12MHz)
    RCC_ADCCLKConfig(RCC_PCLK2_Div6);

    // 7. 配置PLL:HSE作为输入,预分频1,倍频9
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

    // 8. 使能PLL
    RCC_PLLCmd(ENABLE);
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

    // 9. 选择SYSCLK源为PLL
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

    // 10. 等待切换完成
    while(RCC_GetSYSCLKSource() != 0x08);
}

注意顺序很重要!先配置Flash等待周期再升频,不然CPU访问Flash会出错。这个是很多人踩的坑。

五、USB时钟的特殊处理

如果用USB,需要USB时钟精确的48MHz。PCLK1最高36MHz不够,需要从PLL输出再分频:

// USB时钟源 = PLL输出 / 1.5 = 72MHz / 1.5 = 48MHz
RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div1_5);

注意:用USB的时候APB1不能超过36MHz,但USB时钟可以从PLL直接分频出来不经过APB1。

六、几个实用技巧

1. 上电默认用HSI(8MHz内部振荡器),代码里再切到HSE+PLL。这样即使外部晶振没起振也不会死机。

2. 切换时钟源的时候一定要等稳定标志置位再往下走,不然会出诡异的问题。

3. 调完时钟记得检查各个总线的时钟频率是否符合芯片手册要求。APB1不能超过36MHz,ADC不能超过72MHz,USB必须48MHz±0.2%。

4. 低功耗模式下可以关HSE和PLL只用HSI或LSI,电流能降很多。但切换回来要等振荡器稳定,这段等待时间要注意。

5. 用STM32CubeMX配置时钟树确实方便,但建议至少看懂生成的代码在干什么,不然出了问题排查起来很痛苦。



共1条 1/1 1 跳转至页

回复

匿名不能发帖!请先 [ 登陆 注册 ]