In this tutorial, we’ll discuss The STM32 PWM Phase Shift and how to configure and use the Synchronized Timer Slave Mode With PWM in STM32 microcontrollers to generate phase-shifted PWM output signals with programmable phase angles (45°, 90°, 120°, etc). We’ll implement the STM32 PWM Phase Shift in a code example and a full test project. Without further ado, let’s get right into it!
Table of Contents
- STM32 PWM Phase Shift
- STM32 PWM Phase Shift (Timer Synchronization)
- STM32 PWM Phase Shift Example
- Wrap Up
STM32 PWM Phase Shift
Timers in STM32 microcontrollers have a special mode called “Asymmetric PWM” Mode. Which can be used to generate phase-shifted PWM output signals with programmable phase angles between them. Moreover, the timer slave mode can also be used to trigger another timer so they run synchronously and generate phase-shifted PWM signals similar to what could be achieved using Asymmetric PWM mode but with multiple timer units.
One last method that can also be used to generate phase-shifted PWM signals with STM32 microcontrollers is to use interrupt events to synchronize the PWM manually by code inside the ISR. However, this is inefficient from a CPU utilization perspective but it can be doable if, and only if, the PWM output signal’s frequency is relatively low (under 1kHz or so).
Different Methods To Generate Phase-Shifted PWM Outputs With STM32 MCUs:
- Use Timer Synchronization (slave mode with trigger)
- Use Timer’s Asymmetric PWM Mode (if available in your target MCU)
- Use Timer Update Interrupt to manually manipulate the PWM outputs
In this tutorial, we’ll use method number 1 (timer-synchronized PWM Outputs) to generate 3 PWM output signals with programmable phase-shift angles. Since it’s available in all STM32 target microcontrollers and way more efficient than using interrupts.
STM32 PWM Phase Shift (Timer Synchronization)
The STM32 TIMx timers are linked together internally for timer synchronization or chaining. When one Timer is configured in Master Mode, it can reset, start, stop, or clock the counter of another Timer configured in Slave Mode. Using this feature, we can set up TIM1 as a master which triggers TIM2 (slave) that in turn triggers TIM3 (second slave) to generate 3 Phase-Shifted PWM output signals.
Each TIMx timer module can select a trigger source according to the table below.
Keep in mind that the timers (TIM1& TIM2) both need to have an extra channel other than the PWM output channel. That extra channel will be an output-compare-no-output-pin configuration to be used as a trigger output TRGOx that goes into the ITRx of the following timer.
By setting up the three timers (TIM1, TIM2, and TIM3) in this way, we could achieve 3 phase-shifted PWM outputs as shown below.
Note that the phase shift angle between PWM1 & PWM2 is controlled by the TIM1-OC (output compare) channel. Likewise, the phase shift between PWM2 & PWM3 is controlled by the TIM2-OC channel.
STM32 PWM Phase Shift Example
In this example project, we’ll generate 3 Phase-Shifted PWM outputs with a 120° phase-shift between them, each with a duty cycle of 50% and a PWM frequency of 20kHz.
#1
Open STM32CubeMX, create a new project and select the target microcontroller. For me, it’s (STM32F103C8T6 / BluePill)
#2
Configure the 3 timers (TIM1, TIM2, and TIM3) as follows:
You can use this STM32 PWM Calculator that I’ve made to help you configure the timer PWM mode quickly. The PWM Configurations For the 3 Phase-Shifted PWM outputs will be as follows:
- PSC = 0, ARR = 3599 (20kHz)
- PWM1,2,3 Pulse = 1800 (50%)
- OC1,2 (Phase-Shift) = 1199 (120°)
Here are the three timers’ configurations (side-by-side).
#3
Go to the Clock configuration page and select a clock source to give you the maximum SysClk of 72MHz (in my case).
#4
Name & Generate The Project Initialization Code For CubeIDE or The IDE You’re Using.
STM32 PWM Phase Shift Example Code
Here is The Application Code For This LAB (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 29 30 31 32 33 34 35 36 37 | /* * LAB Name: STM32 PWM Phase-Shift Example * Author: Khaled Magdy * For More Info Visit: www.DeepBlueMbedded.com */ #include "main.h" TIM_HandleTypeDef htim1; TIM_HandleTypeDef htim2; TIM_HandleTypeDef htim3; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_TIM1_Init(void); static void MX_TIM2_Init(void); static void MX_TIM3_Init(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_TIM1_Init(); MX_TIM2_Init(); MX_TIM3_Init(); HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_2); HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); HAL_TIM_OC_Start(&htim2, TIM_CHANNEL_2); HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); while (1) { } } |
Note that besides starting the 3 PWM output channels, I’ve also enabled and started both TIM1-OC and TIM2-OC output compare channels which are needed to achieve the phase shift between the PWM output signals as illustrated earlier in this tutorial.
STM32 PWM Phase Shift Example Testing
Here are the 3 phase-shifted PWM output signals as shown on my DSO. The 3-phase PWM signals are 20kHz, 50%, 120° apart, and perfectly synchronized.
The measured phase shift between PWM1 & PWM2 is 16.6µs. Given that the period is 50µs, then it’s a 360x(16.6/50) = 120° phase shift.
Each PWM output channel can have its complementary output enabled to help you drive half-bridge (gate driver) configurations if needed. According to the setup we’ve made so far, they’ll still maintain the phase shift relation between each other. The complementary PWM output is just the inverse of each PWM output waveform we already have, with optional dead-time insertion, of course.
For further information, check out this STM32 PWM Complementary Output & Dead-Time Control Tutorial.
Required Parts For STM32 Examples
All the example Code/LABs/Projects in this STM32 Series of Tutorials are done using the Dev boards & Electronic Parts Below:
QTY. | Component Name | Amazon.com | AliExpress | eBay |
1 | STM32-F103 BluePill Board (ARM Cortex-M3 @ 72MHz) | Amazon | AliExpress | eBay |
1 | Nucleo-L432KC (ARM Cortex-M4 @ 80MHz) | Amazon | AliExpress | eBay |
1 | ST-Link V2 Debugger | Amazon | AliExpress | eBay |
2 | BreadBoard | Amazon | AliExpress | eBay |
1 | LEDs Kit | Amazon & Amazon | AliExpress | eBay |
1 | Resistors Kit | Amazon & Amazon | AliExpress | eBay |
1 | Capacitors Kit | Amazon & Amazon | AliExpress & AliExpress | eBay & eBay |
1 | Jumper Wires Pack | Amazon & Amazon | AliExpress & AliExpress | eBay & eBay |
1 | Push Buttons | Amazon & Amazon | AliExpress | eBay |
1 | Potentiometers | Amazon | AliExpress | eBay |
1 | Micro USB Cable | Amazon | AliExpress | eBay |
★ Check The Links Below For The Full Course Kit List & LAB Test Equipment Required For Debugging ★
Download Attachments
You can download all attachment files for this Article/Tutorial (project files, schematics, code, etc..) using the link below. Please consider supporting our work through the various support options listed in the link down below. Every small donation helps to keep this website up and running and ultimately supports the whole community.
Wrap Up
In conclusion, we’ve explored the STM32 PWM Phase Shift implementation using timer synchronized slave mode and how to configure the STM32 timers to generate 3-Phase PWM signals with programmable (adjustable) phase shift angles between those PWM output signals.
You can build on top of the provided example code project and integrate it into your system. You can also check the rest of the tutorials in this series to learn more about other features of the STM32 PWM.
Hai Khaled Magdy,
With the same process of STM32 PWM Phase Shift (Timer Synchronized) + Example Code, can we generate a 4phase 90 degree and a 2 phase 180 degree in one.
how to generate 4 phase 90 degree phase shift using stm32?
Thanks for your article, I am a rocky STM32 developer and I already implemented a stepper motor controller with 120 degree shift phases, with a LCD display showing the angule of rotation, but after I use HAL_TIM_PWM_Stop for each timer and start again with HAL_TIM_PWM_Start the last timer doesn’t restart, can you help me. Thanks for your time.