cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 pwm signal and reverse of it

GunkutA
Senior

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?

1 ACCEPTED SOLUTION

Accepted Solutions
berendi
Principal

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.

View solution in original post

12 REPLIES 12
TDK
Guru

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
Senior

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

berendi
Principal

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.

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

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.

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

berendi
Principal

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

GunkutA
Senior

Thanks 🙂

GunkutA
Senior

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?