Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Вопросы по тактированию STM32F100
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
allsettingsdone
Здравствуйте, начал подробно разбираться со способами тактирования STM. Написал функцию для простоты которая позволяет выбрать источник тактирования и менять множитель частоты, НО возник момент когда я тактирую мк от внутреннего RC генератора 8 МГц - то программа работает медленней чем если бы тактировал от кварца 8 МГц (смотрел на осциллографе частоту дрыгания ногами в цикле с "for(volatile uint32_t i=10; i>0; i--) {}"). И вот в случае тактирования мк от кварца 8 МГц длительность импульса - 3 мкс, а если выбрать тактирование от внутреннего RC генератора с частотой опять таки 8 Мгц - то длительность импульса будет уже 8 мкс!!! (компилирую в Keil со вторым уровнем оптимизации). И ещё совершенно не получается изменять частоту тактирования при помощи ФАПЧ (PLL). Прилагается проект в Keil. Он сам небольшой, функция называется init_clk(uint32_t clk_sourse, uint32_t PLL_status, uint32_t PLL_freq).
Golikov A.
ну в целом входная частота проходит еще через ряд делителей, и на разных источниках делители разные. Может вы внутренний клок поделили на что-то, а внешний нет... Также есть делители на шине портов и прочей обвески

В процессоре есть специальная ножка на которую выводиться системный клок (не забудьте сделать ее максимально быстрой, в СТМах есть спец регистры которые определяют максимальную частоту работы ножки), подключите эту ножку, и смотрите реальный клок на ней, а не по каким то непонятным циклам.

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

проект качать не очень хочется. вы бы лучше свою функцию в текст сообщения воткнули, ее бы тогда больше народу поглядело...
allsettingsdone
Да вроде бы никаких делителей я не менял на других шинах, и те что есть не делил. Что касается измерения на ножке, то я вывожу прямоугольные импульсы на PC8 | PC9 (на светодиоды на STM32F100DISCOVERY), и в настройках порта выставлена частота тактирования = 50MHz (GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;)
Вот код функции:
CODE

//=======для выбора параметров тактирования в функции init_clk=======
#define HSI 0
#define HSE 1
#define PLL_on 0
#define PLL_off 1

void init_clk(uint32_t clk_sourse, uint32_t PLL_status, uint32_t PLL_freq)
{
if(PLL_status == PLL_on) //если мк тактируется от PLL
{
if(clk_sourse == HSE) //если источником сигнала PLL является HSE
{
RCC->CFGR2 &= ~RCC_CFGR2_PREDIV1; //предочистка делителя HSE
RCC->CFGR2 |= RCC_CFGR2_PREDIV1_DIV1; //делить частоту HSE на 1

RCC->CFGR |= RCC_CFGR_PLLSRC; //источником сигнала для PLL выбран HSE
RCC->CR &= ~RCC_CR_PLLON; //отключить генератор PLL
RCC->CFGR &= ~RCC_CFGR_PLLMULL; //очистить PLLMULL
switch(PLL_freq)
{
case(2): RCC->CFGR |= RCC_CFGR_PLLMULL2; //коэфициент умножения = 2
case(3): RCC->CFGR |= RCC_CFGR_PLLMULL3; //коэфициент умножения = 3
case(4): RCC->CFGR |= RCC_CFGR_PLLMULL4; //коэфициент умножения = 4
case(5): RCC->CFGR |= RCC_CFGR_PLLMULL5; //коэфициент умножения = 5
case(6): RCC->CFGR |= RCC_CFGR_PLLMULL6; //коэфициент умножения = 6
case(7): RCC->CFGR |= RCC_CFGR_PLLMULL7; //коэфициент умножения = 7
case(8): RCC->CFGR |= RCC_CFGR_PLLMULL8; //коэфициент умножения = 8
case(9): RCC->CFGR |= RCC_CFGR_PLLMULL9; //коэфициент умножения = 9
case(10): RCC->CFGR |= RCC_CFGR_PLLMULL10; //коэфициент умножения = 10
case(11): RCC->CFGR |= RCC_CFGR_PLLMULL11; //коэфициент умножения = 11
case(12): RCC->CFGR |= RCC_CFGR_PLLMULL12; //коэфициент умножения = 12
case(13): RCC->CFGR |= RCC_CFGR_PLLMULL13; //коэфициент умножения = 13
case(14): RCC->CFGR |= RCC_CFGR_PLLMULL14; //коэфициент умножения = 14
case(15): RCC->CFGR |= RCC_CFGR_PLLMULL15; //коэфициент умножения = 15
case(16): RCC->CFGR |= RCC_CFGR_PLLMULL16; //коэфициент умножения = 16
}
RCC->CR |= RCC_CR_PLLON; //включить генератор PLL
while((RCC->CR & RCC_CR_PLLRDY)==0) {} //ожидание готовности PLL
RCC->CFGR &= ~RCC_CFGR_SW; //очистка битов выбора источника тактового сигнала
RCC->CFGR |= RCC_CFGR_SW_PLL; //выбрать источником тактового сигнала PLL
while((RCC->CFGR&RCC_CFGR_SWS)!=0x08){} //ожидание переключения на PLL
}
else //если источником сигнала PLL является HSI
{
RCC->CFGR &= ~RCC_CFGR_PLLSRC; //источником сигнала для PLL выбран HSI с делением на 2
RCC->CR &= ~RCC_CR_PLLON; //отключить генератор PLL
RCC->CFGR &= ~RCC_CFGR_PLLMULL; //очистить PLLMULL
switch(PLL_freq)
{
case(2): RCC->CFGR |= RCC_CFGR_PLLMULL2; //коэфициент умножения = 2
case(3): RCC->CFGR |= RCC_CFGR_PLLMULL3; //коэфициент умножения = 3
case(4): RCC->CFGR |= RCC_CFGR_PLLMULL4; //коэфициент умножения = 4
case(5): RCC->CFGR |= RCC_CFGR_PLLMULL5; //коэфициент умножения = 5
case(6): RCC->CFGR |= RCC_CFGR_PLLMULL6; //коэфициент умножения = 6
case(7): RCC->CFGR |= RCC_CFGR_PLLMULL7; //коэфициент умножения = 7
case(8): RCC->CFGR |= RCC_CFGR_PLLMULL8; //коэфициент умножения = 8
case(9): RCC->CFGR |= RCC_CFGR_PLLMULL9; //коэфициент умножения = 9
case(10): RCC->CFGR |= RCC_CFGR_PLLMULL10; //коэфициент умножения = 10
case(11): RCC->CFGR |= RCC_CFGR_PLLMULL11; //коэфициент умножения = 11
case(12): RCC->CFGR |= RCC_CFGR_PLLMULL12; //коэфициент умножения = 12
case(13): RCC->CFGR |= RCC_CFGR_PLLMULL13; //коэфициент умножения = 13
case(14): RCC->CFGR |= RCC_CFGR_PLLMULL14; //коэфициент умножения = 14
case(15): RCC->CFGR |= RCC_CFGR_PLLMULL15; //коэфициент умножения = 15
case(16): RCC->CFGR |= RCC_CFGR_PLLMULL16; //коэфициент умножения = 16
}
RCC->CR |= RCC_CR_PLLON; //включить генератор PLL
while((RCC->CR & RCC_CR_PLLRDY)==0) {} //ожидание готовности PLL
RCC->CFGR &= ~RCC_CFGR_SW; //очистка битов выбора источника тактового сигнала
RCC->CFGR |= RCC_CFGR_SW_PLL; //выбрать источником тактового сигнала PLL
while((RCC->CFGR&RCC_CFGR_SWS)!=0x08){} //ожидание переключения на PLL
}
}
else //если мк тактируется не от PLL
{
if(clk_sourse == HSE) //если мк тактируется от внешнего генератора HSE
{
RCC->CR |= RCC_CR_HSEON; //включить генератор HSE
while((RCC->CR & RCC_CR_HSERDY)==0) //ожидание готовности HSE
RCC->CFGR &= ~RCC_CFGR_SW; //очистка битов выбора источника тактового сигнала
RCC->CFGR |= RCC_CFGR_SW_HSE; //выбрать источником тактового сигнала генератор HSE
}
else //если мк тактируется от внутреннего генератора HSI
{
RCC->CR |= RCC_CR_HSION; //включить генератор HSI
while((RCC->CR & RCC_CR_HSIRDY)==0) {} //ожидание готовности HSI
RCC->CFGR &= ~RCC_CFGR_SW; //очистка битов выбора источника тактового сигнала
RCC->CFGR |= RCC_CFGR_SW_HSI; //выбрать источником тактового сигнала генератор HSI
}
}
}


