cancel
Showing results for 
Search instead for 
Did you mean: 

Make PWM Pulses offset from each other with same Duty Cycle

Rogers.Gary
Senior II
Posted on January 27, 2015 at 19:59

Hello,

Based on this very good example (below from clive1) on how to set up the timers for low frequencies, I'm trying to now adjust the PWM signal from each output. Note that the configuration has only the mode changed from ''TIM_OCMode_Toggle'' to ''TIM_OCMode_PWM1'' which now generates the PWM signals. To create the duty cycle, I did this: TIM_OCInitStructure.TIM_Pulse = (uint16_t)(Period * dutyCycle); Where dutyCycle is a value between 0.1 and 0.5, it works fine. However, what I really need is the second channel to have exactly the same duty cycle, but offset by some interval in milliseconds (or ratio of period), this to drive an H-Bridge. The only result I can get is that the second channel just changes the duty cycle. Is there any way to do this in one setup, or do I need another Timer set up the same way and trigger the second one relative to the first? (see comments in sample below) Thank you! Help appreciated as always. /********************************************************************/

void TIM4_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
int Prescaler, Period;
Prescaler = ((SystemCoreClock / 2) / 20000); // 20 KHz timebase, assumes APB1 H/4 TIMCLK4 H/2
Period = 20000 / 1; // 1 Hz - 1 second on, 1 second off duty
// The toggle halves the frequency, a phase shift of 90 degrees (1/4) is 180 degrees (1/2)
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = Period - 1;
TIM_TimeBaseStructure.TIM_Prescaler = Prescaler - 1;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
/* Output Compare Toggle Mode configuration: Channel 1, 2 & 3 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_Pulse = (uint16_t)(Period * dutyCycle);

TIM_OC1Init(TIM4, &TIM_OCInitStructure);
TIM_OCInitStructure.TIM_Pulse = ????? - NEED SAME DUTY CYCLE BUT LAGGING CHANNEL 1

TIM_OC2Init(TIM4, &TIM_OCInitStructure);

 

/* TIM4 enable counter */
TIM_Cmd(TIM4, ENABLE);
}

#stm32f4-timers-pmw
2 REPLIES 2
Posted on January 27, 2015 at 21:41

This wades off in to areas of the timer design I really don't like, or understand well. Or may be I understand they don't work well...

I'd perhaps try using two timers of identical configuration, and achieve the phase shift via different TIMx->CNT settings with the desired offset. Then enable both with some tight code. There are perhaps ways to get a common trigger or sync. But you'd probably not want a reset.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Rogers.Gary
Senior II
Posted on January 27, 2015 at 22:33

Or is it you know darn well that some people don't understand them well? Well? 8-)

Your suggestion seems like a good one, and I alluded to that in my original post regarding a second timer. Using another Cortex device, the LPC1768, I did something similar, but using RTOS to place a delay of x milliseconds after the first timer started to send the next channel. Accurate to the millisecond.

The only question left is, after configuring the timers as above, can you tell me which registers for (as inTIMx->???) I would modify directly to change PERIOD, PRESCALER and TIM_PULSE, such that I do not have to go through the initialization again? I need to do this on the fly to adjust the frequency and pulse width.

When I look through the documentation there's a gazillion things on registers, so a hint as to which ones is appreciated.

Thanks clive1..