Top.Mail.Ru

Часть 3. STM32 и С++. Инициализация тактового генератора.

Прежде чем мы начнём писать библиотеки для работы с классами, нам необходимо разобраться с тактовым генератором и некоторыми функциями для портов ввода/вывода, которым не требуются классы. В этой статье будет рассмотрен принцип инициализации на максимальную тактовую частоту на внешнем кварцевом резонаторе. Если необходимо будет работать или с внутренним источником тактирования или каки-либо ещё нюансы, поняв как устроен тактовый генератор, можно будет над ним издеваться как захотим. Причём на любом МК.

Для начала посмотрим тактовые генераторы разных МК. Я не стал приводить примеры монструозных тактовых генераторов, чтобы раньше времени никто не испугался. Начнём с более простого. Тактовый генератор STM32F030C8T:

Тактовый генератор STM32F103C8T:

Тактовый генератор STM32F301R8T:

Тактовый генератор STM32F407VET:

Как видите, между ними много общего. В каждом тактовом генераторе есть кое-что, что их объединяет:

  1. Внутренний тактовый HSI генератор на RC-цепочке. У разных МК частота может быть разной. После включения и сброса тактовый генератор находится именно в таком состоянии. Вы можете или остаться на нём или переключиться на кварцевый резонатор. Стабильность этого генератора хуже, чем на кварцевом. Правда в большинстве случаев хватает и этого. Примечание: в других МК он может называться по другому - HSI16, HSI48 и т. д. Но сути это не меняет.
  2. Тактовый генератор с кварцевым резонатором HSE. Где стоит надпись "Input frequency", указано на какие частоты можно поставить кварцевый резонатор.
  3. Мультиплексор. Переключает источники тактирования - внутренний или внешний генератор. В зависимости от МК может иметь разное количество входов, а может и отсутствовать, если выводов у корпуса мало.
  4. Делитель перед модулем PLL. Может входить в состав PLL, может отсутствовать.
  5. Модуль PLL. Крутая штука, позволяющая тактировать ядро МК практически любыми частотами.
  6. Ещё один мультиплексор. По стрелочкам можно определиться, что, куда включает.
  7. Делители шин периферии. Не все шины и не вся периферия может работать на максимальных частотах. Для этого введены дополнительные делители. С ними нужно быть очень осторожными. Прежде чем запускать периферийное устройство, нужно из даташита или Reference manual (RM для краткости) узнать от какой шины тактируется таймер. Самый простой способ - в RM посмотреть в разделе регистров RCC, куда подключено данное устройство и в CubeMX посмотреть частоту тактирования шины.

Теперь нам в CubeMX необходимо выставить все частоты на максимум, который возможен на внешнем кварцевом резонаторе. Я применяю в основном на 8Мгц. Но можно и другой, но не любой. Иначе можете получить дробные частоты и никогда не запустите USB (надеюсь с CubeMX все знакомы):

В данном случае я включил USB, чтобы убедиться, что мы можем получить необходимую частоту. В самой функции делитель можно не включать. Его можно запустить отдельно при инициализации USB, но при этом можно хватануть проблем. Я нашёл некоторый алгоритм, который в большинстве случаев упрощает выбор, но не всегда.

Делитель /M ставим такой, чтобы после него тактовая частота была 2МГц. В нашем случае 8 / 4 = 2. Умножитель *N делаем равным 168,  т. е. максимальной тактовой частоте ядра МК. Получаем на выходе 2*168=336МГц. Делитель /P оставляем по умолчанию, получаем 168МГц на выходе второго мультиплексора. Но у нас шина APB получается перегруженной, поэтому ставим там соответствующие делители для получения необходимых частот. Теперь мы знаем коэффициенты деления и умножения и можем перейти непосредственно к программированию. Но нам необходимо учесть, что данная библиотека предназначена для инициализации тактового генератора после сброса, когда все регистры RCC находятся в состоянии "по умолчанию". Какой регистр и в каком состоянии после сброса, можно узнать из описания регистров в RM.

Шаг 1.

Запускаем тактирование модуля управления питанием PWR и конфигуратора системы SYSCFG. Это не всегда нужно, и иногда этот шаг можно опустить:

RCC->APB1ENR |= RCC_APB1ENR_PWREN;
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;

Шаг 2.

Запускаем HSE и ждём некоторое время в ожидании запуска. Если кварцевый резонатор битый или трассировка платы неудачна, он может и не запуститься. Если запуск так и не произошёл, мы выходим из функции, ничего не предпринимая:

uint32_t StartUpCo