Embedded Systems
Generating PWM with STM32
May 21, 2026
1 min read
A technical walkthrough on configuring STM32 hardware timers for precise Pulse Width Modulation (PWM) generation.
View the complete source code and project on GitHub
The Physical Layer of PWM
When configuring bare-metal PWM, you are essentially setting up a hardware timer to count up to an Auto-Reload Register (ARR) value. A separate Capture/Compare Register (CCR) sets the duty cycle.
// Example Bare-Metal Timer Configuration
TIM2->PSC = 79; // Prescaler (e.g., for 80MHz clock, sets tick to 1us)
TIM2->ARR = 999; // Auto-reload value (Period = 1ms -> 1kHz frequency)
TIM2->CCR1 = 499; // Duty Cycle = ~50%
TIM2->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; // PWM Mode 1
TIM2->CCER |= TIM_CCER_CC1E; // Enable Output
TIM2->CR1 |= TIM_CR1_CEN; // Start Timer
Why it matters
In power electronics, the precision of your timer dictates the granularity of your control loops. If you’re designing a grid-tied inverter or a digital SMPS, knowing exactly when the registers update (shadow registers vs active) is critical to avoiding shoot-through in half-bridge configurations.