STM32CubeMX Tutorial Series: Basic Timer
Abstract: STM32 has powerful timers, including basic timer, comment timer and senior timer. In this chapter, we will introduce the basic application of the timer: How to use timer interrupt to control the LED blinking with interval of 1s.
In this chapter, we will use the GPIO project described in the preceding chapter, and modify it as required. Copy the GPIO project and modify the name of the file fold. Click the .ico file to open the STM32cubeMX project file and reconfigure it. Start up the TIM3, and select the internal clock.
The timer severs as a clock of the MCU. In the following section, we will take the basic timer as an example to simply introduce the timers. See Figure 262 in File:STM32F7-Reference-EN.pdf
In the figure above, we can see that the basic timer contains 3 registers.
- Counter register (TIMx_CNT)
- Prescaler register(TIMx_PSC)
- Auto-reload register(TIMx_ARR)
Counter register(TIMx_CNT) stores the current count value. And the prescaler register(TIMx_PSC) value define the counter behavior with the specific SK_PSC pulse number.As the figure192 shows, the prescaler value is 1, it means the counter may add 1 every two pulses, frequency is divided by 2 (the prescaler register is set to 0 by default, which means no frequency division). In case that frequency is required to be divided by 10000, the prescaler value should be set to 10000-1. See Figure 192 in File:STM32F7-Reference-EN.pdf Auto-reload register (TIMx_ARR) stores the overflow value of the counter. For example, as the figure194 shows, when the counter increase to 36, it will overflow and trigger an interrupt event. In fact, the overflow event may be triggered every 37 pulses (the counter begin from 0). See Figure 194 in File:STM32F7-Reference-EN.pdf
You should set the CK_PSC frequency to make sure the time set by the timer. In the TIM3 configuration, select internal clock as the clock source. By reading the relative datasheet or viewing the code, you can find that the TIM3 is connected to APB1 clock line.
When the internal clock is set to CKD, the CK_PSC clock frequency is equal to the clock frequency of APB1 (108MHz or108000 000Hz). In case that the timer is set to 1s, the internal clock can be set to 10800 division. (The prescaler register (TIMx_PSC) is set to 10800-1), and the frequency of the CK_CNT is 10000Hz. In this case, auto-reload register (TIMx_ARR) is set to 10000-1, which means the timer is set to 1s.TRGO is a trigger output, which can trigger internal ADC/DAC. However, this function is not in used in here. So the relative parameters are default setting.
The timer has 3 counting mode:
In upcounting mode, the counter counts from 0 to the auto-reload value (content of theTIMx_ARR register), then restarts from 0 and generates a counter overflow event.
In downcounting mode, the counter counts from the auto-reload value (content of theTIMx_ARR register) down to 0, then restarts from the auto-reload value and generates acounter underflow event.
In center-aligned mode, the counter counts from 0 to the auto-reload value (content of the TIMx_ARR register) - 1, generates a counter overflow event, then counts from the auto-reload value down to 1 and generates a counter underflow event. Then it restarts counting from 0.
Under the tab NVIC Settings, check the Enabled checkbox to enable the timer interrupt. The priority configurations are remain in default settings. Or, you can enable TIM3 interrupt in NVIC configuration.
You can regenerate a new report and a new code, then compile the program.
Open the file main.c, delete the chapter of lines above the while loop in the main() routine, and make sure the while loop is empty. Add the interrupt callback function in the middle of USER CODE BEGIN 4 andUSER CODE END 4 after the file main.c.Intimer interrupt handler function, the levels of LED1~LED4 may have a switch.
/* USER CODE BEGIN 4 */ /** * @brief Period elapsed callback in non blocking mode * @param htim: TIM handle * @retval None */ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == htim3.Instance) { /* Toggle LED */ BSP_LED_Toggle(LED1); BSP_LED_Toggle(LED2); BSP_LED_Toggle(LED3); BSP_LED_Toggle(LED4); } } /* USER CODE END 4 */
In the main.c file, add the following code before the while(1) loop, to start the TIM Base generation in interrupt mode.
/* USER CODE BEGIN 2 */ /*##-1- Start the TIM Base generation in interrupt mode ####################*/ HAL_TIM_Base_Start_IT(&htim3); /* USER CODE END 2 */
Compile the program again, and download the compiled code to the Open746-C development board. If the program has no error, you can see the LED1~LED4blink once pre second when pressing the key WAKEUP.
Let’s review the program describe above. In the TIM3 timer configuration, select internal clock with no frequency division as clock source, and mount it to the APB1 clock bus (108MHz). The timer mode is set to upcounting mode and prescaler register is set to 10800-1 (10800 division). The timer frequency is 10000Hz, which means each pulse has 1/10000s. If the timer is set to 1s, auto-reload register should be set to 10000-1. (For 0.2s, auto-reload register is set to 0.2/(1/10000)-1, that is 2000-1)
In the main() routine, call HAL_TIM_Base_Start_IT(&htim3) to enable the timer. The counter count from 0 to 10000-1(9999), generate a counter overflow event, then counts from 0 again. Since we have enabled the timer interrupt, the overflow event may trigger a timer interrupt. And the program will jump to the interrupt service function, in which the LEDs levels will have a switch. For next overflow triggering interrupt, the LED levels will switch again. Therefore, we can see the LED is always blinking.