2014-04-08 07:03 AM
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
2014-04-08 07:08 AM
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.2014-04-08 07:33 AM
Ok thanks I was hopping to avoid that since it is not so practical...
I will look into it.