Showing results for 
Search instead for 
Did you mean: 

How to generate a one second interrupt using an STM32 Timer

ST AME Support NF
ST Employee

How do I generate a one second interrupt using an STM32 Timer?

1. Introduction

It is very common that applications require a periodic interrupt that is used as a time-base for triggering tasks, adding delays, keeping track of elapsed time, etc. While this article shows how to configure an STM32 Timer to generate an interrupt every second, it is easy to change some parameters for other periodic rates.

2. Pre-requisite


  • Nucleo-G070RB
  • Micro USB cable used to power the Nucleo board from a host machine and to load the code into the STM32.


  • STM32CubeIDE

3. Theory

In this article we will use a general STM32 timer in order to generate an interrupt every second. We could have used the Systick or the RTC (Real Time Clock), but in this article we will use a simple timer, timer 3 (TIM3), in an STM32G0 Microcontroller. TIM3 is one of many timers embedded in the STM32 Microcontrollers.
TIM3 contains many components as shown in the following block diagram. While the timer supports a number of functions and features, only a subset is needed to generate a periodic one second interrupt. The following components of the timer block are used and configured for this example:
  • Input clock (clock source for the timer): This clock, called Internal clock (CK_INT), comes from the RCC (Reset and Clock Control) block and is prescaled from the peripheral clock (APB) which is prescaled from the AHB clock.
  • Prescaler input clock, CK_PSC, comes from the Trigger controller and is the same as the input clock
  • PSC prescaler divides its input clock, CK_PSC, and outputs it as CK_CNT
  • CK_CNT is the input clock to the CNT counter that is used to increment it
  • Auto-reload register (ARR) is loaded with the value that the counter increments to. When the value is reached, an update interrupt is generated, the counter is cleared and restarts counting again. The value loaded into the ARR determines the periodic rate of the timer interrupts.

In this part we will review the various calculations necessary to configure TIM3 to generate an interrupt every second.
First of all TIM3 input clock (TIM3CLK) is set to APB1 clock (PCLK1),
  APB1 prescaler will be set to 1.
  And PCLK1 = HCLK
  => TIM3CLK = HCLK = System Core Clock
In this example we will run the STM32G0 at its maximum speed which is 64 MHz.
So SystemCoreClock is set to 64 MHz.
To get TIM3 counter clock at 10 KHz, the Prescaler is computed as following:
    Prescaler = (TIM3CLK / TIM3 counter clock) - 1
    Prescaler = (SystemCoreClock /10 KHz) – 1 = (64 MHz / 10 KHz)-1 = 6400 -1 = 6399
The TIM3 ARR (Auto-Reload Register) value which is the Period is equal to 10000 - 1,
Update rate = TIM3 counter clock / (Period + 1) = 1 Hz. This results in an interrupt every 1 second.
When the counter value reaches the auto-reload register value, the TIM update interrupt is generated and, in the handler routine, pin PA5 (connected to LED4 on board NUCLEO-G070RB) is toggled.
Now that we have calculated the necessary configuration values, let’s walk through the steps to generate the code to for the timer to trigger an interrupt every second.


4. Steps

  1.  Open STM32CubeIDE
  2. Create a new project using the NUCLEO-G070RB board
  1. Give a name to the project
  1. Initialize all peripherals with their default settings
  1. Set the System Clock frequency
We are going to set HCLK to the maximum of 64 MHz:
Setting the APB Presecaler to 1 results in the APB Peripheral Clock (PCLK) set to 64 MHz also.

  1. Select TIM3
Note that while you can use any timer, TIM3 is used in  this example.

You will find TIM3 in the Pinout & Configuration Tab of the STM32CubeIDE under “Timers”.
  1. Select internal clock as clock source for TIM3:
In the TIM3 Mode and Configuration, select Internal Clock as Clock Source.
  1. Configure TIM3
In the Parameter Settings we will input the values we calculated earlier in the Theory section.
We will set 6399 for Prescaler
And use 10000 for the Counter Period
  1. Enable TIM3 global interrupts

  1. Generate Code
Save the project, that will also generate the code.
  1. Add code to toggle the LED
In main.c, add the following code in the main function (this code is used to Start the Timer TIM3 in Interrupt mode):
  if (HAL_TIM_Base_Start_IT(&htim3) != HAL_OK)
    /* Starting Error */
  /* USER CODE END 2 */
In stm32g0xx_it.c,  add the following code in TIM3_IRQHandler (Timer 3 Interrupt Service Request) which will toggle the LED:
  1. Build the project, enter debug mode and run the code
After the project is built, enter a debug session and then click on the Resume icon to run the code.
While the code is running, the green LED is toggled every second as configured.

5. Links

STM32G070 Datasheet

Arm® Cortex®-M0+ 32-bit MCU, 128 KB Flash, 36 KB RAM, 4x USART, timers, ADC, DAC, comm. I/Fs, 1.7-3.6V (

STM32G070 Reference Manual

STM32G0x0 advanced Arm®-based 32-bit MCUs - Reference manual


STM32CubeIDE - Integrated Development Environment for STM32 - STMicroelectronics


NUCLEO-G070RB - STM32 Nucleo-64 development board with STM32G070RB MCU, supports Arduino and ST morpho connectivity - STMicroelectronics
Associate II

Great and clear post. Thank you!

Associate III

Thanks. I did HAL_TIM_Base_Start() instead of HAL_TIM_Base_Start_IT() until I saw this post.

Version history
Last update:
‎2021-10-21 01:09 AM
Updated by: