#include #include #include "exti.h" #include "pin.h" #include "timer.h" #include "registers.h" #include "display.h" #include "delay.h" 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 } display_t display; timer_t stopwatch_timer; timer_t display_timer; timer_t startstop_debounce_timer; exti_t startstop_exti; pin_t startstop_button; exti_t null_button; void main() { // Setup SystemCoreClockSetHSI(); systick_configure(); RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN; RCC->APB1ENR |= RCC_APB1ENR_TIM2EN | RCC_APB1ENR_TIM3EN | RCC_APB1ENR_TIM4EN; RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; // The timer clocks are at 12 MHz. // For 100 Hz, the prescaler would be 120 000. That is too big, // so 200 Hz is chosen. From there it will have to be divided by 2 by application. // For 6800 Hz, 1765 prescaler will be used, leading to 6798... Hz // Initialize timer for display at interrupt frequency // digit update frequency * digits * 34 // aim for 100 Hz * 4 * 17 = 6 800 Hz exti_init(&null_button, 4, EXTI, SYSCFG); exti_external_interrupt(&null_button, EXTI_GPIOA); exti_rising_interrupt(&null_button); exti_enable_interrupt(&null_button); exti_init(&startstop_exti, 0, EXTI, SYSCFG); exti_external_interrupt(&startstop_exti, EXTI_GPIOB); exti_rising_interrupt(&startstop_exti); exti_enable_interrupt(&startstop_exti); pin_init(&startstop_button, GPIOB, 0); pin_into_input(&startstop_button); pin_speed(&startstop_button, LOW_SPEED); { pin_t pin_data; pin_t pin_sftclk; pin_t pin_strobe; pin_init(&pin_data, GPIOA, 9); pin_init(&pin_sftclk, GPIOA, 8); pin_init(&pin_strobe, GPIOB, 5); pin_into_output(&pin_data); pin_into_output(&pin_sftclk); pin_into_output(&pin_strobe); display_init(&display, 4, pin_data, pin_sftclk, pin_strobe); display_dots(&display, 1 << 1); } timer_init(&stopwatch_timer, TIM2, 2); timer_configure(&stopwatch_timer, 0, 60000, 0); timer_set_refresh(&stopwatch_timer, 10000*4); timer_init(&startstop_debounce_timer, TIM4, 4); timer_configure(&startstop_debounce_timer, 0, 60000, 1); timer_set_refresh(&startstop_debounce_timer, 10); timer_enable_interrupt(&startstop_debounce_timer); timer_init(&display_timer, TIM3, 3); timer_configure(&display_timer, 0, 500, 0); timer_set_refresh(&display_timer, 4); timer_enable_interrupt(&display_timer); timer_enable(&display_timer); __enable_irq(); // Application while (1) { uint32_t count = timer_count(&stopwatch_timer) >> 2; display_enable_digit(&display, 0, (count % display.max_value) >= 1000); display_convert_number(&display, count); /* DELAY_US(100); */ } } void null_timer(void) { timer_set_counter(&stopwatch_timer, 0); } void toggle_timer(void) { if (timer_is_enabled(&stopwatch_timer)) { timer_disable(&stopwatch_timer); } else { timer_enable(&stopwatch_timer); } } void EXTI0_handler(void) { exti_clear_interrupt(&startstop_exti); timer_set_counter(&startstop_debounce_timer, 0); timer_enable(&startstop_debounce_timer); } void EXTI4_handler(void) { exti_clear_interrupt(&null_button); null_timer(); } /* void TIM2_handler(void) { */ /* // The stopwatch timer */ /* } */ void TIM3_handler(void) { timer_clear_interrupt(&display_timer); display_update(&display); } void TIM4_handler(void) { timer_clear_interrupt(&startstop_debounce_timer); if (pin_read(&startstop_button)) { toggle_timer(); } }