Top.Mail.Ru

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

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

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

Пример настройки тактирования в STM32CubeMx

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

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

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

Частоты тактирования шин

Открываем полученный проект и ищем там в файле 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_DIV4;

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

Это все, конечно, хорошо, но вообще неплохо было бы задействовать внешний кварцевый резонатор. Но в "Clock Configuration" на данный момент этот вариант (HSE) неактивен:

Clock configuration, HSE

Связано это с тем, что предварительно нужно активировать внешний источник тактирования на вкладке "Pinout & Configuration":

Активация HSE

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

Выводы для HSE

Переходим снова на вкладку конфигурации частот и настраиваем