Стал более менее нормально ориентироваться в системе тактирования, поэтому решил запилить заметку.
В отличие от AVR в STM32 3 источника тактирования:
1. Внутренний RC (HSI) — установлен внутри мк, поэтому частота всегда фиксированная, недостаток — частота может плавать, для 103 серии 8МГц, для 407 16МГц.
2. Внешний (HSE) — например, кварцевый резонатор, соответственно высокая стабильность и точность отсчетов. Можно частоту изменять, путем замены кварца, т.е. что поставишь то и будет. Максимальная частота для 103 — 25МГц, для 407 серии — 26МГц.
3. Умножитель частоты (PLL) — в этом случае, в начале нужно выбрать какой будет «базовый» источник: HSE или HSI. Далее путем задания коэффициентов, базовая частота делится или умножается. На полученной частоте будет работать камень. Т.е. частоты выше ~25МГц можно получить только задействовав модуль PLL.
При этом нужно учесть что при использовании HSI в качестве базовой, максимальная частота будет ниже чем при использовании HSE. Кроме того, так как частота HSI может плавать, то PLL будет изменяться вместе с ней. Например, мы рассчитываем что HSI = 8МГц, в реальсти она 7.8МГц, допустим коэффициент умножения частоты 9. Тогда на выходе вместо 8*9 = 72МГц, получим 7.8*9 = 70МГц. Где то это не сыграет роли, а где то может и помешать.
Вначале все каменюги стартуют на HSI. Затем можно переключиться на HSE или PLL, в случае каких то сбоев, микроконтроллер не отключатся, а переходит на HSI. Кроме основной тактовой SYSCLK нужно не забывать, что периферия тактируется от разных шин (названия могут отличаться в разных сериях). Каждая шина имеет свою максимальную тактовую частоту, которая может быть намного меньше SYSCLK, поэтому для настройки у каждой шины есть предделители.
Дабы немного освоиться с настройкой лучше поковыряться в STM32Cube Mx, если параметры вне диапазона, то подсвечиваются красным. Выставленные настройки сгенерятся в проект.
Чтобы использовать HSE нужно предварительно в RCC указать внешний кварц, иначе HSE будет не доступно в разделе Clock configuration
Самое неудобное как оказалось, это определение текущей тактовой, для меня в первое время это было весьма проблематично. Можно понадеяться, что все сконфигурировано правильно. Для 100% уверенности у STM32 есть специальная нога MCO, на которую можно вывести текущий тактовый сигнал, тыкнуться осциллографом и посмотреть. При этом нужно учитывать, максимальную частоту GPIO (см. мануал).
Для 103 mco выводится напрямую, т.е. если кварц на 8МГц, то и на пине MCO будет 8МГц, не совсем удобно.
Для F4 MCO можно вывести с предделителем
При настройке тактирования есть еще один тонкий момент с чтением флеш памяти. Если дословно переводить даташит 103 серии:
Данные и инструкции Flash памяти поступают через шину AHB. Если камень работает на частоте выше 24МГц, то медленная флеш не будет успевать, поэтому нужно включать буфер упреждающей выборки(Prefetch buffer). Кроме того, необходимо включать задержку перед чтением операций программируемых «на лету»
нулевая задержка, если 0 < SYSCLK ≤ 24 MHz
один цикл, если 24 MHz < SYSCLK ≤ 48 MHz
два цикла, если 48 MHz < SYSCLK ≤ 72 MHz
Prefetch buffer должен включаться/выключаться только когда SYSCLK ниже чем 24МГц без предделителя на шине AHB (SYSCLK должно быть равно HCLK). Prefetch buffer обычно включается или выключается во время инициализации, когда микроконтроллер тактируется от внутреннего 8МГц RC (HSI) генератора.
Да, это тоже нужно учитывать при тактировании 🙂 Если есть желание - курите референс мануал, если нет - пользуйтесь SPL, HAL.
Прошивок не будет, потому что с кубом и HAL это не актуально - выставить нужные частоты галочками не составит труда. В качестве бонуса оставлю настройку битами, мне пригодилось:
Для внешнего кварца:
RCC->CR|=RCC_CR_HSEON; //Запускаем генератор HSE. while (!(RCC->CR & RCC_CR_HSERDY)) {}; // Ждем готовности RCC->CFGR &=~RCC_CFGR_SW; //Сбрасываем биты RCC->CFGR |= RCC_CFGR_SW_HSE; // Переходим на HSE |
Для внутреннего PLL
RCC->CFGR |= RCC_CFGR_PLLMULL6; //HSI / 2 * 6 = 24 MHz RCC->CR |= RCC_CR_PLLON; //enable PLL while((RCC->CR & RCC_CR_PLLRDY) == 0) {} //wait till PLL is ready RCC->CFGR &= ~RCC_CFGR_SW; //clear SW bits RCC->CFGR |= RCC_CFGR_SW_PLL; //select PLL as system clock while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_1) {} //wait till PLL is used |
Для внешнего PLL
RCC->CR |= RCC_CR_HSEON; //enable HSE while((RCC->CR & RCC_CR_HSERDY) == 0) {} //wait till HSE is ready RCC->CFGR |= RCC_CFGR_HPRE_DIV1 | //HCLK = SYSCLK RCC_CFGR_PPRE2_DIV1 | //PCLK2 = HCLK RCC_CFGR_PPRE1_DIV1; //PCLK1 = HCLK RCC->CFGR &= ~RCC_CFGR_PLLMULL; //clear PLLMULL bits RCC->CFGR |= RCC_CFGR_PLLSRC_PREDIV1 | //PLL source = PREDIV1 RCC_CFGR_PLLXTPRE_PREDIV1_Div2 | //HSE / 2 = 4 MHz RCC_CFGR_PLLMULL6; //4 * 6 = 24 MHz RCC->CR |= RCC_CR_PLLON; //enable PLL while((RCC->CR & RCC_CR_PLLRDY) == 0) {} //wait till PLL is ready RCC->CFGR &= ~RCC_CFGR_SW; //clear SW bits RCC->CFGR |= RCC_CFGR_SW_PLL; //select PLL as system clock while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_1) {} //wait till PLL is used |
Добрый день.
Спасибо за статью. Не хватает только Clock security system (CSS) для перехода на внутренний источник тактирования, если отрубится внешний.
Да, спасибо. Стоит добавить.
только когда пытался настроить, то контроллер просто завис (кварц не был подключен). Наверное что-то упустил при чтении даташита 😛
Здравствуйте! У меня такая проблема: имеется внешний кварц на 11.0592Мгц, инициализация проходит нормально(переключил источник тактирования с HSI на PLL(Pll тактируется с HSE). Но значения битов PLLMULL PLLXTPRE и PLLSRC не меняются при попытке изменить значения этих битов.
их можно менять только ДО того как вы переключитесь на PLL.
Спасибо, да действительно надо настраивать PLL предварительно отключив его, теперь всё заработало.
…Например, мы рассчитываем что HSI = 8МГц, в реальсти она 7.8МГц…
Абалдеть! Неужели так низко пал STM32?!!! Стабильность 2.5%?!!!
что Вас удивляет? это же RC. Вот пруф из даташита:
At 25 °C, the HSI has an accuracy of ±1% typically. In the range of –40 to 105 °C, the accuracy value of the RC frequency increases to the maximum value of ±3%
шарюсь по «мертвым» форумам в поисках истины ))
На STM32F051 не могу переключиться на HSE. Голова уже лопнула ))
Кварц, судя по описанию, может быть до 32 МГц, — я поставил 27 МГц. В обвязке С1=С2=6,8пФ, R1=0, R2=390. Хотя в другом источнике предлагают 10пФ/10пФ, 0/40 Ом, а есть еще вариант — 20пФ/20пФ, и сопротивление 0/0 Ом. Пробовал все.
В тексте проги следующее:
RCC->CR |= RCC_CR_HSEON; // включили питание
while (!(RCC->CR & RCC_CR_HSERDY)) {} // подождали, пока включится
RCC->CFGR |= RCC_CFGR_SW_HSE; // и переключили на тактирование
// процессора от HSE
while (!(RCC->CFGR & RCC_CFGR_SWS_HSE)) {} // подождали, пока включится
..а воз и ныне там… И станок блин не идет, скорости не хватает (((((
самая свежая инфа в даташите, там написано 25МГц максимум
у меня вопрос .Когда включать CSS и где его прописывать?
И как прописывать?
Когда мне лень читать даташит и хочется руками что то поправить, я беру примеры из SPL или HAL и смотрю, как это сделано там. Включать или не включать CSS, зависит от проекта.