Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdbool.h>
- #include "stm32f1xx.h"
- // Прототипы используемых функций
- int clockInit(void);
- void portClockInit(void);
- void otherPortInit(void);
- void msDelay(int ms);
- int main(void)
- {
- // Начальные инициализации оборудования STM32
- clockInit();
- portClockInit();
- otherPortInit(); // <-- Если закомментировать этот вызов, код работает МЕДЛЕННЕЕ
- // Инициализация порта A0
- uint32_t mode;
- uint32_t cnf;
- // Для начала сброс конфигурации пина в ноль
- GPIOA->CRL &= ~(GPIO_CRL_MODE0 | GPIO_CRL_CNF0);
- mode=0b11; // Режим выхода, с максимальной частотой 50 МГц
- cnf=0b00; // Двухтактный выход (Output push-pull)
- GPIOA->CRL |= (mode << GPIO_CRL_MODE0_Pos) | (cnf << GPIO_CRL_CNF0_Pos);
- // Основной цикл
- while (true)
- {
- GPIOA->BSRR = (1<<GPIO_BSRR_BS0_Pos); // Светодиод на A0 включается
- msDelay(1000);
- GPIOA->BRR = (1<<GPIO_BRR_BR0_Pos); // Low
- msDelay(1000);
- }
- return 0;
- }
- // Настройка тактирования системы от внешнего кварца
- // через 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;
- }
- // Включение тактирования портов
- void portClockInit(void)
- {
- // Тактирование портов GPIOA и GPIOB
- RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
- RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
- }
- // Настройка пинов A8, A9, B3, B4, B6, B7
- void otherPortInit(void)
- {
- // Для начала сброс конфигурации всех используемых портов в ноль
- GPIOA->CRH &= ~(GPIO_CRH_MODE8 | GPIO_CRH_CNF8);
- GPIOA->CRH &= ~(GPIO_CRH_MODE9 | GPIO_CRH_CNF9);
- GPIOB->CRL &= ~(GPIO_CRL_MODE3 | GPIO_CRL_CNF3);
- GPIOB->CRL &= ~(GPIO_CRL_MODE4 | GPIO_CRL_CNF4);
- GPIOB->CRL &= ~(GPIO_CRL_MODE6 | GPIO_CRL_CNF6);
- GPIOB->CRL &= ~(GPIO_CRL_MODE7 | GPIO_CRL_CNF7);
- uint32_t mode;
- uint32_t cnf;
- mode=0b11; // Режим выхода, с максимальной частотой 50 МГц
- cnf=0b00; // Режим push-pull
- GPIOA->CRH |= (mode << GPIO_CRH_MODE8_Pos) | (cnf << GPIO_CRH_CNF8_Pos);
- GPIOA->CRH |= (mode << GPIO_CRH_MODE9_Pos) | (cnf << GPIO_CRH_CNF9_Pos);
- mode=0b00; // Режим входа
- cnf=0b01; // Режим плавающего входа, подтяжки нет
- GPIOB->CRL |= (mode << GPIO_CRL_MODE3_Pos) | (cnf << GPIO_CRL_CNF3_Pos);
- GPIOB->CRL |= (mode << GPIO_CRL_MODE4_Pos) | (cnf << GPIO_CRL_CNF4_Pos);
- GPIOB->CRL |= (mode << GPIO_CRL_MODE6_Pos) | (cnf << GPIO_CRL_CNF6_Pos);
- GPIOB->CRL |= (mode << GPIO_CRL_MODE7_Pos) | (cnf << GPIO_CRL_CNF7_Pos);
- }
- // Функция задержки
- void msDelay(int ms)
- {
- while (ms-- > 0) {
- volatile int x=500;
- while (x-- > 0)
- __asm("nop");
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement