Ads

Get STM32 tutorial using HAL at $10 for a limited time!

Sunday, August 30, 2015

STM32F4 Discovery Tutorial 9 - Timer Interrupt

In this tutorial, I will share how to generate interrupt every given interval using timer on STM32F4 Discovery board. For example project, we will make orange LED toggle every 500ms interval using TIM2. In the main program we will toggle blue LED every 2500ms (blue LED toggling will not using timer interrupt, but just use delay function).

First, we write code for initialize timer. We will use TIM2. This is the block diagram for configuring the timer clock:


void TIM_INT_Init()
{
    // Enable clock for TIM2
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    // TIM2 initialization overflow every 500ms
    // TIM2 by default has clock of 84MHz
    // Here, we must set value of prescaler and period,
    // so update event is 0.5Hz or 500ms
    // Update Event (Hz) = timer_clock / ((TIM_Prescaler + 1) * 
    // (TIM_Period + 1))
    // Update Event (Hz) = 84MHz / ((4199 + 1) * (9999 + 1)) = 2 Hz
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    TIM_TimeBaseInitStruct.TIM_Prescaler = 4199;
    TIM_TimeBaseInitStruct.TIM_Period = 9999;
    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;

    // TIM2 initialize
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);
    // Enable TIM2 interrupt
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
    // Start TIM2
    TIM_Cmd(TIM2, ENABLE);

    // Nested vectored interrupt settings
    // TIM2 interrupt is most important (PreemptionPriority and 
    // SubPriority = 0)
    NVIC_InitTypeDef NVIC_InitStruct;
    NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStruct);
}
After that, we must write code for interrupt handler that will be call every timer interrupt (500ms). In this handler, we write code for toggle orange LED.
void TIM2_IRQHandler()
{
    // Checks whether the TIM2 interrupt has occurred or not
    if (TIM_GetITStatus(TIM2, TIM_IT_Update))
    {
        // Toggle orange LED (GPIO13)
        GPIO_ToggleBits(GPIOD, GPIO_Pin_13);

        // Clears the TIM2 interrupt pending bit
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
    }
}
Finally, in the main function we can write code for toggle blue LED using delay function. The blue LED will toggle every 2500ms.
#include "stm32f4xx.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_tim.h"
#include "misc.h"
#include "clock.h"
#include "delay.h"

int main(void)
{
    // Set clock to 168MHz
    CLOCK_SetClockTo168MHz();

    // Delay initialization
    DELAY_Init();

    // Timer interrupt initialization
    TIM_INT_Init();

    // Clock for GPIOD
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

    // GPIOD initialization as an output for orange LED (GPIOD13)
    // and blue LED (GPIOD15)
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Init(GPIOD, &GPIO_InitStruct);

    while (1)
    {
        // Toggle blue LED (GPIO15)
        GPIO_ToggleBits(GPIOD, GPIO_Pin_15);
        // Delay 2.5s
        DELAY_Ms(2500);
    }
}
This is the link for download these clock, delay library if you need.

8 comments :

  1. I am new to stm32, i can't understand this can you explain this in detail.

    // Update Event (Hz) = timer_clock / ((TIM_Prescaler + 1) *
    11
    // (TIM_Period + 1))
    12
    // Update Event (Hz) = 84MHz / ((4199 + 1) * (9999 + 1)) = 0.5 Hz

    ReplyDelete
    Replies
    1. I'm sorry, I think there is a mistake here, it should be 2Hz not 0.5Hz, because the LED is blinking every 500ms (1/2Hz=0.5s=500ms)
      This formula is used for calculating how fast the interrupt is generated.
      Update Event (Hz) = timer_clock / ((TIM_Prescaler + 1) * (TIM_Period + 1)) = 2Hz
      For example, 2Hz means that the interrupt will be called every 500ms.
      The timer clock is 84MHz, the prescaler is used for slowing the timer clock from 84MHz to 20kHz (84MHz/4200).
      With 20kHz the period is 0.05ms, then we set the period value(ARR) to 10000, so 0.05*10000 is 500ms. I have added the illustration in the article.

      Delete
    2. Thanks erwin for your reply, now i understand the concept.

      Delete
  2. Can I generate 5 different pulses by this?
    If possible then how? Please reply soon.

    ReplyDelete
  3. how where to add clock.c/.h and delay.c/.h in the atollic program. caan't figure it out

    ReplyDelete
  4. how can we add stm32f407vgtx HMC5883L.C and HMC5883L.H Library

    ReplyDelete
  5. how to calculate counter period for STM32f429zi discovery board?

    ReplyDelete
  6. I am using TIMER 1.
    how to calculate Count period of stm32f4zi discovery board?

    ReplyDelete