PROGCONT.RU

Форма входа







Регистрация Вход/

Пример Пример Пример


STM32F Clock (тактирование).

 Давайте посмотрим на схеме(STM32F105RBT6) что это такое и как она устроена.

нет

 На схеме мы видим, что тактирование CPU и основной периферии возможно только через шину SYSCLK, та подключается к одному из трех источников HSI, HSE и PLLCLK(множитель). По умолчанию (сброса или включения) SYSCLK подключена к HSI частота которого 8Мгерц. Пере подключать SYSCLK на другой источник, а так же настройку множителей, делителей нужно выполнять в самом начале вашей программы, перед настройкой периферии, потому что если вы, например, выполните сначала настройку UART а потом переключите на внешний генератор то компилятор не правильно рассчитает параметры для настройки скорости соединения.

Все функции для работы с тактированием контроллера и периферии находятся в файле stm32f10x_rcc.h.

 Функция для выбора источника:

RCC_SYSCLKConfig( RCC_SYSCLKSource);

RCC_SYSCLKSource-источник.
   RCC_SYSCLKSource_HSI-внутренний генератор.
   RCC_SYSCLKSource_HSE-внешний генератор.
   RCC_SYSCLKSource_PLLCLK-множитель.

HSI (High Speed Internal)-Встроенный высокочастотный или главный генератор.

 Разработчики что бы упростить нам жизнь встроили в контролер HSI генератор 8Мгерц, SYSCLK всегда начинает тактироваться от него.
 Если вам необходимо вернутся обратно на HSI и сбросить все настройки(RCC), выполните функцию:

RCC_DeInit();// Функция возвращает к начальным настройкам.

 Возвращение со своими настройками выполняется в следующем порядке:

RCC_HSICmd(ENABLE);// Включаем HSI
RCC_SYSCLKConfig( RCC_SYSCLKSource_HSI);//Переключаем шину SYSCLK на HSI
while(RCC_GetSYSCLKSource() != 0x00); // Ждем пока HSI не станет источником
RCC_HSEConfig(RCC_HSE_OFF);// Выключаем HSE

HSE (High Speed Extrenal)-Внешний высокочастотный или кварцевый генератор.

 Схема подключения.

нет

 Подключить SYSCLK к внешнему кварцу можно следующим набором функций, частота кварца должна быть 3-25Мгерц:

RCC_HSEConfig(RCC_HSE_ON);// Включаем HSE
RCC_WaitForHSEStartUp();// Ждем стабилизации
RCC_SYSCLKConfig( RCC_SYSCLKSource_HSE);// Переключаем SYSCLK на HSE
while(RCC_GetSYSCLKSource() != 0x04); // Ждем пока HSE не станет источником
RCC_HSICmd(DISABLE);// Выключаем HSI

 Если мы хотим тактировать другим генератором(частота источника не должна превышать 25Мгерц), например другим контролером то должны использовать следующую схему и набор функций:

нет RCC_HSEConfig(RCC_HSE_Bypass);// Подключаем к внешнему источнику
RCC_SYSCLKConfig( RCC_SYSCLKSource_HSE);//Переключаем SYSCLK на HSE
while(RCC_GetSYSCLKSource() != 0x04); // Ждем пока HSE не станет источником
RCC_HSICmd(DISABLE);// Выключаем HSI

 У SYSCLK есть защита от остановки или поломки источника HSE называется CSS, о ней читайте ниже.



PLLCLK-Множитель частоты.

 Основной свой упор будем делать на PLLCLK так как только через него, реально получить частоту более 25Мгерц и поэтому он станет основным источником тактов для наших проектов.
 PLLCLK не является тактовым генератором, это всего-навсего множитель, поэтому его самого надо к чему-то подключить, выбор небольшой это к HSI через делитель на 2 или к HSE через PREDIV1(делитель1) и с возможностью подключить дополнительный множитель. Все манипуляции с PLLCLK возможны, только когда он отключён.

 Выбор между HSI/2 или PREDIV1 выполняется функцией:

RCC_PLLConfig( RCC_PLLSource, RCC_PLLMul);

RCC_PLLSource- Источники тактирования.
   RCC_PLLSource_HSI_Div2-к HSI через делитель на 2
   RCC_PLLSource_PREDIV1-к HSE через PREDIV1
