#include #include /*! * \brief Configures pin 5 ("PA11") as digital output. */ void config_output(void) { RCC->IOPENR |= RCC_IOPENR_GPIOAEN; GPIOA->MODER &= ~(0x3u << (11 * 2)); GPIOA->MODER |= (0x1u << (11 * 2)); GPIOA->OTYPER &= ~(0x1u << (11 * 1)); } /*! * \brief Configures TIM2 overflow with 10 us period (-> 100 kHz). */ void config_blink_timer(void) { //Enable the TIM2 clock. RCC->APBENR1 |= RCC_APBENR1_TIM2EN; //Make sure the timer's "counter" is off. TIM2->CR1 &= ~TIM_CR1_CEN; //Reset the peripheral. RCC->APBRSTR1 |= (RCC_APBRSTR1_TIM2RST); RCC->APBRSTR1 &= ~(RCC_APBRSTR1_TIM2RST); //Set the timer prescaler/autoreload timing registers. TIM2->PSC = 16 - 1; //-> 16 MHz / 16 = 1 MHz TIM2->ARR = 10 - 1; //-> 1/1 MHz * 10 = 10 us (100 kHz) //Send an update event to reset the timer and apply settings. TIM2->EGR |= TIM_EGR_UG; //Enable TIM2 interrupts and set priority. NVIC_EnableIRQ(TIM2_IRQn); NVIC_SetPriority(TIM2_IRQn, 0); } /*! * \brief Enables the "Cycle Timer", which will now fire interrupts that trigger * execution of the "App Loop" (--> \c TIM2_IRQHandler()). */ void start_app(void) { //Clear TIM2_IRQn update interrupt, TIM2->SR &= ~TIM_SR_UIF; //Enable the hardware interrupt. TIM2->DIER |= TIM_DIER_UIE; //Enable the timer. TIM2->CR1 |= TIM_CR1_CEN; } /*! * \brief Initializes any peripheral being used. */ void init(void) { //Disable interrupts. __disable_irq(); config_output(); config_blink_timer(); //Enable interrupts. __enable_irq(); } /*! * \brief Initializes the system and runs the application. */ int main(void) { init(); start_app(); while(1) __WFI(); return EXIT_SUCCESS; } /*! * \brief This IRQ handler will be triggered every 10 us by the "Blink Timer". * This "time base" is used to blink a LED with a defined pattern (50 kHz, * 50% DS). */ void TIM2_IRQHandler(void) { //Clear TIM2 update interrupt flag. TIM2->SR &= ~TIM_SR_UIF; //Toggle PA11 (pin 5). GPIOA->ODR ^= (0x1u << 11); }