/
sichern
/
didactic
Обзор
Документация
Войти
/
sichern
/
didactic
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/f373_SetClk.c
203 строки
15 KB
SChern
Исправление кодировки
20 июл 2026, 15:11
20 июл 2026, 15:11
ffcdcaa
Код
Авторство
О чём код?
/********************* * f373_SetClk.c * Файл инициализации системы тактирования микроконтроллера * Version: v1.0 * Created: 31.07.2025 * Author: SSS **********************/ #include "main.h" void SetSysClock(void) { FlagStatus HSEStatus = RESET; // флаг статуса HSE __IO uint32_t StartUpTimer; // таймер таймаута // Частота внешнего кварца F HSE=8.0 МГц /* последовательность запуска блоков, если мы хотим переключить систему с внутреннего RC-генератора на HSE через PLL, 1. Запустить генератор HSE 2. Настроить количество циклов ожидания FLASH, если системная частота SYSCLK болше 24 МГц (см.) 3. Настроить PLL 4. Запустить PLL 5. Настроить делители шин 6. Переключиться на работу от PLL 7. Включить Clock Security System */ RCC_Reset(); // Всё сбросили для работы от внутреннего RC-генератора // п.1 Запускаем генератор HSE RCC->CR |= RCC_CR_HSEON; // Bit 16 HSEON - установили в 1: HSE oscillator ON; // стабилизация генератора (ждём пока не закончится таймаут или не установится флаг RCC_CR_HSERDY for(StartUpTimer=0; ;StartUpTimer++) { // Если успешно запустилось, то выходим из цикла if (RCC->CR && RCC_CR_HSERDY) { HSEStatus = SET; // RCC_CR_HSERDY - External High Speed clock ready flag break; } // Если не запустился HSE, то возвращаем ошибку if(StartUpTimer > HSE_STARTUP_TIMEOUT) { HSEStatus = RESET; break; } } // end for if (HSEStatus == SET) // при успешном старте генератора { // п.2 Настраиваем PLL // Конфигурируем источник тактов для PLL. Регистр RCC_CFGR - Reset value: 0x0000 0000: // - Bit 16: PLLSRC=1 HSE/PREDIV (HSE без деления, т. к. Bit 17 PLLXTPRE=0) // - Bits 21:18 PLLMUL[3:0] = 9, к-т умножения PLL RCC->CFGR |= RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL9; // На выходе PLL имеем PLLCLK=8 МГц*9= 72 МГц // п.3 Запускаем PLL RCC->CR |= RCC_CR_PLLON; // Ожидаем, пока PLL выставит бит готовности while((RCC->CR & RCC_CR_PLLRDY)==0) {}// Ждем // п.4 Настраиваем количество циклов ожидания FLASH /* FLASH-память микроконтроллера, в которой хранится управляющая программа, может работать на максимальной частоте 24 МГц. Обмен данными с FLASH осуществляется через шину AHB (см. рис. 3). А если частота шины AHB выше 24 МГц, то необходимо ввести циклы ожидания обращений к этой памяти, примем, чем выше частота, тем больше этих циклов надо: - ноль циклов ожидания, если 0 < SYSCLK <= 24 MHz - один цикл ожидания, если 24 MHz< SYSCLK <= 48 MHz - два цикла ожидания, если 48 MHz< SYSCLK <= 72 MHz*/ // Устанавливаем 2 цикла ожидания для Flash, так как частота ядра у нас будет 48 MHz< SYSCLK <= 72 MHz FLASH->ACR |= FLASH_ACR_PRFTBE; // Включаем буфер предвыборки FLASH (по умолчанию уже включен) FLASH->ACR |= FLASH_ACR_LATENCY_1; // Конфигурируем Flash на 2 цикла ожидания, т.к. частота > 48 MHz // п.5 Настраиваем делители шин // Регистр RCC_CFGR - Reset value: 0x0000 0000: RCC->CFGR |= RCC_CFGR_HPRE_DIV1; // Биты 7:4 HPRE[3:0]=0 - Делитель шины AHB - HCLK=SYSCLK=72 МГц (MAX 72 MHz) процессорное ядро, память, DMA, GPIO RCC->CFGR |= RCC_CFGR_PPRE1_DIV2; // Биты 10:8 PPRE1[2:0]=b100 - Делитель шины APB1 - PCLK1=HCLK/2=36 МГц (MAX 36 MHz) USART2, USART3,таймеры TIM2..7-12..14, SPI2,3 RCC->CFGR |= RCC_CFGR_PPRE2_DIV1; // Биты 13:11 PPRE2[2:0]=0 - Делитель шины APB2 - PCLK2=HCLK=72 МГц (MAX 72 MHz) USART1, АЦП, USART1, TIM15..17, SPI1 RCC->CFGR &= ~RCC_CFGR_USBPRE; // Bit 22 USBPRE: предделитель USB = 0: деление на 1,5; 72/1,5=48 (USB clock д.б.=48 MHz); RCC->CFGR |= RCC_CFGR_SDADCPRE_DIV12; // Биты 31:27 SDPRE[4:0]=b10101 - Делитель шины SDADC - SYSCLK/12 = 6 МГц (MAX 6 MHz); // Если нужно тактировать АЦП - устанавливаем ADCPRE[1:0]: // 00: PCLK2 divided by 2 // 01: PCLK2 divided by 4 // 10: PCLK2 divided by 6 // 11: PCLK2 divided by 8 //RCC->CFGR |= RCC_CFGR_ADCPRE; // ADCPRE[1:0]=b10 - Делитель шины ADC - PCLK2/6=12 МГц (MAX 14 MHz) RCC->CFGR2 &= ~(RCC_CFGR2_PREDIV1); // Bits 3:0 [3:0] PREDIV = 0000: HSE -> PLL без деления // п.6 Выбираем источник для SYSCLK от PLL // RCC_CFGRSW[1:0]: // - 00: HSI selected as system clock // - 01: HSE selected as system clock // - 10: PLL selected as system clock // - 11: not allowed RCC->CFGR |= RCC_CFGR_SW_PLL; // Ждем, пока PLL выберется как источник системной частоты while((RCC->CFGR & RCC_CFGR_SWS)!= RCC_CFGR_SWS_PLL) { // Ждем } // п.7 Включаем Clock Security System RCC->CR |= RCC_CR_CSSON; // Clock Security System enable } // end при успешном старте генератора (HSEStatus == SET) } // end SetSysClock() // === RCC system reset === void RCC_Reset(void) { // Последовательность сброса: // 1. Включаем внутренний RC генератор // 2. Сбрасываем биты в регистре RCC_CFGR // 3. Отключаем PLL, CSS, HSE в регистре RCC_CR // 4. Отдельно отключаем HSE crystal oscillator bypass после выключения HSE // 5. Сбрасываем биты предделителей PLL в регистре RCC_CFGR после выключения PLL // 6. Сбрасываем биты предделителей ADC34, ADC12 и HSE->PLL в регистре RCC_CFGR2 // 7. Отключаем все прерывания и очищаем pending bits // 1. Включаем внутренний RC генератор RCC->CR |= RCC_CR_HSION; // 2. Сбрасываем биты SDADCPRE, MCO, ADCPRE, PPRE2, PPRE1, HPRE и SW биты в регистре RCC_CFGR // Биты для только для чтения и Reserv оставляем без изменения. // -- Регистр CFGR - Clock configuration register. Reset value: 0x0000 0000 Поля: // Bits 31:27 SDPRE[4:0]: предделитель SDADC = 00000: SYSCLK/2 // Bits 26:24 MCO[3:0]: подача тактового сигнала на MCO = 000: Функция отключена // Bit 23 Reserved = 1: Reset value - оставляем без изменения // Bit 22 USBPRE: предделитель USB (USB clock д.б.=48 MHz) = 0: деление на 1,5; = 1: без деления // Bits 21:18 PLLMUL[3:0]: коэффициент умножения PLL = 1111: x 2 (PLL д.б. выключен!) => 1111 // Bit 17 PLLXTPRE: Делитель частоты с HSE генератора перед подачей на PLL; = 1: деление на 2; = 0: без деления (PLL д.б. выключен!) => 1 // Bit 16 PLLSRC: Источник входной частоты PLL = 1: HSE/PREDIV (RCC_CFGR2); = 0: HSI/2 (PLL д.б. выключен!) => 1 // Bits 15:14 ADCPRE[1:0]: предделитель шины ADC = 00: PCLK/2 // Bits 13:11 PPRE2[2:0]: предделитель шины APB2 (high speed) = 000: HCLK без деления // Bits 10:8 PPRE1[2:0]: предделитель шины APB1 (low speed) = 000: HCLK без деления // Bits 7:4 HPRE[3:0]: предделитель AHB (SYSCLK/AHB) = 000: SYSCLK без деления // Bits 3:2 SWS[1:0]: System clock switch status только чтение => = 11: HSI oscillator used as system clock // Bits 1:0 SW[1:0]: System clock switch = 00: HSI selected as system clock // Биты PLLMUL[3:0], PLLXTPRE и PLLSRC можно менять только при выключеном PLL, поэтому их оставляем без изменения (записываем после выключения PLL) // 31:27 26:24 23 22 21:18 17 16 15:14 13:11 10:8 7:4 3:2 1:0 RCC->CFGR &= (uint32_t)0x00BF000C; // 00000 000 1 0 1111 1 1 00 000 000 0000 11 00 = 0x00BF000C // или //RCC->CFGR &= ~( RCC_CFGR_SDADCPRE | RCC_CFGR_MCO | RCC_CFGR_USBPRE | RCC_CFGR_ADCPRE | RCC_CFGR_PPRE2 | RCC_CFGR_PPRE1 | RCC_CFGR_HPRE | RCC_CFGR_SW); // 3. Сбрасываем биты HSEON, CSSON and PLLON биты в регистре RCC_CR // -- Регистр RCC_CR - Clock control register. Reset value: 0x0000 XX83 where X is undefined. Поля: // Bits 31:26 Reserved => 111111 // Bit 25 PLLRDY: PLL clock ready flag только чтение => 1 (= 0: PLL unlocked; = 1: PLL locked) // Bit 24 PLLON: PLL enable = 0: PLL OFF; = 1: PLL ON // Bits 23:20 Reserved => 1 // Bit 19 CSSON: Clock security system enable (CSS) — система безопасности тактирования = 0: OFF; = 1: ON // Bit 18 HSEBYP: HSE crystal oscillator bypass = 0: OFF; = 1: ON (HSE д.б. выключен!) => 1 // Bit 17 HSERDY: HSE clock ready flag; только чтение => 1 (= 0: HSE не готов; = 1: успешный запуск и стабилизации частоты HSE-генератора) // Bit 16 HSEON: HSE clock enable; = 0: OFF; = 1: ON // Bits 15:8 HSICAL[7:0]: HSI clock calibration - initialized automatically at startup => 11111111 // Bits 7:3 HSITRIM[4:0]: точная настройка HSI по умолчанию => 10000 // Bit 1 HSIRDY: HSI clock ready flag;только чтение => 1 (= 0: HSI не готов; = 1: стабилизации частоты HSI-генератора) // Bit 0 HSION: HSI clock enable; = 1: HSI ON; = 0: HSI OFF // 31:26 25 24 23:20 19 18 17 16 15:8 7:3 2 1 0 RCC->CR &= (uint32_t)0xFEF6FFFF; // 111111 1 0 1111 0 1 1 0 11111111 11111 1 1 1 // или //RCC->CR &= ~(RCC_CR_PLLON | RCC_CR_CSSON | RCC_CR_HSEON); // Т.к. по умолчанию после сброса RCC_CR=0x0000 XX83, оставим регистр как после сброса //RCC->CR |= (uint32_t)0x0000FF83; // 4. Reset HSEBYP bit - можно записывать только после отключения HSE осциллятора, поэтому "идёт" отдельно RCC->CR &= ~RCC_CR_HSEBYP; // 5. Сбрасываем биты PLLSRC, PLLXTPRE, PLLMUL and USBPRE bits // Bit 22 USBPRE: предделитель USB (USB clock д.б.=48 MHz) = 0: деление на 1,5 // Bits 21:18 PLLMUL[3:0]: коэффициент умножения PLL = 0000: x 2 // Bit 17 PLLXTPRE: Делитель частоты с HSE генератора перед подачей на PLL; = 0: без деления // Bit 16 PLLSRC: Источник входной частоты PLL = 0: HSI/2 RCC->CFGR &= (uint32_t)0xFF80FFFF; // 7. Disable all interrupts and clear pending bits // -- Регистр RCC_CIR - Clock interrupt register. Reset value: 0x0000 0000. Поля: // Bits 31:24 Reserved => 0 // Bit 23 CSSC: Clock security system interrupt clear = 1: Clear CSSF flag // Bits 22:21 Reserved => 0 // Bit 20 PLLRDYC: PLL ready interrupt clear = 1: Clear PLLRDYF flag // Bit 19 HSERDYC: HSE ready interrupt clear = 1: Clear HSERDYF flag // Bit 18 HSIRDYC: HSI ready interrupt clear = 1: Clear HSIRDYF flag // Bit 17 LSERDYC: LSE ready interrupt clear = 1: LSERDYF cleared // Bit 16 LSIRDYC: LSI ready interrupt clear = 1: LSIRDYF cleared // Bits 15:13 Reserved, must be kept at reset value. // Bit 12 PLLRDYIE: PLL ready interrupt enable = 0: PLL lock interrupt disabled; = 1: PLL lock interrupt enabled // Bit 11 HSERDYIE: HSE ready interrupt enable = 0: HSE ready interrupt disabled; = 1: HSE ready interrupt enabled // Bit 10 HSIRDYIE: HSI ready interrupt enable = 0: HSI ready interrupt disabled; = 1: HSI ready interrupt enabled // Bit 9 LSERDYIE: LSE ready interrupt enable = 0: LSE ready interrupt disabled; = 1: LSE ready interrupt enabled // Bit 8 LSIRDYIE: LSI ready interrupt enable = 0: LSI ready interrupt disabled; = 1: LSI ready interrupt enabled // Bit 7 CSSF: Clock security system interrupt flag - только чтение, очищается установкой бита CSSC // Bits 6:5 Reserved // Bit 3 HSERDYF: HSE ready interrupt flag - только чтение, очищается установкой бита HSERDYC // Bit 2 HSIRDYF: HSI ready interrupt flag - только чтение, очищается установкой бита HSIRDYC // Bit 1 LSERDYF: LSE ready interrupt flag - только чтение, очищается установкой бита LSERDYC // Bit 0 LSIRDYF: LSI ready interrupt flag - только чтение, очищается установкой бита LSIRDYC RCC->CIR = 0x009F0000; // Сбрасываем биты PREDIV // -- Регистр RCC_CFGR2 (Clock configuration register 2) Reset value: 0x0000 0000. Поля: // Bits 31:4 Reserved, must be kept at reset value. // Bits 3:0 [3:0] PREDIV: PREDIV division factor = 0000: HSE input to PLL not divided RCC->CFGR2 &= (uint32_t)0xFFFFFFF0; } // ==== end RCC_Reset() =====