Когда вы работали с STM32 CubeMX вы быстро выставляли мышкой источник тактирования, выбирали делители для шин. Осмелюсь предположить, что вы могли тупо задать частоту HCLK и позволить кубу самостоятельно настроить за вас систему тактирования! Куб очень полезный и очень опасный инструмент, без него начинает казаться, что тактирование ручками настроить вообще не реально. Но это не так и вы в этом убедитесь, конечно же. В микроконтроллерах на базе ядра ARM Cortex-M непростая система тактирования, на первый взгляд. Но стоит лишь один раз во всем разобраться и сразу станет не так страшно. Чтобы ядро процессора функционировало, ему нужен источник тактовых сигналов, чтобы периферия (GPIO, UART, SPI, АЦП и т.д.) функционировала - ей тоже нужно тактирование! Наверное я обрадую вас, сказав, что этот урок можно вообще пропустить, ведь по умолчанию, ядро УЖЕ работает на частоте 8 МГц. Но если хотите вникать по полной, то добро пожаловать под кат* (*вид вечнозелёных кустарников из семейства бересклетовых). Я напомню, что в этом цикле уроков работаем мы с микроконтроллером STM32F103C6T6.
Если вам нравится то, что я делаю и вы хотите следить за новыми статьями - станьте подписчиком Telegram канала ipaSoft Electronics. Чем нас больше, тем я дисциплинированнее))
Все начинается с системной частоты SYSCLK. Ядро процессора тактируется SYSCLK. Ядро процессора со всем остальным соединяется через шину AHB. Эта шина соединяет ядро процессора с RAM, ROM и медленными шинами APB1 и APB2 (для периферии). Тактируется быстрая AHB от источника тактового сигнала SYSCLK. Но не напрямую тактируется, а через делитель, AHB Prescaler. Я не припомню, чтобы хоть раз использовал этот делитель, он у меня обычно всегда /1. Частота, на которой работает AHB называется HCLK.

Вся медленная периферия тактируется от медленных шин APB1 и APB2. А сами шины APB1 и APB2 получают тактирование от HCLK через делители (APB1 Prescaler и APB2 Prescaler).
Открывайте же свой пустой проект, созданный в предыдущем уроке https://ipasoft.info/index.php/articles/cmsis-stm32-urok-1-sozdanie-proekta
Первый регистр, с которого начинают настройку системы тактирования — Clock control register (RCC_CR), значение его по-умолчанию 0x??83. Это означает, что при подаче питания (Reset state) включается только внутренний HSI генератор.

Описание битов регистра:
PLL RDY (25) – правильнее было бы назвать PLL BSY. Если он установлен в лог. 1, то PLL заблокирован, недоступен. Сбрасывается в 0 он аппаратно.
PLL ON (24) – включить (1) или отключить (0) PLL программно. Нельзя отключить, если тактирование системы происходит от PLL.
CSS ON (19) – включить (1) или отключить (0) защиту системы тактирования. Она автоматически переключит с HSE на HSI если с генератором HSE что-то произойдет. Включить CSS можно только при наличии флага HSE RDY.
HSE BYP (18) – тактирование от внешнего источника тактовой частоты (Duty cycle 50%, от 0 до 72 МГц).
HSE RDY (17) – флаг возводится аппаратно, когда HSE стабилен.
HSE ON (16) – устанавливается и сбрасывается программно. Сбрасывается аппаратно, при переходе в режим энергосбережения.
HSI CAL (15..8) – калибровочное значение HSI (заводское), только для чтения.
HSI TRIM (7..3) – пользовательская калибровка встроенного генератора. По-умолчанию, значение 16, что соответствует 8 МГц при 25°С. Каждая единица весит 40 кГц. Таким образом можно нарулить ±0.64 МГц. Эта ручная калибровка позволяет приспособить микроконтроллер к работе на разных температурах.
HSI RDY (1) – встроенный генератор стабилен (1) или не стабилен (0).
HSI ON (0) – включить (1) или отключить (0) встроенный генератор софтово.
Следующий регистр тактирования Clock configuration register (RCC_CFGR)

