新唐MCU技术
直播中

李芳

8年用户 1545经验值
私信 关注
[问答]

为什么使用以下命令初始化系统时钟源时,HCLK的时钟源无法切换到PLL?

为什么使用以下命令初始化系统时钟源时,HCLK的时钟源无法切换到PLL?

回帖(2)

夏日余晖

2025-8-26 17:27:53

**CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_HCLKSEL_Msk);  **
CLK->CLKSEL0 |= CLK_CLKSEL0_HCLKSEL_PLL;

答:在执行第一个命令行时,

CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_HCLKSEL_Msk);

HCLKSEL (CLKSEL0 [2: 0]) 设置为 0x00。当HCLKSEL设置为0x00时,如下图所示,HCLK的时钟源切换到外部晶体。


如果此时外部晶体不稳定或不启用,则开关时钟源将发生故障,HCLKSEL 将保持其默认设置(初始化为 0x07,时钟源为 HIRC)。

因此,在执行第二个命令行时,

CLK->CLKSEL0 |= CLK_CLKSEL0_HCLKSEL_PLL;

无法将 HCLKSEL 正确设置为 PLL,也无法将 HCLK 切换到 PLL。


要切换时钟源,用户需要确保要切换的时钟源稳定。建议使用以下方法切换时钟源:


1.直接写一个值

CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_HCLKSEL_Msk) | CLK_CLKSEL0_HCLKSEL_PLL;


2.调用功能

CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_PLL,CLK_CLKDIV_HCLK(2));​


举报

挽你何用

2025-8-29 17:29:38

在使用命令初始化系统时钟源时,若HCLK无法切换到PLL,可能是以下原因导致的:


1. PLL未就绪或配置错误



  • 原因:  

    • PLL未启用(RCC_CR寄存器中PLLON位未置1)。  

    • PLL时钟源(如HSE/HSI)未就绪(HSERDY/HSIRDY标志未置位)。  

    • PLL倍频系数超范围或配置错误(如输入频率过高)。  



  • 解决步骤:  


     // 正确启用时钟源(以HSE为例)
    RCC->CR |= RCC_CR_HSEON;                   // 开启HSE
    while(!(RCC->CR & RCC_CR_HSERDY));         // 等待HSE就绪

    // 配置PLL(假设目标SYSCLK=72MHz)
    RCC->CFGR |= RCC_CFGR_PLLSRC_HSE;          // PLL源选择HSE
    RCC->CFGR |= RCC_CFGR_PLLMUL9;             // 倍频9倍(8MHz*9=72MHz)
    RCC->CR |= RCC_CR_PLLON;                   // 开启PLL
    while(!(RCC->CR & RCC_CR_PLLRDY));         // 等待PLL锁定



2. 时钟切换步骤错误



  • 原因:  

    • 切换系统时钟到PLL时未遵循时序规范(未等待切换完成)。  

    • 直接修改RCC_CFGRSW位,但未检查切换状态。  


  • 解决步骤:  
     RCC->CFGR |= RCC_CFGR_SW_PLL;              // 切换系统时钟源到PLL
    while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); // 等待切换完成


3. Flash预取未配置



  • 原因:  

    • 当PLL输出频率较高时,需调整Flash等待周期(如STM32F1系列超过24MHz需设置FLASH_ACR)。  


  • 解决步骤:  
     FLASH->ACR |= FLASH_ACR_PRFTBE;            // 开启Flash预取
    FLASH->ACR |= FLASH_ACR_LATENCY_2;         // 2等待周期(适用于72MHz)


4. 外设时钟未正确启用



  • 原因:  

    • PLL所需时钟源(如HSE)对应外设未开启(如外部晶振控制寄存器未启用)。  


  • 解决步骤(以STM32启用HSE为例):  
     RCC->CR |= RCC_CR_HSEON;                   // 启用HSE
    while(!(RCC->CR & RCC_CR_HSERDY));         // 等待HSE就绪


5. 总线分频设置冲突



  • 原因:  

    • RCC_CFGRHPRE(HCLK分频)配置过大,导致HCLK频率为0。  


  • 解决步骤:  
     RCC->CFGR &= ~RCC_CFGR_HPRE;              // 清除分频设置
    RCC->CFGR |= RCC_CFGR_HPRE_DIV1;           // 设置HCLK不分频(SYSCLK=HCLK)


6. 硬件问题



  • 原因:  

    • 外部晶振(HSE)未起振或电路故障。  


  • 排查方法:  

    • 检查晶振电路焊接、负载电容匹配。  

    • 暂时改用内部HSI测试:  
      RCC->CFGR |= RCC_CFGR_PLLSRC_HSI_DIV2;  // PLL源改用HSI





完整示例代码(STM32F10x)


void SystemClock_Init(void) {
    // 1. 启用HSE
    RCC->CR |= RCC_CR_HSEON;
    while (!(RCC->CR & RCC_CR_HSERDY));

    // 2. 配置Flash等待周期
    FLASH->ACR |= FLASH_ACR_PRFTBE;
    FLASH->ACR |= FLASH_ACR_LATENCY_2;

    // 3. 配置PLL(8MHz HSE * 9 = 72MHz)
    RCC->CFGR |= RCC_CFGR_PLLSRC_HSE;       // PLL源选择HSE
    RCC->CFGR |= RCC_CFGR_PLLMUL9;          // 9倍频
    RCC->CR |= RCC_CR_PLLON;                // 开启PLL
    while (!(RCC->CR & RCC_CR_PLLRDY));     // 等待PLL锁定

    // 4. 设置总线分频(HCLK不分频,APB1=36MHz,APB2=72MHz)
    RCC->CFGR |= RCC_CFGR_HPRE_DIV1;        // HCLK = SYSCLK
    RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;       // APB1 = HCLK/2
    RCC->CFGR |= RCC_CFGR_PPRE2_DIV1;       // APB2 = HCLK

    // 5. 切换到PLL
    RCC->CFGR |= RCC_CFGR_SW_PLL;           // 选择PLL作为系统时钟
    while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); // 等待切换
}

关键排查点































问题 检查位置
PLL未就绪 RCC_CR寄存器的PLLRDY
HSE/HSI未就绪 RCC_CRHSERDY/HSIRDY
Flash等待周期未配置 FLASH_ACR寄存器
时钟切换未完成 RCC_CFGRSWS状态位
分频器设置错误 RCC_CFGRHPRE/PPRE

通过逐步检查上述配置和硬件状态,即可定位HCLK无法切换到PLL的根本原因。

举报

更多回帖

发帖
×
20
完善资料,
赚取积分