ST意法半导体
直播中

卢表镜

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

配置寄存器的时候发现当打开HSE PLL后ready寄存器一直为0,为什么?

我在配置寄存器的时候发现当打开 HSE PLL后 ready寄存器一直为0 所以在什么条件之下,这个寄存器的值会变为1呢,我使用的是STM32f401rct6 defmt输出为  value: 1000000010101101110000011新手菜鸡轻喷let register_rcc_pllcfgr = unsafe{(RCC_BASE as *mut RW).offset(0x04 / 4)}; // GPIOC_MODER    let mut cfgr_value = unsafe{ptr::read_volatile(register_rcc_pllcfgr).read()};    cfgr_value &= !(0b1 << 22);    cfgr_value |= 0b1 << 22; // 设置为PLL_ON    cfgr_value &= !(0b111111111 << 6);    cfgr_value |= 0b010101000 << 6; //N    cfgr_value &= !(0b111111 << 0);    cfgr_value |= 0b000100 << 0;//M    cfgr_value &= !(0b11 << 16);    cfgr_value |= 0b01 << 16; //p    cfgr_value &= !(0b1111 << 24);    cfgr_value |= 0b0111 << 24; //q    unsafe{ptr::write_volatile(register_rcc_pllcfgr as *mut u32, cfgr_value)};    defmt::println!("value: {:b}",cfgr_value);    let register_rcc_cr = unsafe{(RCC_BASE as *mut RW).offset(0)}; // GPIOC_MODER    let mut cr_value =unsafe{ptr::read_volatile(register_rcc_cr).read()};    cr_value &= !(0b1 << 24); // 清除第 0 个引脚的配置    cr_value |= 0b1 << 24; // 设置为PLL_ON    cr_value &= !(0b1 << 16); // 清除第 0 个引脚的配置    cr_value |= 0b1 << 16; // 设置为HSE_ON    unsafe{ptr::write_volatile(register_rcc_cr as *mut u32, cr_value)};    //defmt::println!("value: {:b}",cr_value);

回帖(2)

盛方圆

2025-3-13 15:41:32
配置PLL时,PLL应该是关闭的。
举报

京五环以外

2025-3-17 17:37:36

关于STM32F401RCT6的PLL就绪标志(PLLRDY)问题,以下是关键排查点:




  1. HSE启动顺序



    • 必须首先启动HSE并等待就绪:
      // 启用HSE(假设使用外部晶振)
      unsafe { ptr::write_volatile(RCC_CR, ptr::read_volatile(RCC_CR) | RCC_CR_HSEON) };
      // 等待HSE就绪(超时保护很重要)
      while (unsafe { ptr::read_volatile(RCC_CR) } & RCC_CR_HSERDY) == 0 {}




  2. PLL配置规范



    • 配置PLL前必须确保PLL已关闭:
      // 关闭PLL
      unsafe { ptr::write_volatile(RCC_CR, ptr::read_volatile(RCC_CR) & !RCC_CR_PLLON) };
      // 等待PLL停止
      while (unsafe { ptr::read_volatile(RCC_CR) } & RCC_CR_PLLRDY) != 0 {}

    • 正确设置分频/倍频参数(示例配置):
      let pllcfgr = RCC_PLLCFGR_PLLSRC_HSE    // 选择HSE作为PLL输入
      | (8 << RCC_PLLCFGR_PLLM_Pos)       // 输入分频M=8(假设HSE=8MHz)
      | (336 << RCC_PLLCFGR_PLLN_Pos)     // VCO倍频N=336
      | (0 << RCC_PLLCFGR_PLLP_Pos);      // 系统时钟分频P=2(PLLP=0对应/2)
      unsafe { ptr::write_volatile(RCC_PLLCFGR, pllcfgr) };




  3. PLL启动顺序


    // 启动PLL
    unsafe { ptr::write_volatile(RCC_CR, ptr::read_volatile(RCC_CR) | RCC_CR_PLLON) };
    // 等待PLL就绪(必须循环等待)
    while (unsafe { ptr::read_volatile(RCC_CR) } & RCC_CR_PLLRDY) == 0 {}



  4. 关键参数验证



    • 计算VCO频率:VCO = (HSE_FREQ / PLLM) * PLLN

      • 例如HSE=8MHz,M=8 → 输入1MHz,N=336 → VCO=336MHz(符合100-432MHz范围)


    • 系统时钟:SYSCLK = VCO / PLLP

      • P=2 → 336/2=168MHz(但F401最大频率84MHz!此处应配置P=4)





  5. 寄存器位域定义检查



    • 确认寄存器偏移量正确(RCC_PLLCFGR偏移应为0x04)

    • 关键位定义:
      const RCC_CR: *mut u32 = (RCC_BASE + 0x00) as *mut u32;
      const RCC_CR_PLLRDY: u32 = 1 << 25;
      const RCC_CR_PLLON: u32 = 1 << 24;
      const RCC_CR_HSERDY: u32 = 1 << 17;
      const RCC_CR_HSEON: u32 = 1 << 16;




  6. 调试建议



    • 通过defmt输出RCC_CR寄存器值:
      let rcc_cr = unsafe { ptr::read_volatile(RCC_CR) };
      defmt::info!("RCC_CR: {:032b}", rcc_cr);

    • 期望值应包含:

      • Bit 17 (HSERDY) = 1

      • Bit 25 (PLLRDY) 在启动后变为1

      • Bit 24 (PLLON) = 1





  7. 常见错误排查



    • 未正确配置Flash等待周期(高时钟频率需要设置FLASH_ACR)

    • HSE旁路模式配置错误(如果使用外部时钟而非晶振)

    • 未关闭CSS(时钟安全系统)导致自动关闭HSE

    • 硬件问题(如晶振未起振、负载电容不匹配)




建议使用STM32CubeMX生成的初始化代码作为参考,特别是:


// CubeMX生成的典型初始化序列
__HAL_RCC_HSE_CONFIG(RCC_HSE_ON);
while(!__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY));

// 配置PLL前必须关闭PLL
RCC->CR &= ~RCC_CR_PLLON;
while((RCC->CR & RCC_CR_PLLRDY) != 0);

// 配置PLL参数
RCC->PLLCFGR = RCC_PLLCFGR_PLLSRC_HSE | ...
RCC->CR |= RCC_CR_PLLON;
while((RCC->CR & RCC_CR_PLLRDY) == 0);

最后检查您的defmt输出值1000000010101101110000011(二进制)转换为十六进制是0x405B83,对应RCC_CR寄存器值:



  • Bit 24 (PLLON) = 1

  • Bit 25 (PLLRDY) = 0 → 说明PLL未就绪

  • Bit 17 (HSERDY) = 1 → HSE已就绪
    说明问题出在PLL配置参数而非HSE,应重点检查PLLM/N/P的配置是否超出芯片限制。

举报

更多回帖

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