#include #include #include "exti.h" #include "pin.h" #include "timer.h" #include "stm32f401xe.h" #define LED_PIN 5 #define LED_GPIO GPIOA #define BUTTON_PIN 13 #define BUTTON_GPIO GPIOC #define BUTTON_GPIO_ID 2 // A 0 B 1 C 2 void hard_fault_handler() { while(1) {} } void usage_fault_handler() { while(1) {} } void nmi_handler() { while(1) {} } void bus_fault_handler() { while(1) {} } /*---------------------------------------------------------------------------- * SystemCoreClockConfigure: configure SystemCoreClock using HSI (HSE is not populated on Nucleo board) *----------------------------------------------------------------------------*/ void SystemCoreClockSetHSI(void) { RCC->CR |= ((uint32_t)RCC_CR_HSION); // Enable HSI while ((RCC->CR & RCC_CR_HSIRDY) == 0); // Wait for HSI Ready RCC->CFGR = RCC_CFGR_SW_HSI; // HSI is system clock while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI); // Wait for HSI used as system clock FLASH->ACR = FLASH_ACR_PRFTEN; // Enable Prefetch Buffer FLASH->ACR |= FLASH_ACR_ICEN; // Instruction cache enable FLASH->ACR |= FLASH_ACR_DCEN; // Data cache enable FLASH->ACR |= FLASH_ACR_LATENCY_5WS; // Flash 5 wait state RCC->CFGR |= RCC_CFGR_HPRE_DIV1; // HCLK = SYSCLK RCC->CFGR |= RCC_CFGR_PPRE1_DIV4; // APB1 = HCLK/4 RCC->CFGR |= RCC_CFGR_PPRE2_DIV2; // APB2 = HCLK/2 RCC->CR &= ~RCC_CR_PLLON; // Disable PLL // HSI = 16 MHz // PLL configuration: VCO = HSI/M * N, Sysclk = VCO/P // => Sysclk = 48 MHz, APB1 = 12 MHz, APB2 = 24 MHz // Since divider for APB1 is != 1, timer clock is 24 MHz RCC->PLLCFGR = ( 16ul | // PLL_M = 16 (384ul << 6) | // PLL_N = 384 ( 3ul << 16) | // PLL_P = 8 (RCC_PLLCFGR_PLLSRC_HSI) | // PLL_SRC = HSI ( 8ul << 24) ); // PLL_Q = 8 RCC->CR |= RCC_CR_PLLON; // Enable PLL while((RCC->CR & RCC_CR_PLLRDY) == 0) __NOP(); // Wait till PLL is ready RCC->CFGR &= ~RCC_CFGR_SW; // Select PLL as system clock source RCC->CFGR |= RCC_CFGR_SW_PLL; while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); // Wait till PLL is system clock src } pin_t led; exti_t button_exti; pin_t button; timer_t toggle_timer; timer_t debounce_timer; // the timer runs at 200 Hz /* uint16_t timer_values[3] = { 20, 100, 300 }; */ uint16_t timer_values[3] = { 40, 200, 600 }; uint8_t current_timer_value = 1; void main() { // TODO: enable tim2, exti, syscfg SystemCoreClockSetHSI(); RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOCEN; RCC->APB1ENR |= RCC_APB1ENR_TIM2EN | RCC_APB1ENR_TIM3EN; RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; volatile uint32_t dummy; dummy = (RCC->AHB1ENR); dummy = (RCC->AHB1ENR); dummy = (RCC->APB1ENR); dummy = (RCC->APB1ENR); dummy = (RCC->APB2ENR); dummy = (RCC->APB2ENR); pin_init(&led, LED_GPIO, LED_PIN); pin_into_output_pushpull(&led); pin_speed(&led, LOW_SPEED); pin_init(&button, BUTTON_GPIO, BUTTON_PIN); pin_into_input(&button); exti_init(&button_exti, BUTTON_PIN, EXTI, SYSCFG); exti_external_interrupt(&button_exti, BUTTON_GPIO_ID); exti_falling_interrupt(&button_exti); exti_clear_interrupt(&button_exti); exti_enable_interrupt(&button_exti); // configure toggle timer timer_init(&toggle_timer, TIM2, 2); timer_set_refresh(&toggle_timer, timer_values[0]); timer_configure(&toggle_timer, 1, 60000, 0); timer_enable_interrupt(&toggle_timer); timer_enable(&toggle_timer); // configure debounce timer timer_init(&debounce_timer, TIM3, 3); timer_set_refresh(&debounce_timer, 10); timer_configure(&debounce_timer, 1, 60000, 1); timer_enable_interrupt(&debounce_timer); __enable_irq(); while(1) { __WFI(); } } // Toggle led timer void TIM2_handler(void) { timer_clear_interrupt(&toggle_timer); pin_toggle(&led); } // Debounce button timer void TIM3_handler(void) { timer_clear_interrupt(&debounce_timer); if (!pin_read(&button)) { timer_set_refresh(&toggle_timer, timer_values[current_timer_value++]); current_timer_value %= sizeof(timer_values) / sizeof(uint16_t); } } void EXTI15_10_handler(void) { if (exti_is_interrupt(&button_exti)) { exti_clear_interrupt(&button_exti); timer_set_counter(&debounce_timer, 0); timer_enable(&debounce_timer); } }