RCC_PLLMul-Коэффициент множителя(зависит от контролера, у STM32F105)
   RCC_PLLMul_4-на 4
   RCC_PLLMul_5
   RCC_PLLMul_6
   RCC_PLLMul_7
   RCC_PLLMul_8
   RCC_PLLMul_9
   RCC_PLLMul_6_5-на 6.5

 Обращаю ваше внимание на подводные камни!

 Предположим, вы захотели настроить контролер на работу 72Мгерц, подключили все как на схеме, выставили делители, множители прошили контролер, а он бац завис, все проверили и не понимаете почему, а фишка заключается во Flash memory, так как она тактируется от SYSCLK и максимальная частота ее должна быть не больше 30Мгерц, хотя у меня работала на 56Мгерц(кварц 8Мгерц плюс множитель 7 на 8 уже зависал).
 Для предотвращения такой ситуации вы должны будете применить следующую функцию, ниже пример с возможными вариантами и дополнительная функция для быстроты работы CPU.

// Наша функция, пропускает 2 такта, частота FLASH будет 72/3=24Мгерц
FLASH_SetLatency(FLASH_Latency_2);

 Для всех частот(SYSCLK) варианты:
   FLASH_Latency_0- если 0Мгерц < SYSCLK ≤ 24Мгерц
   FLASH_Latency_1- если 24Мгерц < SYSCLK ≤ 48Мгерц
   FLASH_Latency_2- если 48Мгерц < SYSCLK ≤ 72Мгерц

// Включаем буфер для быстроты CPU, на всякий случай.
FLASH_PrefetchBufferCmd( FLASH_PrefetchBuffer_Enable);

 HSI/2-пример подключения.

RCC_DeInit(); // Сброс RCC
RCC_HCLKConfig(RCC_SYSCLK_Div1);
// Общий делитель(AHB Prescaler) периферии равен 1, на всякий случай
RCC_PCLK2Config(RCC_HCLK_Div1);// APB2 делитель равен 1, на всякий случай
RCC_PCLK1Config(RCC_HCLK_Div1);// APB1 делитель равен 1, на всякий случай
FLASH_SetLatency(FLASH_Latency_1);// Пропускаем один такт, для Flash
FLASH_PrefetchBufferCmd( FLASH_PrefetchBuffer_Enable);// Доступен предварительный буфер
RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_9);// SYSCLK=4Мгерц*9=36Мгерц
RCC_PLLCmd(ENABLE); // Доступ к PLL разрешен
while( RCC_GetFlagStatus( RCC_FLAG_PLLRDY) == RESET);// Ждем пока PLL не будет готов
RCC_SYSCLKConfig( RCC_SYSCLKSource_PLLCLK); // Выбираем PLL как источник частоты
while(RCC_GetSYSCLKSource() != 0x08);// Ждем пока PLL не станет источником
RCC_HSEConfig(RCC_HSE_OFF);// Выключаем HSE

 HSE через PREDIV1-тут тоже все не однозначно, у PREDIV1 есть два пути(зависит от контролера, у STM32F105) первый напрямую к HSE или второй через PLL2CLK(второй множитель).

 Выбор пути через функцию:

RCC_PREDIV1Config( RCC_PREDIV1_Source, RCC_PREDIV1_Div);

 RCC_PREDIV1_Source-Источник.
   RCC_PREDIV1_Source_HSE-напрямую к HSE.
   RCC_PREDIV1_Source_PLL2-через PLL2CLK к HSE.
 RCC_PREDIV1_Div-Коэффициент делителя.
От RCC_PREDIV1_Div1 до RCC_PREDIV1_Div16.


 Пример подключения PREDIV1 напрямую к HSE(HSE=8Мгерц).

RCC_HSEConfig(RCC_HSE_ON);//Включаем HSE
RCC_WaitForHSEStartUp();//Ждем пока HSE будет готов
RCC_HCLKConfig(RCC_SYSCLK_Div1);
// Общий делитель(AHB Prescaler) периферии равен 1, на всякий случай
RCC_PCLK2Config( RCC_HCLK_Div1);//APB2 делитель равен 1, на всякий случай
RCC_PCLK1Config( RCC_HCLK_Div2);//APB1 делитель равен 2, максимальная частота APB1 36Мгерц
FLASH_SetLatency(FLASH_Latency_2);//Пропускаем два такта, для Flash
FLASH_PrefetchBufferCmd( FLASH_PrefetchBuffer_Enable);// Доступен предварительный буфер
RCC_PREDIV1Config( RCC_PREDIV1_Source_HSE, RCC_PREDIV1_Div1);//HSE источник, делитель 1
RCC_PLLConfig( RCC_PLLSource_PREDIV1, RCC_PLLMul_9); //SYSCLK=8Мгерц*9=72Мгерц
RCC_PLLCmd(ENABLE);//Доступ к PLL разрешен
while(RCC_GetFlagStatus( RCC_FLAG_PLLRDY) == RESET);//Ждем пока PLL не будет готов
RCC_SYSCLKConfig( RCC_SYSCLKSource_PLLCLK); // Выбираем PLL как источник частоты
while(RCC_GetSYSCLKSource() != 0x08);// Ждем пока PLL не станет источником
RCC_HSICmd(DISABLE);// Выключаем HSI

