A bare-metal STM32 project that uses TIM2 update interrupts to toggle the onboard LED and print timer tick information over USART2.
The firmware starts in normal blink mode, automatically switches to fast mode, then switches to slow mode.
This project demonstrates timer-based event generation using STM32 hardware timers.
Instead of using a software delay loop, the LED is toggled from the TIM2_IRQHandler() interrupt service routine.
The main loop prints timer tick updates over UART.
| Mode | Timer ARR | Approx. Interrupt Period | LED Behavior |
|---|---|---|---|
| Normal | 999 |
1 second | LED toggles once per second |
| Fast | 199 |
200 ms | LED toggles quickly |
| Slow | 1999 |
2 seconds | LED toggles slowly |
The firmware changes modes automatically:
Start
|
| Tick 0 to 49
v
Normal Mode
|
| At tick 50
v
Fast Mode
|
| At tick 250
v
Slow Mode
When a mode change happens, the STM32 prints a message over UART.
Example output:
Timer Started
==================
Tick: 0
Tick: 1
Tick: 2
...
Tick: 50
>>> Switching to FAST mode!
Tick: 51
Tick: 52
...
Tick: 250
>>> Switching to SLOW mode!
- STM32 NUCLEO-F446RE
- USB cable
No external components are required.
| Function | Pin |
|---|---|
| Onboard LED | PA5 |
| USART2_TX | PA2 |
| USART2_RX | PA3 |
USART2 is connected to the PC through the onboard ST-Link Virtual COM Port.
| Setting | Value |
|---|---|
| USART | USART2 |
| Baud rate | 9600 |
| Data bits | 8 |
| Parity | None |
| Stop bits | 1 |
| Flow control | None |
- Bare-metal STM32 programming
- Direct register manipulation
- GPIO output configuration
- USART2 transmit
- TIM2 hardware timer configuration
- Timer prescaler,
TIM2_PSC - Auto-reload register,
TIM2_ARR - Timer update interrupt
- NVIC interrupt enabling
- Interrupt Service Routine, ISR
- Runtime timer period changes
- Volatile variables shared between ISR and main loop
- UART number printing
- Event flag pattern using
mode_change_flag
TIM2 Hardware Timer
|
v
Update Event
|
v
NVIC triggers TIM2_IRQHandler()
|
v
ISR toggles LED
|
v
ISR increments timer_ticks
|
v
ISR changes mode when tick threshold is reached
|
v
main() prints tick and mode change messages over UART
The project assumes a 16 MHz timer clock.
TIM2_PSC = 15999;
TIM2_ARR = 999;This produces an initial 1-second timer interrupt:
16 MHz / (15999 + 1) = 1000 Hz
1000 counts per second using ARR = 999
Later, the firmware changes TIM2_ARR:
TIM2_ARR = 199; // Fast mode
TIM2_ARR = 1999; // Slow modetimer_ticks counts timer update events, not always real seconds.
In normal mode, one tick is approximately 1 second.
In fast mode, one tick is approximately 200 ms.
In slow mode, one tick is approximately 2 seconds.
- Open STM32CubeIDE.
- Create a project for NUCLEO-F446RE.
- Replace
Core/Src/main.cwith the code fromsrc/main.c. - Build the project.
- Flash it to the board.
- Open a UART terminal at 9600 baud.
- Watch timer tick messages and LED mode changes.
Find the serial port:
ls /dev/ttyACM* /dev/ttyUSB* 2>/dev/nullOpen with minicom:
minicom -D /dev/ttyACM0 -b 9600If no message appears, press the reset button on the NUCLEO board after opening the terminal.
More details:
docs/terminal_setup.md
stm32-tim2-interrupt-led-uart/
│
├── README.md
├── .gitignore
├── docs/
│ ├── wiring.md
│ └── terminal_setup.md
└── src/
└── main.c
- Add button-controlled mode switching
- Use separate real-time seconds counter
- Print current mode with every tick
- Add UART command interface to change timer speed
- Use timer interrupts for accurate non-blocking delays
- Add PWM output using timer channels
- Add low-power sleep while waiting for timer interrupt