Всем доброго дня!
Взял отладку 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){
};
}
Сообщение отредактировал IgorKossak - Jan 18 2016, 14:15
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!
Прикрепленные файлы
main.txt ( 2.08 килобайт )
Кол-во скачиваний: 3