STM32 Timer - EPFL-MICRO-315/TPs-Wiki GitHub Wiki

⚠ wiki page used in TP1

Timer configuration

  • This section will cover the set up of a timer interruption (TIM7 will be used as an example)
  • A typical timer setup requires a start function to initialize the timer
    void timer7_start(void)
    {
        // Enable TIM7 clock
        RCC->APB1ENR |= RCC_APB1ENR_TIM7EN;
    
        // Enable TIM7 interrupt vector
        NVIC_EnableIRQ(TIM7_IRQn);
    
        // Configure TIM7
        TIM7->PSC = PRESCALER - 1;      // Note: final timer clock  = timer clock / (prescaler + 1)
        TIM7->ARR = COUNTER_MAX - 1;    // Note: timer reload takes 1 cycle, thus -1
        TIM7->DIER |= TIM_DIER_UIE;     // Enable update interrupt
        TIM7->CR1 |= TIM_CR1_CEN;       // Enable timer
    }
    
    • ⚠ Before you can access the timer registers you have to enable the clock
      • TIM7 is connected to APB1 as it is shown for instance in the block diagram of the microcontroller in the datasheet
      • => you have to set the TIM7EN enable bit in RCC->APB1ENR
    • Every interrupt must be enabled in the Nested vectored interrupt controller (NVIC) in order to generate an interrupt
      • call the provided function NVIC_EnableIRQ(TIM7_IRQn) with the interrupt number as argument, in this case TIM7_IRQn
      • 💡 IRQ stands for Interrupt ReQuest
      • 💡 The interrupt number is defined in the enum IRQn_Type in the header file stm32f407xx.h
  • Then you need to implement the interrupt service routine (ISR)
    // Timer 7 Interrupt Service Routine
    void TIM7_IRQHandler(void)
    {
        /*
        *
        *   BEWARE !!
        *   Based on STM32F40x and STM32F41x Errata sheet - 2.1.13 Delay after an RCC peripheral clock enabling
        *
        *   As there can be a delay between the instruction of clearing of the IF (Interrupt Flag) of corresponding register (named here CR) and
        *   the effective peripheral IF clearing bit there is a risk to enter again in the interrupt if the clearing is done at the end of ISR.
        *
        *   As tested, only the workaround 3 is working well, then read back of CR must be done before leaving the ISR
        *
        */
    
        /* do something ... */
    
        // Clear interrupt flag
        TIM7->SR &= ~TIM_SR_UIF;
        TIM7->SR; // Read back in order to ensure the effective IF clearing
    }
    
    • 💡 The address of the interrupt routines is placed in the interrupt vector table, which is defined in the file TP1_blinky/ST/startup_stm32f407xx.s
    • 💡 Implementing the interrupt handler overwrites the default handler
    • 💡 The compiler knows this function is the interrupt handler of the timer 7 thanks to the file startup_stm32f407xx.s
  • Now you can start configuring the TIM7 timer using the following registers:
    • CR1: Control Register 1, configure and enable the timer
    • DIER: DMA/Interrupt Enable Register
    • PSC: Prescaler Register, change the counting frequency by dividing the base clock
    • ARR: Auto-Reload Register, value at which the timer will reset its counter to 0 and generate an interrupt