cancel
Showing results for 
Search instead for 
Did you mean: 

How to generate PWM output using timers on PB0 and PB1

marco2
Associate III
Posted on January 21, 2016 at 15:58

Hi all,

I have the stm32F429 micro and I need to generate 2 PWM Output (see below) using pin PB0 and PB1. I tried with toggle mode and TM3 on ch3 and 4, but the duty is 50/50 and is not good. There is a phase shift of 2,4us. Do you have any suggestions?

0690X00000605KoQAI.png

stm32f429

11 REPLIES 11
Posted on January 21, 2016 at 16:39

There is only one counting element in a timer, so you can't produce this using a single timer.

You can chain TIM1 and TIM3, running with the same period (they are on different APB buses so you might need to think about the particular ARR setting for both), triggering one (with the phase difference set in CNT) from the other. Don't forget to set TIM1_BDTR.MOE for TIM1 and don't forget that it's the inverted outputs of TIM1 on PB0/PB1, so you might compensate for this by different timing or setting the other PWM mode or negating by CCER.CCxNP.

Do this step by step - first achieve the two PWMs on two timers, then learn how to chain them/trigger.

JW

marco2
Associate III
Posted on January 21, 2016 at 19:38

Timer1 output is negated. How can I change the negation, using libraries?

Posted on January 21, 2016 at 19:45

I think you have to change your model about what's ON vs OFF

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Posted on January 21, 2016 at 20:19

> Timer1 output is negated. How can I change the negation, using libraries?

Well, use those functions of those libraries which allow you to achieve different timing, or to set the other type of PWM, or setting of CCER.CCxNP.

JW

marco2
Associate III
Posted on January 26, 2016 at 13:18

Below the code I use. The problem is that I have jittering between the two generated PWN waves. Can anyone tell me ho w can I solve this?

void TIM3_IOConfig(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

/* GPIOB Configuration: TIM3 CH3 (PB0) and TIM3 CH4 (PB1) */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;

GPIO_Init(GPIOB, &GPIO_InitStructure);

/* Connect TIM3 pins to AF2 */

GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, GPIO_AF_TIM3);

}

void Delay(__IO uint32_t nTime)

{

TimingDelay = nTime;

while(TimingDelay != 0);

}

void TimingDelay_Decrement(void)

{

if (TimingDelay != 0x00)

{

TimingDelay--;

}

}

void TIM1_Configuration(void)

{

TimerPeriod = (SystemCoreClock / 208000) - 1;

Channel2Pulse = (uint16_t) (((uint32_t) 33 * (TimerPeriod - 1)) / 100);

/* Time Base configuration */

TIM_TimeBaseStructure.TIM_Prescaler = 0;

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseStructure.TIM_Period = TimerPeriod;

TIM_TimeBaseStructure.TIM_ClockDivision = 0;

TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;

TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;

TIM_OCInitStructure.TIM_Pulse = Channel2Pulse;

TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;

TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;

TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;

TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;

TIM_OC2Init(TIM1, &TIM_OCInitStructure);

/* Automatic Output enable, Break, dead time and lock configuration*/

TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;

TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;

TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;

TIM_BDTRInitStructure.TIM_DeadTime = 0;

TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;

TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;

TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;

TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);

}

void TIM3_Configuration()

{

TimerPeriod /= 2;

Channel3Pulse = (uint16_t) (((uint32_t) 66 * (TimerPeriod - 1)) / 100);

/* Time base configuration */

TIM_TimeBaseStructure.TIM_Prescaler = 0;

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseStructure.TIM_Period = TimerPeriod;

TIM_TimeBaseStructure.TIM_ClockDivision = 0;

TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;

TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;

TIM_OCInitStructure.TIM_Pulse = Channel3Pulse;

TIM_OCInitStructure.TIM_OCPolarity = TIM_OCNPolarity_Low;

TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;

TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;

TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;

TIM_OC4Init(TIM3, &TIM_OCInitStructure);

TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;

TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;

TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;

TIM_BDTRInitStructure.TIM_DeadTime = 0;

TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;

TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;

TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;

TIM_BDTRConfig(TIM3, &TIM_BDTRInitStructure);

}

void TIM1_TIM3_Enable(uint8_t delay_10uc)

{

/* TIM1 counter enable */

TIM_Cmd(TIM1, ENABLE);

TIM_CtrlPWMOutputs(TIM1, ENABLE);

//delay

/* TIM3 counter enable */

TIM_Cmd(TIM3, ENABLE);

TIM_CtrlPWMOutputs(TIM3, ENABLE);

}

void TIM1_TIM3_Disable(uint8_t delay_10uc)

{

/* TIM1 counter enable */

TIM_Cmd(TIM1, DISABLE);

TIM_CtrlPWMOutputs(TIM1, DISABLE);

//delay

/* TIM3 counter enable */

TIM_Cmd(TIM3, DISABLE);

TIM_CtrlPWMOutputs(TIM3, DISABLE);

}

void TIM1_IOConfig(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

/*GPIOB clocks enable */

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

/* TIM1 clock enable */

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;

GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_PinAFConfig(GPIOB, GPIO_PinSource0, GPIO_AF_TIM1);

}

int main(void)

{

STM_EVAL_LEDInit(LED3);

STM_EVAL_LEDOn(LED3);

STM_EVAL_LEDOff(LED3);

TIM1_IOConfig();

TIM3_IOConfig();

TIM1_Configuration();

TIM3_Configuration();

TIM1_TIM3_Enable(0);

if (SysTick_Config(SystemCoreClock / 1000))

{

/* Capture error */

while (1);

}

/* Infinite loop */

while (1)

{

STM_EVAL_LEDToggle(LED3);

Delay(500);

}

}

Walid FTITI_O
Senior II
Posted on February 01, 2016 at 16:06

Hi stevasway,

Try to do this by generating two complementary signals with a dead time inserted.

To get more information about this topic, read the relevant section in the reference manual; TIM1/TIM8 chapter. And check the example in standard library '' TIM_ComplementarySignals '' following this path : Project\STM32F4xx_StdPeriph_Examples\TIM\TIM_ComplementarySignals

-Hannibal-
marco2
Associate III
Posted on February 03, 2016 at 18:33

Thanks I'll try.

Posted on February 03, 2016 at 19:58

> Subject: How to generate PWM output using timers on PB0 and PB1

> Try to do this by generating two complementary signals with a dead time inserted.

How? There is no complementary-timer-channel-pin-pair on PB0 and PB1.

JW

gregstm
Senior II
Posted on February 04, 2016 at 03:26

A possible alternative..... use 32 bit DMA to the GPIOB BSRR register (in circular mode) to send the required bit pattern (set up in an array beforehand).