Почему PLL не блокируется?У меня правильная конфигурация часов? - PullRequest
1 голос
/ 10 июля 2019

Я использую stm32l412kb для связи по UART.Я пытаюсь настроить периферийные часы USART2 на частоту 72 МГц.После сброса stm32 использует MSI на частоте 4 МГц, а затем я использую PLL для расширения до 72 МГц при достижении периферийного устройства.

Код сохраняется при первой проверке PLLRDY, так как я предполагаю, что PLL не блокируется.Может ли это быть из-за слишком высокой частоты на выходе?Я все правильно настроил?Как я узнаю, что PLL используется вместо MSI 4 МГц или HSE 24 МГц?

'' '

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;
}

' ''

Вашответы всегда высоко ценятся,

Большое спасибо,

Harry

Обновление, благодаря комментариям: Первая проверка PLL была изменена с:

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

до:

while(RCC->CR & RCC_CR_MSIRDY);

Однако проверка PLL все еще застревает на втором.

Ответы [ 3 ]

3 голосов
/ 10 июля 2019

См. Справочное руководство (pdf), раздел 6.2.3 «Часы MSI», «Аппаратная автоматическая калибровка с LSE (режим PLL)» и раздел 6.4.1 «Регистр управления часами (RCC_CR).) "

В вашем коде есть:

RCC->CR |= RCC_CR_MSIPLLEN;

Но перед тем, как включить режим PLL на часах MSI, нужно сделать две вещи:

  1. Внешнийдолжен быть установлен низкочастотный резонатор или генератор (например, тактовый кварц 32768 Гц)
  2. Как сказано в описании Бит 2 MSIPLLEN : MSIPLLEN должен быть включен после включения LSE (LSEON включен)) и готово (LSERDY устанавливается аппаратно). Существует аппаратная защита, позволяющая избежать включения MSIPLLEN, если LSE не готов.

Итак, если у вас установлена ​​LSE, сначала вы должны включитьвключите его и подождите, пока он не будет готов:

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

Но, вероятно, вам не нужно использовать функцию PLL от MSI, потому что USART гораздо более устойчив к отклонениям частоты.Тогда режим MSI-PLL должен быть отключен.

Микроконтроллеры STM32 имеют некоторые защитные механизмы, чтобы избежать неправильного переключения источника синхронизации.Некоторые биты не могут быть установлены, пока источник синхронизации не будет готов, или не могут быть очищены, если источник синхронизации используется.Они описаны в справочном руководстве в битовых описаниях.

Поэтому, пожалуйста, внимательно сравните все шаги, которые вы делаете с руководством.

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 вы забудете установить его источник (биты PLLSRC в PLLCFGR).Т.е.:

// set MSI as the source for PLL
RCC->PLLCFGR = (RCC->PLLCFGR & ~RCC_PLLCFGR_PLLSRC_Msk) | RCC_PLLCFGR_PLLSRC_MSI; 
2 голосов
/ 10 июля 2019

После отключения PLL с помощью RCC->CR &= ~(RCC_CR_PLLON_Msk); дождитесь, пока PLLRDY не будет очищено .

Ваш код делает противоположное, ждет, пока не будет установлено PLLRDY, что означает, что он заблокирован. Но вы только что отключили его, поэтому он не заблокируется.

После настройки PLLCFGR снова включите его и подождите, пока не установится PLLRDY. Эта часть выглядит хорошо в коде.


Когда PLL работает с требуемой скоростью, вы должны установить Переключатель системных часов (RCC_CFGR_SW) в положение PLL вместо выхода тактового сигнала микроконтроллера, чтобы ваша система работала на часах PLL.

Выход тактовой частоты микроконтроллера делает что-то еще. Он может быть подключен к внешнему выводу, к выходу тактового сигнала для использования его вне MCU, например, синхронизировать несколько MCU.

0 голосов
/ 10 июля 2019

Я всегда использую Cube, чтобы увидеть дерево часов.Я также использую регистры - но этот инструмент очень удобен и предотвращает множество глупых ошибок, так как он даст вам знать, если значения выходят за пределы рекомендуемых.

enter image description here

PS это должен быть комментарий, но я хотел поставить картинку.Поэтому, пожалуйста, не принимайте УФ или не принимайте

...