Вот так к примеру я вызываю функцию: init_clk(HSI,PLL_off,1); //тактирование от генератора HSI, ФАПЧ выключен, коэффициент умножения ФАПЧ = 1 (все равно в данном случае не используется)
allsettingsdone
Может так вопрос будет понятнее:

===========================================================
В случае тактирования от PLL (а PLL от внешнего кварцевого резонатора (HSE))

1.Предочистка делителя для HSE
Код
RCC->CFGR2 &= ~RCC_CFGR2_PREDIV1;


2.Делить частоту HSE на 1
Код
RCC->CFGR2 |=  RCC_CFGR2_PREDIV1_DIV1;


3.Источником сигнала для PLL выбран HSE
Код
RCC->CFGR |= RCC_CFGR_PLLSRC;


4.Отключить генератор PLL
Код
RCC->CR   &= ~RCC_CR_PLLON;


5.Очистить PLLMULL
Код
RCC->CFGR &= ~RCC_CFGR_PLLMULL;


6.Коэффициент умножения = 2
Код
RCC->CFGR |=  RCC_CFGR_PLLMULL2;


7.Включить генератор PLL
Код
RCC->CR   |=  RCC_CR_PLLON;


8.Ожидание готовности PLL
Код
while((RCC->CR & RCC_CR_PLLRDY)==0) {}


9.Очистка битов выбора источника тактового сигнала
Код
RCC->CFGR &= ~RCC_CFGR_SW;


10.Выбрать источником тактового сигнала PLL
Код
RCC->CFGR |=  RCC_CFGR_SW_PLL;


11.Ожидание переключения на PLL
Код
while((RCC->CFGR&RCC_CFGR_SWS)!=0x08){}


===========================================================

В случае тактирования от внешнего кварца (HSE)

1.Включить генератор HSE
Код
RCC->CR     |= RCC_CR_HSEON;


2.Ожидание готовности HSE
Код
while((RCC->CR & RCC_CR_HSERDY)==0)


3.Очистка битов выбора источника тактового сигнала
Код
RCC->CFGR &= ~RCC_CFGR_SW;


4.Выбрать источником тактового сигнала генератор HSE
Код
RCC->CFGR |=  RCC_CFGR_SW_HSE;


===========================================================

В случае тактирования от внутреннего RC-генератора (HSI) без PLL

1.Включить генератор HSI
Код
RCC->CR   |=  RCC_CR_HSION;


2.Ожидание готовности HSI
Код
while((RCC->CR & RCC_CR_HSIRDY)==0) {}


3.Очистка битов выбора источника тактового сигнала
Код
RCC->CFGR &= ~RCC_CFGR_SW;


4.Выбрать источником тактового сигнала генератор HSI
Код
RCC->CFGR |=  RCC_CFGR_SW_HSI;


===========================================================

И при настройках на одинаковые частоты тактирования (во всех трех случаях должно быть 8 МГц) у меня получаются разные временные задержки.
Что я делаю не так?
yarunt
По Кейловскому стартапу при выборе ppl entry clock source есть два варианта HSE или HSI/2. При HSI/2 ставлу в 2 раза умножение больше и все работает.
allsettingsdone
На сколько я знаю при использовании PLL от HSI - частота на 2 не делится, а при использовании HSE (то есть внешнего резонатора) - для PLL частота аппаратно сама на 2 делится. Так вот что умножай что не умножай - частоты не совпадают, и не получается от PLL сделать например 16 или 24 МГц.
yarunt
Ну, а как обстоят дела с калибровочным байтом HSI TRIMMING, он тоже очень влияет на частоту.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.