首页 > 解决方案 > 为什么 PLL 不锁定?我的时钟配置是否正确?

问题描述

我正在使用 stm32l412kb 进行 UART 通信。我正在尝试将 USART2 外设时钟配置为 72MHz 频率。stm32 复位后使用 4MHz 的 MSI,然后我使用 PLL 在到达外围设备时将其扩展到 72MHz。

该代码在第一次 PLLRDY 检查时保持不变,因为我假设的 PLL 没有锁定。这可能是由于频率输出太高吗?我是否正确配置了所有内容?我怎么知道使用的是 PLL 而不是 4MHz MSI 或 24MHz HSE?

'''

void configureClocks(){
/*Clock Configuration
 * The MSI (at 4MHz) is used as system clock source after startup from Reset.
 * */

/*Turning on the medium speed internal clock (making sure it's on)*/
RCC->CR |= RCC_CR_MSION;
RCC->CR |= RCC_CR_MSIPLLEN;

/*Waiting until clock is ready*/
while(!(RCC->CR & RCC_CR_MSIRDY));

/*Selecting the MSI (0010) as the MCU clock output*/
RCC->CFGR   &= RCC_CFGR_MCOSEL_Msk;
RCC->CFGR   |= (0b0010<<RCC_CFGR_MCOSEL_Pos);


/*Turn off PLL to allow to make changes*/
RCC->CR &= ~(RCC_CR_PLLON_Msk);


/*Make sure PLL is locked*/
while(!(RCC->CR & RCC_CR_PLLRDY));

/*At 4Mhz, (4*36/2 = 72Mhz)*/
RCC->PLLCFGR &= ~(RCC_PLLCFGR_PLLN_Msk | RCC_PLLCFGR_PLLM_Msk);
RCC->PLLCFGR |= (2 << RCC_PLLCFGR_PLLM_Pos) | (36 << RCC_PLLCFGR_PLLN_Pos);

/*Turning back on the PLL clock*/
RCC->CR |= RCC_CR_PLLON;


/*Waiting until clock is ready*/
while(!(RCC->CR & RCC_CR_PLLRDY));

/*Selecting the PLL (0101) as the microcontroller clock output*/
RCC->CFGR   &= RCC_CFGR_MCOSEL_Msk;
RCC->CFGR   |= (0b0101<<RCC_CFGR_MCOSEL_Pos);

/*Enabling the USART2 peripheral clock.*/
RCC->APB1ENR1 &= ~(RCC_APB1ENR1_USART2EN_Msk);
RCC->APB1ENR1 |= (0b1 << RCC_APB1ENR1_USART2EN_Pos);

/*Enabling the GPIOA port peripheral clock*/
RCC->AHB2ENR &= ~(RCC_AHB2ENR_GPIOAEN_Msk);
RCC->AHB2ENR |= (0b1 << RCC_AHB2ENR_GPIOAEN_Pos);
return;
}

'''

您的回复总是非常感谢,

非常感谢,

哈利

更新,感谢评论:第一个 PLL 检查已更改为:

while(!(RCC->CR & RCC_CR_MSIRDY));

到:

while(RCC->CR & RCC_CR_MSIRDY);

但是,PLL 检查仍然卡在第二个。

标签: cconfigurationstm32clock

解决方案


请参阅参考手册(pdf) 第 6.2.3 节“MSI 时钟”、“使用 LSE(PLL 模式)进行硬件自动校准”和第 6.4.1 节“时钟控制寄存器(RCC_CR)”

您的代码中有:

RCC->CR |= RCC_CR_MSIPLLEN;

但在 MSI 时钟上启用 PLL 模式之前,您需要做两件事:

  1. 应安装外部低频谐振器或振荡器(例如 32768Hz 时钟石英)
  2. 正如Bit 2 MSIPLLEN描述中所说:MSIPLLEN 必须在LSE 启用(启用LSEON)并准备好(LSERDY 由硬件设置)后启用。如果LSE 未准备好,有硬件保护可以避免启用MSIPLLEN。

所以,如果你安装了 LSE,首先你必须打开它,然后等待它准备好:

RCC->BDCR |= (RCC_BDCR_LSEON);
/*Make sure LSE is ready*/
while(!(RCC->BDCR & RCC_BDCR_LSERDY));

但可能您不必使用 MSI 的 PLL 功能,因为 USART 对频率偏差的容忍度更高。然后应保持禁用 MSI-PLL 模式。

STM32 MCU 有一些保护机制来避免错误地切换时钟源。某些位在时钟源准备好之前无法设置,或者在时钟源正在使用时无法清除。它们在参考手册的位描述中进行了描述。

因此,请仔细比较您正在执行的所有步骤与手册。

UPD 正如在另一个答案中指出的那样

/*Turn off PLL to allow to make changes*/
RCC->CR &= ~(RCC_CR_PLLON_Msk);


/*Make sure PLL is locked*/
while(!(RCC->CR & RCC_CR_PLLRDY));

禁用时不能锁定 PLL。因此,while 循环将永远运行。

UPD2

在启用 PLL 之前,您忘记设置它的源(PLLCFGR 中的 PLLSRC 位)。IE:

// set MSI as the source for PLL
RCC->PLLCFGR = (RCC->PLLCFGR & ~RCC_PLLCFGR_PLLSRC_Msk) | RCC_PLLCFGR_PLLSRC_MSI; 

推荐阅读