STM32Cube. RCC. Настройки тактирования.

Как и обещал в этой статье мы поговорим о настройке всевозможных тактовых частот различных шин при помощи STM32Cube. Статья, в целом, будет небольшая, но важная, поскольку эти настройки являются основополагающей частью любого проекта с использованием STM32.

Настройки частот

Итак, для тестирования мы можем взять за основу проект из предыдущей статьи с таймером (ссылка). Так мы будем наглядно видеть как именно влияют наши эксперименты с тактовой частотой на работу реального железа.

Собственно, говорить тут особо не о чем, перейдем сразу к практике. Открываем STM32Cube и сразу же идем на вкладку Clock Configuration:

Тактирование в STM32

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

Итак, наш таймер TIM3 сидит на шине APB1. Как мы видим из этой схемы у нас используется внутренний высокочастотный генератор на 16 МГц (HSI — High Speed Internal). Полученные на его выходе 16 МГц проходят через два предделителя, обозначенных на схеме синим, прежде чем добираются до шины APB1. Но поскольку в данном случае эти предделители равны 1 на APB1 мы получаем все те же 16 МГц. Именно эту частоту мы и брали, когда рассчитывали делитель частоты для таймера в предыдущей статье.

Давайте увеличим APB1 Prescaler до 4 и посмотрим, как это скажется на работе таймера и мигании нашего светодиода. При смене предделителя у нас умножитель частоты для APB1 Timer Clocks станет равным 2 и в итоге мы получим 8 МГц:

Настройки STM32

Открываем полученный проект и ищем там в файле main.c функцию SystemClock_Config():

void SystemClock_Config(void)
{
 
  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
 
  __PWR_CLK_ENABLE();
 
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
 
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = 6;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  HAL_RCC_OscConfig(&RCC_OscInitStruct);
 
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
 
}

Как видите, в заново сгенерированном коде абсолютно правильно установлено наше новое значение предделителя:

RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;

Кстати стоит отметить еще одну очень важную деталь…

В полученном коде есть специальные секции вида:

/* USER CODE BEGIN 1 */
 
/* USER CODE END 1 */

Если мы поместим код внутрь этих секций, то при повторной генерации проекта Cube учтет наличие нашего кода в старом проекте и перенесет его в новый проект. Вот сейчас мы изменили настройки тактирования и заново сгенерировали проект и файлы с исходным кодом, а наш код, который переключает состояние светодиода в прерывании по переполнению таймера никуда не пропал и остался на своем месте. А все почему? А потому, что он помещен в специальную секцию для пользовательского кода =)

/* USER CODE BEGIN TIM3_IRQn 1 */
 
  HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12);
 
  /* USER CODE END TIM3_IRQn 1 */

Теперь нам остается собрать проект и запрограммировать микроконтроллер. В результате мы видим, что светодиод стал мигать с частотой в 2 раза меньше, чем была раньше. Собственно, так и должно было произойти, поскольку мы уменьшили частоту тактирования таймера ровно в 2 раза 😉

Это все, конечно, хорошо, но вообще неплохо было бы задействовать внешний кварцевый резонатор, установленный на плате Discovery. Но в окне настроек частот он неактивен. Поэтому идем в окно Pinout и включаем внешний источник тактирования!

Enable HSE

Cube сразу же отметил выводы микроконтроллера, к которым подключается внешний кварц. Сделано это для того, чтобы пользователь знал, что эти выводы он не сможет задействовать для каких-нибудь других целей.

Переходим снова в окно конфигурации частот и настраиваем использование внешнего генератора так, чтобы частота таймера у нас оказалась равной 48 МГц. Как это сделать можно увидеть на следующем рисунке:

Внешний генератор

Поскольку на плате Discovery установлен кварц на 8 МГц, то именно это значение необходимо указать в специальном поле Input frequency. Ну а дальше все легко настраивается просто по схеме, тут разработчики Cube постарались и сделали интерфейс действительно интуитивно понятным )

Итак, поскольку частота тактирования шины, а соответственно и нашего таймера стала равной 48 МГц, то давайте в настройках таймера  изменим значение предделителя с 16000 на 48000. Это нужно для того, чтобы светодиод на плате снова стал мигать 1 раз в секунду (прерывание по переполнению таймера каждые 500 мс).

После изменения всех настроек генерируем проект для IAR, компилируем и загружаем новую прошивку в микроконтроллер. Светодиод на плате мигает точно с той частотой, с какой и должен  😉

 На это заканчиваем с настройкой частот, но не заканчиваем с изучением STM32Cube, так что до скорых встреч!

Понравилась статья? Поделись с друзьями!

STM32Cube. RCC. Настройки тактирования.: 20 комментариев
  1. Подскажите, в чем может быть загвоздка. Сделал как у вас, тактирование таймера 48, предделитель поставил 48000, считать до 499. Прошилось, мигает, но скорость мигания явно медленнее, даже векундомер включил на десять сек 4 раза мигает, все перепроверил:
    htim3.Instance = TIM3;
    htim3.Init.Prescaler = 48000;
    htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim3.Init.Period = 499;
    htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

  2. Да тут было это значение. Я нашел ошибку у меня в main pll стояли делители другие, но на SYSCLK ,было 48, поэтому не заметил сразу. Благодарю Вас. Жду следующих уроков

  3. А что за частота (To Cortex System timer) и (FCLK Cortex clock) и для чего используется? Хотелось бы хоть какое то иметь представление о них.

  4. А внешние генераторы я так понял опциональные, зачем они вообще нужны/используются ибо с помощью делителя мы можем получить нужную частоту с внутреннего генератора?

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

  6. Почему никто не задает вопрос как сделать доступным внешний кварц? У меня вот он серым подсвечен..оказывается его в RCC нужно включить предварительно

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

    • А нет, прошу прощения. Здесь же подробно описано в статье как включить внешний кварц! Вы видимо только до середины дочитали …=\

  7. Доброго всем дня!
    А подскажите пожалуйста, кто знает, возможно ли изменение частоты тактирования в процессе работы контроллера.
    Использую MSI источник. Необходимо переключаться между 1МГц и 65кГц.

  8. Добрый день! Подскажите почему в Cube указана входная частота для HSI 16 MHz. Ведь на плате установлен кварц на 8 MHz.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *