Взял отладку STM32VL Discovery (на STM32F100RBT6). Работаю с блоком RCC: беру частоту с внешнего кварца 8МГц (HSE) пропускаю через предделитель PREDIV1 и умножаю в блоке PLLMUL. Показания системной частоты SYSCLK снимаю осциллографом на выводе MCO (ножка PA8) см. рис.
Нажмите для просмотра прикрепленного файла
Так вот частота SYSCLK выдается предсказуемо до тех пор пока предделитель PREDIV1 установлен в значении от 1 до 7. А вот если PREDIV1 в значении от 8 и выше (до 16), то программа не выполняется до конца и зацикливается на строчке:
while (!(RCC->CR & RCC_CR_PLLRDY));// Ожидание готовности PLL.
В этот момент контроллер тактируется от внутреннего генератора (HSI), поэтому на выводе MCO вижу частоту 8МГц. В чем может быть проблема?
Вот сам код:
CODE
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
void init_PLL ( unsigned long int HSE_PREDIV,unsigned long int PLLMUL,unsigned long int HSI_OR_HSE)
{
// Проверяем тактируемся ли мы от HSI (), если мы уже сцеплины с HSI тогда можно начать подготовку двух других блоков HSE и PLL
if((RCC->CFGR&RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)// МК тактируется не от HSI
{
RCC->CIR |= RCC_CIR_HSIRDYC; // сброс флага RCC_CR_HSIRDY
RCC->CR |= RCC_CR_HSION; // Запуск HSI
while (!(RCC->CR & RCC_CR_HSIRDY));// Ожидание готовности HSI.
RCC->CFGR &= ~(RCC_CFGR_SW_0|RCC_CFGR_SW_1); // Переключаем на HSI
while ((RCC->CFGR&RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI); // Ожидание переключения на HSI.
}
RCC->CR &= ~RCC_CR_PLLON; // ВЫКЛЮЧАЕМ PLL.
if(HSI_OR_HSE){ //определяем что заводить в PLL
RCC->CFGR |= RCC_CFGR_PLLSRC_PREDIV1; // заводить в блок PLL HSE
RCC->CFGR2 = HSE_PREDIV; //заносим делитель
}
else
RCC->CFGR &= ~RCC_CFGR_PLLSRC_PREDIV1; // заводить в блок PLL HSI
RCC->CFGR &= ~RCC_CFGR_PLLMULL; // Очистить биты PLLMULL
RCC->CFGR |= PLLMUL; //Устанавливаем значение множителя PLLMULL
RCC->CIR |= RCC_CIR_PLLRDYC; // сброс флага RCC_CR_PLLRDY
RCC->CR |= RCC_CR_PLLON; // Запустить PLL.
while (!(RCC->CR & RCC_CR_PLLRDY));// Ожидание готовности PLL.
RCC->CFGR &=~RCC_CFGR_SW; // Очистить биты SW0 и SW1
RCC->CFGR |= RCC_CFGR_SW_PLL; //(Выбираем PLL источником для SYSCLK)
while ((RCC->CFGR&RCC_CFGR_SWS)!=RCC_CFGR_SWS_PLL); // Ожидание переключения на PLL.
}
int main(void) {
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // Разрешение тактирования I/O порта A ( 0x00000004 )
GPIOA->CRH = 0x0000000B; // Вывод PA8 в альтернативную функцию (CNF0= 0; CNF1= 1; MODE0= 0; MODE1= 1; )
RCC->CFGR |= RCC_CFGR_MCO_SYSCLK; // Выбрать ситемный тактовый сигнал ( 0x04000000 )
init_PLL ( RCC_CFGR2_PREDIV1_DIV7, RCC_CFGR_PLLMULL2, RCC_CFGR_PLLSRC_PREDIV1);
while (1){
};
}