Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdbool.h>
- #include "stm32f1xx.h"
- // Прототипы используемых функций
- void delayMs(int ms);
- int clockInit();
- int main(void)
- {
- // Начальные инициализации оборудования STM32
- clockInit();
- // Включение тактирования портов GPIOA, GPIOB, GPIOC
- RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
- RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
- RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;
- // Обязательный сброс конфигурации портов в 0
- GPIOA->CRL &= ~(GPIO_CRL_MODE0 | GPIO_CRL_CNF0);
- GPIOC->CRH &= ~(GPIO_CRH_MODE13 | GPIO_CRH_CNF13);
- GPIOC->CRH &= ~(GPIO_CRH_MODE14 | GPIO_CRH_CNF14);
- GPIOB->CRL &= ~(GPIO_CRL_MODE3 | GPIO_CRL_CNF3);
- GPIOB->CRL &= ~(GPIO_CRL_MODE4 | GPIO_CRL_CNF4);
- // Настройка режимов портов
- uint32_t mode=0b11; // Режим выхода, с максимальной частотой 50 МГц
- uint32_t cnf=0b00; // Режим push-pull
- GPIOA->CRL |= (mode << GPIO_CRL_MODE0_Pos) | (cnf << GPIO_CRL_CNF0_Pos);
- GPIOC->CRH |= (mode << GPIO_CRH_MODE13_Pos) | (cnf << GPIO_CRH_CNF13_Pos);
- GPIOC->CRH |= (mode << GPIO_CRH_MODE14_Pos) | (cnf << GPIO_CRH_CNF14_Pos);
- GPIOB->CRL |= (mode << GPIO_CRL_MODE3_Pos) | (cnf << GPIO_CRL_CNF3_Pos);
- GPIOB->CRL |= (mode << GPIO_CRL_MODE4_Pos) | (cnf << GPIO_CRL_CNF4_Pos);
- while (true)
- {
- delayMs(500);
- GPIOA->BSRR = (1<<GPIO_BSRR_BR0_Pos);
- GPIOC->BSRR = (1<<GPIO_BSRR_BR13_Pos);
- GPIOC->BSRR = (1<<GPIO_BSRR_BR14_Pos);
- GPIOB->BSRR = (1<<GPIO_BSRR_BR3_Pos);
- GPIOB->BSRR = (1<<GPIO_BSRR_BR4_Pos);
- delayMs(500);
- GPIOA->BSRR = (1<<GPIO_BSRR_BS0_Pos);
- GPIOC->BSRR = (1<<GPIO_BSRR_BS13_Pos);
- GPIOC->BSRR = (1<<GPIO_BSRR_BS14_Pos);
- GPIOB->BSRR = (1<<GPIO_BSRR_BS3_Pos);
- GPIOB->BSRR = (1<<GPIO_BSRR_BS4_Pos);
- };
- return 0;
- }
- // Функция задержки в микросекундах, размещается в ОЗУ
- __attribute__((noinline, section(".ramfunc")))
- void delayMs(int ms)
- {
- uint32_t cycles = ms * F_CPU / 9 / 1000;
- __asm volatile (
- "1: subs %[cycles], %[cycles], #1 \n"
- " bne 1b \n"
- : [cycles] "+r"(cycles)
- );
- }
- // Настройка тактирования системы от внешнего кварца
- // через PLL на максимально возможных частотах.
- // Внешний кварц должен быть на 8МГц
- // Возвращает:
- // 0 - завершено успешно
- // 1 - не запустился кварцевый генератор
- // 2 - не запустился PLL
- // Настройка делается на 72МГц
- int clockInit(void)
- {
- __IO int startUpCounter;
- //////////////////////////////////
- // Запускаем кварцевый генератор
- //////////////////////////////////
- RCC->CR |= (1<<RCC_CR_HSEON_Pos); // Запускаем генератор HSE
- //Ждем успешного запуска или окончания тайм-аута
- for(startUpCounter=0; ; startUpCounter++)
- {
- // Если успешно запустилось, то выходим из цикла
- if(RCC->CR & (1<<RCC_CR_HSERDY_Pos))
- break;
- // Если не запустилось, то отключаем все, что включили
- // и возвращаем ошибку
- if(startUpCounter > 0x1000)
- {
- RCC->CR &= ~(1<<RCC_CR_HSEON_Pos); // Останавливаем HSE
- return 1;
- }
- }
- ////////////////////////////////
- // Настраиваем и запускаем PLL
- ////////////////////////////////
- // Настраиваем PLL
- RCC->CFGR |= (0x07<<RCC_CFGR_PLLMULL_Pos) | // PLL множитель равен 9
- (0x01<<RCC_CFGR_PLLSRC_Pos); // Тактирование PLL от HSE
- RCC->CR |= (1<<RCC_CR_PLLON_Pos); // Запускаем PLL
- // Ждем успешного запуска или окончания тайм-аута
- for(startUpCounter=0; ; startUpCounter++)
- {
- // Если успешно запустилось, то
- // выходим из цикла
- if(RCC->CR & (1<<RCC_CR_PLLRDY_Pos))
- break;
- // Если по каким-то причинам не запустился PLL, то
- // отключаем все, что включили
- // и возвращаем ошибку
- if(startUpCounter > 0x1000)
- {
- RCC->CR &= ~(1<<RCC_CR_HSEON_Pos); // Останавливаем HSE
- RCC->CR &= ~(1<<RCC_CR_PLLON_Pos); // Останавливаем PLL
- return 2;
- }
- }
- /////////////////////////////////
- // Настраиваем FLASH и делители
- /////////////////////////////////
- // Устанавливаем 2 цикла ожидания для Flash
- // так как частота ядра у нас будет 48 MHz < SYSCLK <= 72 MHz
- FLASH->ACR |= (0x02<<FLASH_ACR_LATENCY_Pos);
- // Делители
- RCC->CFGR |= (0x00<<RCC_CFGR_PPRE2_Pos) | // Делитель шины APB2 отключен
- (0x04<<RCC_CFGR_PPRE1_Pos) | // Делитель нишы APB1 равен 2
- (0x00<<RCC_CFGR_HPRE_Pos); // Делитель AHB отключен
- RCC->CFGR |= (0x02<<RCC_CFGR_SW_Pos); // Переключаемся на работу от PLL
- // Ждем, пока переключимся
- while((RCC->CFGR & RCC_CFGR_SWS_Msk) != (0x02<<RCC_CFGR_SWS_Pos))
- {
- }
- // После того, как переключились на
- // внешний источник такирования
- // отключаем внутренний RC-генератор
- // для экономии энергии
- RCC->CR &= ~(1<<RCC_CR_HSION_Pos);
- // Здесь настройка и переключение сисемы на внешний
- // кварцевый генератор и PLL запершилось успехом.
- //Выходим
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement