LED Toggle using the Sysytick timer on STM32F4xx

Wednesday, August 20, 2014 11:00 AM

Introduction

This tutorial is a continuation of the previous tutorial in which we have seen together how to turn on the LED on STM32F4-Discovery board. So it's important to check the previous tutorial Here.

In this tutorial we will try to toggle the LED using the Systick timer. The Timer is a hardware devices counter for measuring the time, it can be count up or a countdown.
In our case the Systick timer is a countdown.  The Systick have an initial value called RELOAD value, from this value the Systick counter is decreasing till reach the zero. When the timer reach the zero an interruption is trigged. The RELOAD can be any value in the range 0x00000001-0x00FFFFFF (1- 16777215)
This was a general overview of the Systick timer. Later we will see it in detail.
You can download the LED toggle project Here. And If you want to see the video go to the bottom of this page.

Systick configuration

The Systick is an internal timer inside the cortex-m4, so to find the configuration function we have to go to the ‘core_cm4.h’, you find this header file inside the STM32F4-Discovery firmware package here:
STM32F4-Discovery_FW_V1.1.0\Libraries\CMSIS\Include
Inside this header file we look for the SysTick_Config function which is responsible to initializes the system tick timer and its interrupt and start the system tick timer.
By default the SysTick_Config function configure the SysTick Counter clock source to be Core Clock Source (HCLK) and it’s about 168 MHz.


As shown in the picture above the parameter of the function is the number of ticks between two interrupt or RELOAD value.

Here’s an example of how we calculate the time between two interrupt:
We know that the SysTick Counter clock source is about 168MHz so 168 000 000 ticks per second.
So to calculate the time required to make a ticks we proceed like this: 1/168 000 000 ≈ 5.952 μs.
If we put 2000 in the RELOAD value we obtain an interruption every 11.904 ms (5.952 μs x 2000 = 11.904 ms.)

Now let’s go back in our case. We want to obtaint an interruption every 1ms.
We know that the SysTick Counter clock source is about 168MHz that means 168 000 000 ticks per second, so if we put the clocks core frequency as the RELOAD value, we will have an interruption every 1 second.

in real case we cannot put 168 000 000 in the RELOAD value because as mentioned before the RELOAD value should not exceed 0xFFFFFF (16 777 215).

If we divide the clocks core frequency by thousand (168 Mhz / 1000), we will obtain an interruption every 1 ms. And the RELOAD value still above the limit (168 000).

Here’s the function inside the main:

int main()
{
	.
    .
    .
  //Systick Configuration
  SysTick_Config(SystemCoreClock/1000);  
  return 0;
}
 
              

 

Interrupt handler

The interrupt handler function is inside the stm32f4xx_it.c

In every interruption the microcontrollers interrupt from executing the main program and go to execute the code inside the Systick_Handler.


We left the Systick_Handler right now, we will back to it later and we go for coding our main file.

Here’s the code :

#include "stm32f4xx.h"
#include "stm32f4_discovery.h"

void Delay(__IO uint32_t time);
extern __IO uint32_t TimmingDelay;

int main()
{
  //Enable the GPIOD Clock
  …..  
  // GPIOD Configuration
  …..  
  // GPIOD-PIN-15 ON
  …..  
   //Systick Configuration
  ……
  
  //LED Toggle
  while(1)
  {
    // insert a delay of 500ms
    Delay(500);
    
    //Toggle the LED 
    STM_EVAL_LEDToggle(LED5);
  }
  return 0;
}
 
            

We create a loop after finishing all the configuration and insert inside this loop a delay of 500ms. We see later how to create this delay using the Systick timer.
After the delay we toggle the LED by using the STM_EVAL_LEDToggle function. This one is inside the stm32f4_discovery.c driver.
You can also use the GPIO_ToggleBits function inside the stm32f4xx_gpio.c instead of STM_EVAL_LEDToggle it’s the same.

Now let’s go deep and see how to create the delay function using the Systick timer.
Here’s the definition of the Delay function.:

void Delay(__IO uint32_t time)
{
  TimmingDelay = time;
  while(TimmingDelay !=0);
}          
 
            

We assign the time value variable to the TimmingDelay variable which is about 500.
The TimmingDelay is declared in the top of the main file as an extern because we will use this variable inside the interrupt handler file.

extern __IO uint32_t TimmingDelay;      
     

The microcontroller still inside the delay function till the TimmingDelay, which initially equal to 500, reach the zero.

while(TimmingDelay !=0);          
   

The __IO used before declaring a variable. Means that variable is a volatile.
The term 'volatile' has very specific meaning to a C/C++ compiler -- it means that the variable or parameter may change outside of the view of the C compiler. So the compiler is required to not optimize it.

We move on to the interrupt handler file and there we declare again the TimmingDelay that we’ve declared in the main before. but this time without using the extern.

__IO uint32_t TimmingDelay;
void SysTick_Handler(void)
{
  if(TimmingDelay !=0)
  {
    TimmingDelay --;
  }
}         
   

Then inside the SysTick_Handler we check if the TimmingDelay doesn't reach the zero then we decrease it.
We know that the interruption is trigged every 1ms and the TimmingDelay is initially equal to 500, so the TimmingDelay variable will reach the zero after 500 ms.

Here’s main program code:

#include "stm32f4xx.h"
#include "stm32f4_discovery.h"

void Delay(__IO uint32_t time);
extern __IO uint32_t TimmingDelay;

int main()
{
  //Enable the GPIOD Clock
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE);
  
  // GPIOD Configuration
  STM_EVAL_LEDInit(LED5);
  
  // GPIOD-PIN-15 ON
  STM_EVAL_LEDOn(LED5);
  
  //Systick Configuration
  SysTick_Config(SystemCoreClock/1000);
  
  //LED Toggle
  while(1)
  {
    // insert a delay of 500ms
    Delay(500);
    
    //Toggle the LED 
    STM_EVAL_LEDToggle(LED5);
  
  }
  
  return 0;
}

void Delay(__IO uint32_t time)
{
  TimmingDelay = time;
  while(TimmingDelay !=0);
}
       
            

The interrupt handler code:

__IO uint32_t TimmingDelay;
void SysTick_Handler(void)
{
  if(TimmingDelay !=0)
  {
    TimmingDelay --;
   }
}         
			 


This Tutorial still available for all STM32Fxx devices.
If you use the same STM32F407VG microcontroller with others boards than the Discovery, you must not add the stm32f4_discovery.c source file.

Video