cancel
Showing results for 
Search instead for 
Did you mean: 

Polarity PWM on STM32F4

thoman92
Associate
Posted on April 08, 2014 at 16:03

Hello!

I am trying to create two square PWMs (duty 50%) with a controlled phase shift (0° to 90°). I am currently using TIM4 with 2 channels set on TIM_OCMode_Toggle and it is working OK. The problem is hapening randomly when I try to change phase shift, I will get the phase of on of the PWM reversed (180° + my phase shift). Is there a way to prevent this phenomenon? Maybee just a way to reset the state of the Pins when updating the Phase Shift would be nice... here is my time initialisation if it is usefull:

void
Config_Timers(
void
) 
{ 
// Create Hardware setup structures 
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; 
TIM_OCInitTypeDef TIM_OCInitStruct; 
// First activate the Peripherals Clocks 
RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM4, ENABLE ); 
// Set Timer 4 Period to 1Hz by default 
PWM_Period = 1000; 
TIM_TimeBaseStructInit( &TIM_TimeBaseInitStruct ); 
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; 
TIM_TimeBaseInitStruct.TIM_Prescaler = 0; 
TIM_TimeBaseInitStruct.TIM_Period = PWM_Period - 1; 
TIM_TimeBaseInit( TIM4, &TIM_TimeBaseInitStruct ); 
// Set Output Compare on Timer4 
// Initialise PWM structure 
TIM_OCStructInit( &TIM_OCInitStruct ); 
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_Toggle; 
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable; 
TIM_OCInitStruct.TIM_OutputNState = TIM_OutputNState_Disable; 
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_Low; 
TIM_OCInitStruct.TIM_OCNPolarity = TIM_OCNPolarity_High; 
TIM_OCInitStruct.TIM_OCIdleState = TIM_OCIdleState_Set; 
TIM_OCInitStruct.TIM_OCNIdleState = TIM_OCIdleState_Reset; 
// Config Channel 3 
TIM_OCInitStruct.TIM_Pulse = 1; 
// start time 
TIM_OC3Init( TIM4, &TIM_OCInitStruct 
// Config Channel 4 
TIM_OCInitStruct.TIM_Pulse = 1; 
// start time 
TIM_OC4Init( TIM4, &TIM_OCInitStruct ); 
// Enable the Timer 
TIM_Cmd( TIM4, ENABLE ); 
return
; 
} 
void
PWM_SetFrequency(unsigned 
int
Frequency_kHz) 
{ 
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; 
PWM_Period = 42000000/(
long
)Frequency_kHz; 
TIM_TimeBaseStructInit( &TIM_TimeBaseInitStruct ); 
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; 
TIM_TimeBaseInitStruct.TIM_Prescaler = 1 - 1; 
TIM_TimeBaseInitStruct.TIM_Period = PWM_Period - 1; 
TIM_TimeBaseInit( TIM4, &TIM_TimeBaseInitStruct ); 
// Set Output Compare on Timer4 
return
; 
} 
void
PWM_SetOffset(unsigned 
char
Offset) 
{ 
int
result; 
if
(Offset != PWM_Offset) 
{ 
PWM_Offset = Offset; 
// Change the starting time of the PWM 
result = (
int
)(((
float
)Offset/(
float
)255) * (
float
)(PWM_Period/2)); 
if
(result == 0) result =1; 
else
if
(result == PWM_Period) result = PWM_Period-1; 
TIM4->CCR3 = 1; 
TIM4->CCR4 = result; 
} 
return
; 
}

Best Regards, Thomas
2 REPLIES 2
Posted on April 08, 2014 at 16:08

Is there a way to prevent this phenomenon?

Perhaps by paying attention to the current phase of TIMx->CNT before advancing/retarding TIMx->CCRx with respect to it, and each other. Or performing the change at the update interrupt.

Also watch which high/low duty cycle you are in.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
thoman92
Associate
Posted on April 08, 2014 at 16:33

Ok thanks I was hopping to avoid that since it is not so practical...

I will look into it.