![]() |
Previous Tutorial | Tutorial 13 | Next Tutorial | ![]() |
|||
STM32 Timers – Timer Mode LAB | |||||||
STM32 Course Home Page 🏠 |
In this LAB, we’ll discuss how to configure the STM32 timer module to operate in the timer mode. And use it to generate a periodic interrupt signal to toggle an LED. You’ll go through step-by-step HAL example configurations to initialize all the required hardware peripherals. Then, we’ll write simple application code to test the hardware functionalities. And also we’ll see how to calculate the timer preload value to get the desired output time interval exactly. without further ado, let’s get started!
[toc]
Required Components For LABs
All the example code/LABs/projects in the course are going to be done using those boards below.
- Nucleo32-L432KC (ARM Cortex-M4 @ 80MHz) or (eBay)
- Blue Pill STM32-F103 (ARM Cortex-M3 @ 72MHz) or (eBay)
- ST-Link v2 Debugger or (eBay)
QTY | Component Name | 🛒 Amazon.com | 🛒 eBay.com |
2 | BreadBoard | Amazon | eBay |
1 | LEDs Kit | Amazon Amazon | eBay |
1 | Resistors Kit | Amazon Amazon | eBay |
1 | Capacitors Kit | Amazon Amazon | eBay & eBay |
2 | Jumper Wires Pack | Amazon Amazon | eBay & eBay |
1 | 9v Battery or DC Power Supply | Amazon Amazon Amazon | eBay |
1 | Micro USB Cable | Amazon | eBay |
1 | Push Buttons | Amazon Amazon | eBay |
★ Check The Full Course Complete Kit List
Some Extremely Useful Test Equipment For Troubleshooting:
- My Digital Storage Oscilloscope (DSO): Siglent SDS1104 (on Amazon.com) (on eBay)
- FeelTech DDS Function Generator: KKMoon FY6900 (on Amazon.com) (on eBay)
- Logic Analyzer (on Amazon.com) (on eBay)
Affiliate Disclosure: When you click on links in this section and make a purchase, this can result in this site earning a commission. Affiliate programs and affiliations include, but are not limited to, the eBay Partner Network (EPN) and Amazon.com.
STM32 Timer Mode LAB Preface
In this LAB, we’ll set up a general-purpose timer module to operate in timer mode. We’ll set the overflow time interval to the desired value using the equation down below. And toggle an LED in the interrupt service routine (ISR) for the timer overflow event.
As you can see, the output time interval is determined by the Prescaler value, the clock frequency, and the timer preload register’s value. Given that the blue pill board can run @ up to 72MHz, and let’s set the frequency to 72Mz. Now, we can choose a value for the Prescaler then put in the desired TOUT and solve for the Preload register value.
In LAB7, we’ll set our desired output time interval to be 100mSec. We’ll toggle the LED once each 100mSec and we’d like to set up the timer interrupt to give us this time interval. So, from the above equation, we can assume the FCLK to be 72MHz. And let the Prescaler be 1000. Now, the only unknown is the Preload value. By solving for it, we’ll get 7200.
LAB Objectives
LAB Number | 7 |
LAB Title | Timer Mode Periodic Event |
- Configure the general-purpose timer (TIM2) to operate in timer mode
- Set The Prescaler, and the Preload value so that the output Time interval is 100mSec
- Toggle an output pin (LED) each 100mSec in the timer overflow ISR
- Measure and verify the output signal’s timing
STM32 Timer – Timer Mode LAB Config.
Step1: Open CubeMX & Create New Project
Step2: Choose The Target MCU & Double-Click Its Name
Step3: Click On The Pin You Want To Configure As An Output & Select Output Option
Let it be B13 pin for example! (The LED Pin)
Step4: Configure Timer2 Peripheral
As we’ve calculated earlier, the Prescaler will be 1000, and the Preload value will be 7200. And the timer module will be clocked at the internal clock frequency.
Step5: Enable The Timer Interrupt Signal In NVIC Tab
Step6: Set The RCC External Clock Source
Step7: Go To The Clock Configuration
Step8: Set The System Clock To Be 72MHz Or Whatever You Want
Step9: Name & Generate The Project Initialization Code For CubeIDE or The IDE You’re Using
Then, open the project in the IDE you’re using. And head over to the main.c file. So we can start writing the application code and have a look at the initialization code generated by the STM32 CubeMX tool.
The Application Code In CubeIDE
Here is the generated initialization code in the main.c file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#include "main.h" TIM_HandleTypeDef htim2; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_TIM2_Init(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_TIM2_Init(); while (1) { } } |
Now, the application we’re currently developing is a LED toggle in the ISR for the timer module. So, open the stm32f1xx_it.c file to find the timer interrupt handler, which is this function TIM2_IRQHandler(). Hover over the HAL_TIM_IRQHandler() function and right-click to navigate to its implementation.
1 2 3 4 5 6 |
void TIM2_IRQHandler(void) { HAL_TIM_IRQHandler(&htim2); } |
After navigating to the timer interrupt handler routine, you’ll find the following implementation. In this code, we’re searching for the callback function’s name that gets called when an overflow interrupt occurs. You can notice that all sources share the same interrupt signal output compare match, overflow, input capture, etc.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim) { // Other timer interrupts events.. //.. //.. //.. /* TIM Update event */ if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_UPDATE) != RESET) { if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_UPDATE) != RESET) { __HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE); #if (USE_HAL_TIM_REGISTER_CALLBACKS == 1) htim->PeriodElapsedCallback(htim); #else HAL_TIM_PeriodElapsedCallback(htim); #endif /* USE_HAL_TIM_REGISTER_CALLBACKS */ } } //.. //.. // Other timer interrupts events.. } |
Now, we’ve got the callback function’s name that gets called whenever timer overflow occurs. It’s HAL_TIM_PeriodElapsedCallback(). So, we’ll write our own implementation for it in the application file (main.c). And a mention-worthy point is that you also have to enable (start) the timer so it gets clocked and starts counting, otherwise it’ll remain IDLE.
Full LAB Code (main.c)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#include "main.h" TIM_HandleTypeDef htim2; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_TIM2_Init(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_TIM2_Init(); HAL_TIM_Base_Start_IT(&htim2); while (1) { } } void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim) { HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_13); } |
Build & Flash The Code And Let’s Test The Results!
Prototyping & Testing
Step0: Refer To The Blue Pill Board Schematic & Pinout
Step1: Connect The ST-Link To The USB Port & SWD Pins On Board
Step2: Click The Debug Button To Compile The Code & Flash It To The Board & Start A Debugging Session
Step3: You Can Stop The Debugging Session Or Keep It Going. But You Need To Restart The MCU Once To Run The New Application At The Booting Process.
Download TimerMode LAB7 Project
The Results For This LAB
Test Video
Output Signal On My DSO
It’s a perfect 100msec time interval !
Other Fine-Timing Experiments
LAB Number | 8 |
LAB Title | Timer Mode Periodic Event (in microseconds) |
I’ve also done a couple of other experiments in which fine output time intervals are desired. First of which was to produce a periodic timer interrupt every 50μSec. Hence the FCLK is 72MHz, and the Prescaler is left as 0 which means 1:1, therefore the preload value is found to be 3600 using the timer formula.
Consequently, I did change these values in code, rebuild & flash it. And the result was a clean 50μSec waveform! As you can see in the screenshot down below
Obviously, by changing the Preload value from 3600 to 360, the output time interval should now be 5μSec. So, I did that and rebuild & flashed the code. And the result was as expected a clean 5μSec time interval as you can see in the screenshot down below.
However, I do believe that there is a fundamental limitation for the timing resolution that can possibly be enhanced by reducing the usage of HAL library functions and calling multiple functions in the process of handling various tasks.
Stay tuned for the upcoming tutorials and don’t forget to SHARE these tutorials. And consider SUPPORTING this work to keep publishing free content just like this!
![]() |
Previous Tutorial | Tutorial 13 | Next Tutorial | ![]() |