Подробно описывать подключение PREDIV1 через PLL2CLK я не буду так как вы наверно вряд ли будете использовать из за постоянного множителя равного 64. Единственное покажу функций которые нужно заменить и добавить в примере выше, если будете использовать такое тактирование.

RCC_PREDIV2Config( RCC_PREDIV2_Div2);//Другие варианты делителя 4,6,8,10,12,14,16
RCC_PLL2Config(RCC_PLL2Mul_8);//Другие варианты множителя 9,10,11,12,13,14,16,20
RCC_PLL2Cmd(ENABLE);
RCC_PREDIV1Config( RCC_PREDIV1_Source_PLL2, RCC_PREDIV1_Div1);// PLL2CLK источник, делитель 1

CSS-Защита от выхода из строя HSE генератора.

Данная защита предназначена для предотвращения зависания контролера если произошла остановка HSE если CSS была включена, противном случае просто зависнем. Сначала включаем CSS, потом переходим на тактирование от HSE, это обязательно, функция ниже.

RCC_ClockSecuritySystemCmd(ENABLE);

Отследить отключения HSE можно проверкой бита RCC_IT_CSS или установкой прерывания.

 Периферия-после включения или сброса вся периферия будет отключена от тактирования и не будет работать.
Подключить можно следующими функциями(для STM32F105RB):
RCC_AHBPeriphClockCmd( RCC_AHBPeriph, ENABLE);
RCC_AHBPeriph-возможные варианты ниже.
   RCC_AHBPeriph_DMA1
   RCC_AHBPeriph_DMA2
   RCC_AHBPeriph_SRAM
   RCC_AHBPeriph_FLITF
   RCC_AHBPeriph_CRC
   RCC_AHBPeriph_FSMC
   RCC_AHBPeriph_SDIO
   RCC_AHBPeriph_OTG_FS
   RCC_AHBPeriph_ETH_MAC
   RCC_AHBPeriph_ETH_MAC_Tx
   RCC_AHBPeriph_ETH_MAC_Rx
RCC_APB2PeriphClockCmd( RCC_APB2Periph, ENABLE);
RCC_APB2Periph-возможные варианты ниже.
   RCC_APB2Periph_AFIO
   RCC_APB2Periph_GPIOA
   RCC_APB2Periph_GPIOB
   RCC_APB2Periph_GPIOC
   RCC_APB2Periph_GPIOD
   RCC_APB2Periph_GPIOE
   RCC_APB2Periph_GPIOF
   RCC_APB2Periph_GPIOG
   RCC_APB2Periph_ADC1
   RCC_APB2Periph_ADC2
   RCC_APB2Periph_TIM1
   RCC_APB2Periph_SPI1
   RCC_APB2Periph_TIM8
   RCC_APB2Periph_USART1
   RCC_APB2Periph_ADC3
   RCC_APB2Periph_TIM15
   RCC_APB2Periph_TIM16
   RCC_APB2Periph_TIM17
   RCC_APB2Periph_TIM9
   RCC_APB2Periph_TIM10
   RCC_APB2Periph_TIM11
RCC_APB1PeriphClockCmd( RCC_APB1Periph, ENABLE);
RCC_APB1Periph-возможные варианты ниже.
   RCC_APB1Periph_TIM2
   RCC_APB1Periph_TIM3
   RCC_APB1Periph_TIM4
   RCC_APB1Periph_TIM5
   RCC_APB1Periph_TIM6
   RCC_APB1Periph_TIM7
   RCC_APB1Periph_TIM12
   RCC_APB1Periph_TIM13
   RCC_APB1Periph_TIM14
   RCC_APB1Periph_WWDG
   RCC_APB1Periph_SPI2
   RCC_APB1Periph_SPI3
   RCC_APB1Periph_USART2
   RCC_APB1Periph_USART3
   RCC_APB1Periph_UART4
   RCC_APB1Periph_UART5
   RCC_APB1Periph_I2C1
   RCC_APB1Periph_I2C2
   RCC_APB1Periph_USB
   RCC_APB1Periph_CAN1
   RCC_APB1Periph_CAN2
   RCC_APB1Periph_BKP
   RCC_APB1Periph_PWR
   RCC_APB1Periph_DAC
   RCC_APB1Periph_CEC
Отключить от тактирования можно теме же функциями только в место ENABLE ставим DISABLE.


Комментариев нет  Только зарегистрированные пользователи могут оставлять комментарии!