MCO (26..24) – выход тактовой частоты с ноги MCO микроконтроллера: 0 — нет, 4 — SYSCLK, 5 – HSI, 6 – HSE, 7 – PLL/2.
USBPRE (22) – делитель частоты для USB. 1 – нет. 0 — на 1.5.
PLLMUL (21..18) – множитель для PLL. Коэффициент умножения равен PLLMUL + 2. Например, для умножения на 9, PLLMUL должен быть равен 7.
PLLXTPRE (17) – делить HSE /2 перед входом PLL? 0 – нет, 1 — да.
PLLSRC (16) – источник частоты для PLL. Настраивать только при отключенном PLL. 0 – HSI/2; 1 – HSE.
ADCPRE (15..14) – делитель частоты для АЦП: 0 - /2; 1 - /4; 2 - /6; 3 - /8.
PPRE2 (13..11) – делитель частоты для APB2. 0 – /1; 4 - /2; 5 - /4; 6 - /8; 7 - /16.
PPRE1 (10..8) – делитель частоты для APB1. 0 – /1; 4 - /2; 5 - /4; 6 - /8; 7 - /16.
HPRE (7..4) – делитель частоты для шины AHB. 0 - /1; 8 - /2; 9 - /4; 10 - /8; 11 - /16; 12 - /64; 13 - /128; 14 - /256; 15 - /512.
SWS (3..2) – статус переключения системного тактирования (только чтение). 0 — систему тактирует HSI; 1 – систему тактирует HSE; 2 – систему тактирует PLL;
SW (1..0) — запрос на установку системного тактирования. В случае успеха будет продублирован в статус SWS. 0 — систему тактирует HSI; 1 – систему тактирует HSE; 2 – систему тактирует PLL;
Эти два регистра могут целиком сконфигурировать тактирование системы. Однако стоит учитывать, что системная Flash память довольно медленная, способна работать на частоте до 24 МГц. Поэтому, если вы планируете работать на частоте выше 24 МГц, то придется настраивать задержку (latency) доступа к Flash памяти. Здесь доступны лишь 3 значения: 0 — без задержки, 1 — задержка 1 цикл, 2 — задержка 2 цикла. Чтобы понять, какое значение нужно именно вам, отнимите от планируемой частоты AHB в МГц единицу и разделите на 24. От результата используйте целую часть.
(24 - 1) / 24 = 0.9583(3), целая часть 0, При @24MHz Latency будет 0
(64 – 1) / 24 = 2.625, целая часть 2, при @64MHz Latency будет 2
Теперь приведу примеры настройки тактирования системы.
Пример 1. 64 МГц от внутреннего RC генератора (HSI).
Это максимальная частота, которую можно выжать из HSI. Сначала потребуется установить latency = 2 для flash. Затем, настроить делитель для APB1, он будет AHB / 2 = 32 MHz. Настроить PLL так, чтобы входная частота была HSI/2 (4 MHz) и умножалась на 16. После этого запустим PLL, а потом и начнем тактироваться от PLL.
FLASH->ACR |= 0x02; // Flash latency = 2
RCC->CFGR |= (14 << 18) // PLL x16
| (3 << 14) // ADC Prescaler /8
| (4 << 8); // APB1 prescaler /2
RCC->CR |= RCC_CR_PLLON; // Включить PLL
while(RCC->CR & RCC_CR_PLLRDY) __NOP(); // Ждать готовности PLL
RCC->CFGR |= 0x02; // Переключиться на тактирование от PLL
Пример 2. 72 МГц от генератора HSE с внешним кварцевым резонатором
Это максимально допустимая (по документам) частота, на которой может работать STM32F103. Внешний кварц будем использовать на 16 МГц. Настройка будет состоять из нескольких этапов. Сначала установим flash latency = 2. Установим делитель AHB / 2 @36MHz для APB1. На PLL будет поступать половина частоты от HSE (16/2 = 8 МГц), делить HSE будем установкой бита PLLXTPRE. Потом сам PLL будет умножать 8 МГц на 9, так и получится 72 МГц.
FLASH->ACR |= 0x02; // Flash latency = 2
RCC->CR |= RCC_CR_HSEON; // Запустить HSE
while (!(RCC->CR & RCC_CR_HSERDY)) __NOP(); // Дождаться запуска
RCC->CFGR |= (7 << 18) // PLL x9
| (3 << 14) // ADC Prescaler /8
| (4 << 8) // APB1 Prescaler /2
| RCC_CFGR_PLLXTPRE; // Делить частоту кварца на 2 перед PLL
RCC->CR |= RCC_CR_PLLON; // Включить PLL
while(RCC->CR & RCC_CR_PLLRDY) __NOP(); // Ждать готовности PLL
RCC->CFGR |= 0x02; // Переключиться на тактирование от PLL
Тактирование периферии
По умолчанию отключено тактирование всей периферии GPIO, I2C, UART, Таймеров (кроме системного таймера SysTick) и прочего. Это сделано для экономии энергии. Тактирование периферии включается отдельно по необходимости. Но это обычно делается в контексте изучения самой периферии.
Часы реального времени
В STM32F103 часы реального времени представляют из себя один 32-битный регистр для хода времени, а скорость приращения этого регистра настраивается в RTC->PRLL. Тикать он может от генератора LSE с внешним кварцем 32768 Гц, или от внутренних генераторов на выбор: HSE/128 и LSI RC 40 kHz. Самым интересным способом тактирования часов реального времени я считаю LSE 32768 Hz, так как он позволяет часам идти от батарейки VBAT. Подробно о работе с часами STM32F1 я написал в статье https://ipasoft.info/index.php/articles/pochemu-sbivaetsya-data-i-kalendar-stm32f103
Обсудить эту статью можно здесь https://t.me/ipasoftel/26
<< Предыдущий урок ||| Следующий урок >>
