Skip to main content
GunkutA
Associate III
May 29, 2020
Solved

STM32 pwm signal and reverse of it

  • May 29, 2020
  • 10 replies
  • 4683 views

The MCU I use is STM32F103C8 and I need 2 PWM signals that complete each other to %100 duty cycle. ( ie: PWM1=%60 and PWM2 =%40 ). When one PWM channel is high the other one needs to be low and vice versa.

The important part is, these two PWM signals should not be high at the same time. So I thought using 2 channels in opposite PWM mode. However, duty cycles will be changing and they will not be same throughout the code so while changing the CCR values of these channels, I believe the pattern might be broken and these signals might get high at the same time, even for a short time. 

Is there a way that I can follow to maintain that comleting PWM signals without having them high at the same time and is there a precaution or a security measure to prevent making them high at the same time?

Edit:

I need to set dead time around 50 ns, with my clock period 13.8 ns I need to set TIM1_BDTR register's DTG bits to 0x04. (These are the [0-7] bits of the BDTR register). I don't want to change the bits [8-15]. But I am not sure how can I reach and change individual bits in STM32. I guess the way I used to do in PIC does not work in STM.

So I think I can change each bit one by one as this:

TIM1_BDTR= (0<<0); 
 TIM1_BDTR= (0<<1); 
TIM1_BDTR= (1<<2);

But this seems wrong. How can I set last LS 3 bits of TIM1_BDTR to 4?

This topic has been closed for replies.
Best answer by berendi

In the STM32F103C8 there is the advanved timer TIM1, where channels 1,2,3 have complementary outputs.

Read 14.3.11 Complementary outputs and dead-time insertion and the description of the TIM1 capture/compare enable register (TIMx_CCER) in the reference manual.

If you can't use TIM1 for some reason, you must ensure that the CCR registers are preloaded (set the TIM_CCMR*_OC*PE bits for those channels), and they are updated within one timer period, this is at best done in the timer update interrupt. This might be tricky when the PWM frequency is above ~100 kHz.

10 replies

TDK
May 29, 2020

You can use the TIMx_CHx and complementary TIMx_CHxN output like this. This is not available on all channels/timers, but it is available.

You could also use separate channel with opposite polarity as long as you ensure the CCRx is updated at the same time (via shadow register).

"If you feel a post has answered your question, please click ""Accept as Solution""."
GunkutA
GunkutAAuthor
Associate III
May 29, 2020

Thanks TDK can you check the Edited part in the main question? I am stuck in a simple step.

berendi
berendiBest answer
Principal
May 29, 2020

In the STM32F103C8 there is the advanved timer TIM1, where channels 1,2,3 have complementary outputs.

Read 14.3.11 Complementary outputs and dead-time insertion and the description of the TIM1 capture/compare enable register (TIMx_CCER) in the reference manual.

If you can't use TIM1 for some reason, you must ensure that the CCR registers are preloaded (set the TIM_CCMR*_OC*PE bits for those channels), and they are updated within one timer period, this is at best done in the timer update interrupt. This might be tricky when the PWM frequency is above ~100 kHz.

GunkutA
GunkutAAuthor
Associate III
May 29, 2020

Yes berendi thanks. I figured that out. Can you check my simple question in the edit part? It is about reaching and changingindividual registers.

berendi
Principal
May 29, 2020

You need bitwise operators to change individual bits in a register. I'd recommend using the standard CMSIS device headers. So you can write either

TIM1->BDTR = (TIM1->BDTR & ~TIM_BDTR_DTG) | TIM_BDTR_DTG_2;

or

TIM1->BDTR = (TIM1->BDTR & ~TIM_BDTR_DTG) |
 (4 << TIM_BDTR_DTG_Pos);

& ~TIM_BDTR_DTG clears the whole DTG bitfield, then you can either set individual bits using the TIM_BDTR_DTG_* macros, or put a numerical value in a mult-bit field using << TIM_BDTR_DTG_Pos.

GunkutA
GunkutAAuthor
Associate III
May 29, 2020

Thank you. But I need to include header for that CMSIS thing. Am I right?

berendi
Principal
May 29, 2020

Yes. It is only a header, there is no actual code in it, only data type and macro definitions.

GunkutA
GunkutAAuthor
Associate III
May 29, 2020

Thanks :)

GunkutA
GunkutAAuthor
Associate III
May 29, 2020

Actually I think Dead time is not working as it supposed to. It messes up the duty cycle. When I set 200 kHz PWM with, %50 duty and dead time= 0. It works fine but when I increase the dead time, code puts this time in the 200 kHz PWM signal. So After all duty cycle gets dropped down.. Shouldn't it work like, after the PWM sequence, then dead time comes. Not putting that dead time inside of the PWM Period. Or was it intended?

waclawek.jan
Super User
May 29, 2020

Read the deadline subchapter in TIM chapter in RM, as berendi said above. There are timing diagrams provided. You have to set things according to the way how they work, not according to how you think they should work.

JW

GunkutA
GunkutAAuthor
Associate III
May 29, 2020

Indeed, it was intended and that correct way.

waclawek.jan
Super User
May 29, 2020

The root issue is, that transistors tend to "close" slower than commanded, which effectively increases the duty at their output (if you look at a single transistor; in half-brigde that results in disastrous overlap between both transistors being open at the same time). So, deadtime only compensates for that increased duty; of course, if you set it to high, it will act then excessively as duty decrease.

JW