Skip to main content
RJha.1
Associate
September 8, 2020
Solved

PWM with phase shift on STM32 F410 using CUBEMX

  • September 8, 2020
  • 10 replies
  • 10913 views

Hi I want to generate two PWM having phase shift between them. I am using stm32f410 and cubemx as platform. Could anyone please help.

Best answer by waclawek.jan

For 50% duty, simply set both channels to Output Compare / Toggle mode, and set the respective CCRx registers to values apart the required phase shift.

Note, that Toggle means one edge per timer period, so you need to set time period to half of the required PWM period.

This probably can be clicked on CubeMX, maybe only the CCRx registered would need to be set manually.

JW

10 replies

waclawek.jan
Super User
September 8, 2020

For this, in 'F4, you normally need two timers, in master-slave configuration to ensure they run synchronously.

In newer families, some timers have asynchronous and combined modes, which can achieve such phase shift within one timer.

JW

RJha.1
RJha.1Author
Associate
September 8, 2020

You are right but in my Microcontroller I don’t have asynchronous PWM instead I have PWM mode 1 and PWM mode 2. Any alternative?

waclawek.jan
Super User
September 8, 2020

Generally, two timers, in master-slave configuration.

What *exactly* are your requirements?

JW

RJha.1
RJha.1Author
Associate
September 8, 2020

I am developing a single phase inverter for which I want to generate four PWMs for four switches. Configuration of four switches are such that two switches constitute one leg so basically there are two legs. I want PWM of one leg to be shifted wrt first leg and also PWM of switch of same leg should be complementary and having dead time.

TDK
Super User
September 8, 2020

I'm pretty sure it can be done on one timer. Set the pin to toggle on match and adjust the difference between CCRx values to control the phase shift. You'll need to be careful about when you change values to prevent the polarity from swapping.

Of course that's only if 50% duty cycle works.

"If you feel a post has answered your question, please click ""Accept as Solution""."
RJha.1
RJha.1Author
Associate
September 9, 2020

Thank you for comments. Could you please elaborate how to configure the registers step wise. I am new at this platform.

waclawek.jan
Super User
September 8, 2020

Complementary channels with deadtime are in TIM1. In 'F410 that's probably it; it's not the best STM32 model for this sort of signals.

Unless you are satisfied with the 50% duty cycle as TDK suggested, which can be pulled out using toggle mode of the output compare, probably the only option is to have a "rolling" DMA-to-CCRx of one channel to provide the phase-shifted signal.

JW

RJha.1
RJha.1Author
Associate
September 9, 2020

I found this where CUBEmx is configured for phase shift as well as for dead time.

https://www.programmersought.com/article/42744314104/

And I am writing (part below) in the user code begin 2. But I am getting no signal as output except noses. Any suggestions?

 HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_2);

 HAL_TIMEx_OCN_Start(&htim1, TIM_CHANNEL_2);

 HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_3);

 HAL_TIMEx_OCN_Start(&htim1, TIM_CHANNEL_3);

waclawek.jan
Super User
September 9, 2020

Read our and check the timer and related GPIO registers content.

Read the timer chapter and write to timer registers directly. Clicking in CubeMX and using HAL usually won't allow anything much beyond the examples, so you'd probably need to get there at the end of the day anyway.

JW

RJha.1
RJha.1Author
Associate
September 9, 2020

Any suggestions regarding the steps and configuring the registers?

RJha.1
RJha.1Author
Associate
September 9, 2020

I want duty cycle 50%.

waclawek.jan
waclawek.janBest answer
Super User
September 9, 2020

For 50% duty, simply set both channels to Output Compare / Toggle mode, and set the respective CCRx registers to values apart the required phase shift.

Note, that Toggle means one edge per timer period, so you need to set time period to half of the required PWM period.

This probably can be clicked on CubeMX, maybe only the CCRx registered would need to be set manually.

JW

RJha.1
RJha.1Author
Associate
September 9, 2020

Thank you so much, its working now. I really appreciate your comments.

Visitor II
March 21, 2024

I have found a way to do this on one advanced timer with variable duty. If anyone is interested. it works on stm32f1 and stm32f4 not tried on other mcu

set one channel to pwm ch# the other to pwm ch#n (i have used ch1 and ch2n also ch1 and ch3n both worked)

set counter mode to Centre Aligned Mode1

set repitition counter to 2 (one for each channel is how i think that works but it works!)

brk state disable

brk polarity high

brk and dead time disable,disable,disable and off

set first channel polarity high the other low, then in software calculate the overflow

uint8_t T_1_duty = 1-50; //percent duty

 

HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_#);

HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_#);

(do calculation for overflow)

 

T1_CH#_ccr = (uint16_t)( T_1_overflow * T_1_duty / 100);

T1_CH#_ccr = (uint16_t)(T_1_overflow * (100-T_1_duty) / 100);

 

this works with 180 because we are counting up and down in centre aligned and the second channel is inverted and so is the on time there are about 3 other ways to get same results i think, by changing polarity , pwm1 pwm2 and using ch# instead of ch#n but this is where i first ended up so i stuck with it.

hope this helps someone, It took me months to figure out, but got help from a lot of

"search engineering" but quite simple really looking from outside the box or from the box inverted lol! Good Luck and God Bless!

 

Andy