STM32f030 а также контроллеры серии STM32F031 настройка тактирования(Clocks) с помощью SPL.
Также моё описание и примеры должны подойти для всей серии контроллеров STM32F0xx(xx это любые цифры в модели).
Ниже схема тактирования и возможные варианты это: оранжевая линия тактирование по умолчанию от HSI напрямую, красная от HSI через делитель на 2 и через множитель, зеленная напрямую от внешнего осциллятора HSE, светло зелёная от HSE через делитель к множителю.
Первый пример, красная линия настройка контроллера тактирование от внутреннего осциллятора HSI, через делитель на 2 и множитель на 12 для получения частоты 48MHz.
#include "stm32f0xx.h"
int main(){
/*Сброс системы тактирования*/
RCC_DeInit();
/*Включаем и настраиваем буфер бодгрузки для процессора*/
FLASH_PrefetchBufferCmd( ENABLE);
FLASH_SetLatency( FLASH_Latency_1);
/*Подклчаем множитель тактовой частоты к делителю на два от HSI, настраиваем множитель как 12*/
RCC_PLLConfig( RCC_PLLSource_HSI_Div2, RCC_PLLMul_12);//8MHz=4*12=48MHz.
RCC_PLLCmd( ENABLE);//Доступ к PLL разрешен.
while( RCC_GetFlagStatus( RCC_FLAG_PLLRDY)== RESET);//Ждем пока PLL будет готов.
RCC_SYSCLKConfig( RCC_SYSCLKSource_PLLCLK); //Выбираем PLL как источник частоты.
/*Ждём когда система тактирования заработает устойчиво на частоте 48MHz и станет источником*/
while( RCC_GetSYSCLKSource()!= 0x08);
while(1){}
return 0;
}
Возможны следующие варианты множителя RCC_PLLMul_2 до RCC_PLLMul_16, выше RCC_PLLMul_12 здесь не рекомендуется применять так как предельная частота работы контроллера 48MHz.
Теперь настроим тактирование от внешнего осциллятора, частота которого может быть от 4 до 32MHz. Кварцевый резонатор подключается к выводам OSC_OUT и OSC_IN. Я использую кварцевый резонатор 16MHz по этому функции
FLASH_PrefetchBufferCmd( ENABLE);
FLASH_SetLatency( FLASH_Latency_1);
не использую.
#include "stm32f0xx.h"
int main(){
RCC_DeInit();
/*Включаем внешний кварцевый резонатор*/
RCC_HSEConfig( RCC_HSE_ON);
/*Ждём стабилизации резонатора*/
while( RCC_GetFlagStatus( RCC_FLAG_HSERDY)== RESET);
/*Переключаем тактирование на внешний резонатор*/
RCC_SYSCLKConfig( RCC_SYSCLKSource_HSE);
/*Ждем стабилизации и переключения*/
while( RCC_GetSYSCLKSource()!= 0x04);
/*Отключаем внутренний осциллятор HSI*/
RCC_HSICmd( DISABLE);
while(1){}
return 0;
}
Настройка тактирования от внешнего осциллятора HSE через делитель и множитель, светло зелёная линия. У меня используется кварцевый резонатор на 16MHz и от этой частоты буду вести расчёты.
#include "stm32f0xx.h"
int main(){
RCC_DeInit();
RCC_HSEConfig( RCC_HSE_ON);
while( RCC_GetFlagStatus( RCC_FLAG_HSERDY)== RESET);
/*Частота будет больше 24MHz поэтому включаем буфер подгрузки*/
FLASH_PrefetchBufferCmd( ENABLE);
FLASH_SetLatency( FLASH_Latency_1);
/*Устанавливаем делитель от HSE равным 1*/
RCC_PREDIV1Config(RCC_PREDIV1_Div1);
/*Подключаем множитель к делителю HSE*/
RCC_PLLConfig( RCC_PLLSource_HSE, RCC_PLLMul_2);//SYSCLK=16MHz/1*2=32MHz.
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);
while(1){}
return 0;
}
Функция RCC_PREDIV1Config(RCC_PREDIV1_Div1); может принять значение делителя от RCC_PREDIV1_Div1 до RCC_PREDIV1_Div16.
Функция RCC_PLLConfig( RCC_PLLSource_HSE, RCC_PLLMul_2); может принять множитель от RCC_PLLMul_2 до RCC_PLLMul_16.
Настраиваем осторожно, что бы системная частота не превышала 48MHz.
И про эти две функции.
FLASH_PrefetchBufferCmd( ENABLE);
FLASH_SetLatency( FLASH_Latency_1);
Функция FLASH_PrefetchBufferCmd( ENABLE); используются для включения буфера подгрузки, что бы ускорить выполнения кода программы, ядро контроллера выполняет код программы и одновременно подгружает другой. Если не включать этот буфер то ядро будет загружать следующий код программы только после выполнения предыдущего, теряя на это время.
FLASH_SetLatency( FLASH_Latency_1); эта функция обеспечивает тактирование буфера частотой не превышающей 24MHz, на большой частоте эта система может работать не стабильно. Значение FLASH_Latency_1 делит системную частоту на два или пропуск каждого второго такта системы, FLASH_Latency_0 частота будет равняться системной.
На последок про такой вывод контроллера под названием MCO, который применяется для тактирования внешних устройств, ниже на рисунке он показан.
Так он показан в datasheet контроллера.
#include "stm32f0xx.h"
int main(){
RCC_DeInit();
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_0);
GPIO_InitTypeDef PORTA_8_MCO;
PORTA_8_MCO.GPIO_Mode = GPIO_Mode_AF;
PORTA_8_MCO.GPIO_OType = GPIO_OType_PP;
PORTA_8_MCO.GPIO_Pin = GPIO_Pin_8;
PORTA_8_MCO.GPIO_PuPd = GPIO_PuPd_NOPULL;
PORTA_8_MCO.GPIO_Speed = GPIO_Speed_Level_3;
GPIO_Init(GPIOA, &PORTA_8_MCO);
RCC_MCOConfig( RCC_MCOSource_SYSCLK, RCC_MCOPrescaler_1);
while(1){}
return 0;
}
RCC_MCOConfig( RCC_MCOSource, RCC_MCOPrescaler) функция подключает вывод к источнику тактирования, параметр RCC_MCOPrescaler на некоторые контроллеры не влияет просто ставьте RCC_MCOPrescaler_1, как и в моём контроллере.
- RCC_MCOSource
- источник сигнала, варианты:
- RCC_MCOSource_NoClock-не тактируется;
- RCC_MCOSource_HSI14-от внутреннего генератора 14MHz;
- RCC_MCOSource_LSI-от внутреннего, низкочастотного генератора;
- RCC_MCOSource_LSE-от внешнего, низкочастотного или часового кварцевого генератора;
- RCC_MCOSource_SYSCLK-от системной шины;
- RCC_MCOSource_HSI-от внутреннего, высокочастотного генератора;
- RCC_MCOSource_HSE-от внешнего, высокочастотного генератора;
- RCC_MCOSource_PLLCLK_Div2-от множителя но частота будет поделена пополам;
- RCC_MCOSource_HSI48-от внутреннего, высокочастотного генератора для тактирования USB, имеется у моделей STM32F04x, STM32F07x и STM32F09x.
- RCC_MCOSource_PLLCLK-от системного множителя, имеется у моделей STM32F04x, STM32F07x и STM32F09x.
Последний пример включение HSI14 генератора и подача с него сигнала на MCO.
#include "stm32f0xx.h"
int main(){
RCC_DeInit();
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_0);
GPIO_InitTypeDef PORTA_8_MCO;
PORTA_8_MCO.GPIO_Mode = GPIO_Mode_AF;
PORTA_8_MCO.GPIO_OType = GPIO_OType_PP;
PORTA_8_MCO.GPIO_Pin = GPIO_Pin_8;
PORTA_8_MCO.GPIO_PuPd = GPIO_PuPd_NOPULL;
PORTA_8_MCO.GPIO_Speed = GPIO_Speed_Level_3;
GPIO_Init(GPIOA, &PORTA_8_MCO);
/*Включаем HSI14*/
RCC_HSI14Cmd(ENABLE);
/*Подключаем его к MCO*/
RCC_MCOConfig( RCC_MCOSource_HSI14, RCC_MCOPrescaler_1);
while(1){}
return 0;
}