Первоначально плата STM32F103 работает от внутреннего генератора на частоте 48 мГц.
Сделал настройку по ссылке но ничего не поменялось на двух разных платах. Почему может не работать?
https://dimoon.ru/obuchalka/stm32f1/uroki-stm32f103-chast-4-nastroyka-rcc.html?ysclid=m77p7n5frs371276003
Код.
//#include <stm32f1xx.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd (PA9, PA8, PB15, PB14, PB13, PB12); //(RS,E,D4,D5,D6,D7)
uint32_t Tay_ind = 1000000;
uint32_t time_new_ind,time_old_ind,time_del_ind;
//-------------------------------------------------------------------------//
int ClockInit(void)
{
__IO int StartUpCounter;
////////////////////////////////////////////////////////////
// Запускаем кварцевый генератор
////////////////////////////////////////////////////////////
RCC->CR |= RCC_CR_HSEON; // Запускаем генератор HSE
// Ждем успешного запуска или окончания тайм-аута
for(StartUpCounter = 0; ; StartUpCounter++)
{
// Если успешно запустилось, то выходим из цикла
if(RCC->CR & RCC_CR_HSERDY)
break;
// Если не запустилось, то отключаем все, что включили и возвращаем ошибку
if(StartUpCounter > 0x1000)
{
RCC->CR &= ~RCC_CR_HSEON; // Останавливаем HSE
return 1;
}
}
////////////////////////////////////////////////////////////
// Настраиваем и запускаем PLL
////////////////////////////////////////////////////////////
// Настраиваем PLL
RCC->CFGR |= RCC_CFGR_PLLMULL2 // PLL множитель равен 9
| RCC_CFGR_PLLSRC; // Тактирование PLL от HSE
RCC->CR |= RCC_CR_PLLON; // Запускаем PLL
// Ждем успешного запуска или окончания тайм-аута
for(StartUpCounter = 0; ; StartUpCounter++)
{
// Если успешно запустилось, то выходим из цикла
if(RCC->CR & RCC_CR_PLLRDY)
break;
// Если по каким-то причинам не запустился PLL, то отключаем все, что включили и возвращаем ошибку
if(StartUpCounter > 0x1000)
{
RCC->CR &= ~RCC_CR_HSEON; // Останавливаем HSE
RCC->CR &= ~RCC_CR_PLLON; // Останавливаем PLL
return 2;
}
}
////////////////////////////////////////////////////////////
// Настраиваем FLASH и делители
////////////////////////////////////////////////////////////
// Устанавливаем 2 цикла ожидания для Flash
// так как частота ядра у нас будет 48 MHz < SYSCLK <= 72 MHz
FLASH->ACR |= FLASH_ACR_LATENCY_2;
// Делители
RCC->CFGR |= RCC_CFGR_PPRE2_DIV1 // Делитель шины APB2 отключен
| RCC_CFGR_PPRE1_DIV2 // Делитель шины APB1 равен 2
| RCC_CFGR_HPRE_DIV1; // Делитель AHB отключен
RCC->CFGR |= RCC_CFGR_SW_PLL; // Переключаемся на работу от PLL
// Ждем, пока переключимся
while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL)
{
}
// После того, как переключились на внешний источник тактирования
// отключаем внутренний RC-генератор для экономии энергии
RCC->CR &= ~RCC_CR_HSION;
// Настройка и переключение системы на внешний кварцевый генератор и PLL завершилось успехом.
// Выходим
return 0;
}
//-------------------------------------------------------------------------//
void setup()
{
//-------------------------------------------------------------------------//
// Инициализация тактирования
if(ClockInit() != 0) {
// Обработка ошибки инициализации тактирования
while(1);
}
//-------------------------------------------------------------------------//
lcd.begin(20, 4);
//-------------------------------------------------------------------------//
// Включаем тактирование TIM2
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
// Настройка TIM2 для счета миллисекунд
TIM2->CR1 = 0; // Остановка таймера
TIM2->PSC = 47999; // Предделитель 48000 (48 МГц / 48000 = 1 кГц)
TIM2->ARR = 0xFFFF; // Автоперезагрузка на максимум (16 бит)
TIM2->CCER &= ~TIM_CCER_CC1P; // Полярность: считаем по фронту
TIM2->EGR = 1; // Обновление регистров
TIM2->CR1 |= (1 << 0); // Запуск TIM2
//-------------------------------------------------------------------------//
}
void loop()
{
time_new_ind= micros();
time_del_ind=time_new_ind-time_old_ind;
if (time_del_ind>=Tay_ind)
{
//-----------------------------------------------------------------------//
uint32_t milliseconds = TIM2->CNT;
uint32_t sysclk_freq = HAL_RCC_GetSysClockFreq();
//-----------------------------------------------------------------------//
lcd.clear();
lcd.setCursor(0, 0);lcd.print("T= ");lcd.print(millis());
lcd.setCursor(0, 1);lcd.print("N= ");lcd.print(milliseconds);
lcd.setCursor(0, 2);lcd.print("F= ");lcd.print(sysclk_freq);
time_old_ind=time_new_ind;
}
}
На какой частоте с таким кодом работают платы ?
В 31 строке надо смотреть что в итоге за множитель получается …RCC_CFGR_PLLMULL9 нужен скорее всего для кварца 8 МГц. Вы как то странно читали описание по ссылке и привели свой вариант кода !!!
Если первая строка = комментарий - откуда берутся все константы ??? Вы уверены что это вообще компилируется и прошивается ???
Плата такая и что самое интересное прошивается и не дает ошибок. На меня это не похоже.
Плата работает на частоте 48 мГц. В 86 строке настраиваю предделитель. Время с таймера и время миллисекунд отображаются синхронно.
https://aliexpress.ru/item/1005004918334754.html?sku_id=12000034303875973&spm=a2g2w.stores.seller_list.3.2ee647dcIl7d7x
Кварц какой на плате ?
И тут в процессе возник еще вопрос - на какой частоте вы хотите запустить микроконтроллер ?
если это действительно плата от Weact, то они только 8мГц.
Ну для начала хотел бы запустить на 72 мгц. Но пока получилось только запустить на 8 мГц от внутреннего генератора. Строки с 6 по 17.
//работает на частоте 8 мгц от внутреннего генератора
#include <LiquidCrystal.h>
LiquidCrystal lcd (PA9, PA8, PB15, PB14, PB13, PB12); //(RS,E,D4,D5,D6,D7)
uint32_t Tay_ind = 1000000;
uint32_t time_new_ind,time_old_ind,time_del_ind;
//-------------------------------------------------------------------------//
void SystemClock_Config(void) {
// Включение HSI (внутренний генератор 8 МГц)
RCC->CR |= RCC_CR_HSION; // Включение HSI
while (!(RCC->CR & RCC_CR_HSIRDY)); // Ожидание готовности HSI
// Переключение на HSI как источник тактирования
RCC->CFGR &= ~RCC_CFGR_SW; // Сброс источника тактирования
RCC->CFGR |= RCC_CFGR_SW_HSI; // Использование HSI как источника тактирования
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI); // Ожидание переключения на HSI
}
//-------------------------------------------------------------------------//
void setup()
{
//-------------------------------------------------------------------------//
SystemClock_Config(); // Настройка тактирования
//-------------------------------------------------------------------------//
lcd.begin(20, 4);
//-------------------------------------------------------------------------//
// Включаем тактирование TIM2
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
// Настройка TIM2 для счета миллисекунд
TIM2->CR1 = 0; // Остановка таймера
TIM2->PSC = 7999; // Предделитель 48000 (8 МГц / 8000 = 1 кГц)
TIM2->ARR = 0xFFFF; // Автоперезагрузка на максимум (16 бит)
TIM2->CCER &= ~TIM_CCER_CC1P; // Полярность: считаем по фронту
TIM2->EGR = 1; // Обновление регистров
TIM2->CR1 |= (1 << 0); // Запуск TIM2
//-------------------------------------------------------------------------//
}
void loop()
{
time_new_ind= micros();
time_del_ind=time_new_ind-time_old_ind;
if (time_del_ind>=Tay_ind)
{
//-----------------------------------------------------------------------//
uint32_t milliseconds = TIM2->CNT;
uint32_t sysclk_freq = HAL_RCC_GetSysClockFreq();
//-----------------------------------------------------------------------//
lcd.clear();
lcd.setCursor(0, 0);lcd.print("T= ");lcd.print(millis());
lcd.setCursor(0, 1);lcd.print("N= ");lcd.print(milliseconds);
lcd.setCursor(0, 2);lcd.print("F= ");lcd.print(sysclk_freq);
time_old_ind=time_new_ind;
}
}
Запустил в работу от внешнего генератора на 8 мгц.
//-------------------------------------------------------------------------//
void SystemClock_Config(void) {
// Включение HSE (внешний кварцевый генератор 8 МГц)
RCC->CR |= RCC_CR_HSEON; // Включение HSE
while (!(RCC->CR & RCC_CR_HSERDY)); // Ожидание готовности HSE
// Настройка FLASH (для работы на частоте HSE)
FLASH->ACR |= FLASH_ACR_PRFTBE; // Включение предварительной выборки
FLASH->ACR &= ~FLASH_ACR_LATENCY; // Сброс задержки
FLASH->ACR |= FLASH_ACR_LATENCY_0; // Установка задержки в 0 тактов (для частот до 24 МГц)
// Переключение на HSE как источник тактирования
RCC->CFGR &= ~RCC_CFGR_SW; // Сброс источника тактирования
RCC->CFGR |= RCC_CFGR_SW_HSE; // Использование HSE как источника тактирования
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSE); // Ожидание переключения на HSE
}
//-------------------------------------------------------------------------//
Добавил настройку шин.
void SystemClock_Config(void) {
// Включение HSE (внешний кварцевый генератор 8 МГц)
RCC->CR |= RCC_CR_HSEON; // Включение HSE
while (!(RCC->CR & RCC_CR_HSERDY)); // Ожидание готовности HSE
// Настройка FLASH (для работы на частоте HSE)
FLASH->ACR |= FLASH_ACR_PRFTBE; // Включение предварительной выборки
FLASH->ACR &= ~FLASH_ACR_LATENCY; // Сброс задержки
FLASH->ACR |= FLASH_ACR_LATENCY_0; // Установка задержки в 0 тактов (для частот до 24 МГц)
// Настройка делителей шин
RCC->CFGR &= ~(RCC_CFGR_HPRE | RCC_CFGR_PPRE1 | RCC_CFGR_PPRE2); // Сброс делителей
RCC->CFGR |= RCC_CFGR_HPRE_DIV1; // AHB без деления (частота = HSE = 8 МГц)
RCC->CFGR |= RCC_CFGR_PPRE1_DIV1; // APB1 без деления (частота = HSE = 8 МГц)
RCC->CFGR |= RCC_CFGR_PPRE2_DIV1; // APB2 без деления (частота = HSE = 8 МГц)
// Переключение на HSE как источник тактирования
RCC->CFGR &= ~RCC_CFGR_SW; // Сброс источника тактирования
RCC->CFGR |= RCC_CFGR_SW_HSE; // Использование HSE как источника тактирования
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSE); // Ожидание переключения на HSE
}
пример функции инициализации RCC для STM32F103C8T6 с использованием внешнего кварца 8 МГц для достижения тактовой частоты 72 МГц:
#include "stm32f10x.h"
void SystemClock_Config(void) {
// 1. Включение HSE и ожидание готовности
RCC->CR |= RCC_CR_HSEON; // Включить HSE
while(!(RCC->CR & RCC_CR_HSERDY)); // Ждем стабилизации генератора
// 2. Настройка задержки Flash-памяти
FLASH->ACR |= FLASH_ACR_LATENCY_2; // Два цикла ожидания (для 48-72 МГц)
FLASH->ACR |= FLASH_ACR_PRFTBE; // Включить предварительную выборку
// 3. Настройка делителей шин
RCC->CFGR |= RCC_CFGR_HPRE_DIV1; // AHB = 72 MHz
RCC->CFGR |= RCC_CFGR_PPRE1_DIV2; // APB1 = 36 MHz
RCC->CFGR |= RCC_CFGR_PPRE2_DIV1; // APB2 = 72 MHz
// 4. Конфигурация PLL (8MHz * 9 = 72MHz)
RCC->CFGR |= RCC_CFGR_PLLSRC_HSE; // Источник PLL - HSE
RCC->CFGR |= RCC_CFGR_PLLMULL9; // Множитель PLL x9
// 5. Включение PLL и ожидание готовности
RCC->CR |= RCC_CR_PLLON; // Запуск PLL
while(!(RCC->CR & RCC_CR_PLLRDY)); // Ждем готовности PLL
// 6. Переключение на PLL как источник системного такта
RCC->CFGR |= RCC_CFGR_SW_PLL; // Выбираем PLL как системный источник
while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); // Ждем переключения
}
Вопрос решен.При попытке запрограммировать PLL умножение на 9 stm32f103 программируется но с коэффициентом 12. Поскольку процессор не может работать на частоте 96 мГц. Его частота сбрасывается и он работает на частоте 48 мГц от внутреннего генератора.