2016-01-21 06:58 AM
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? stm32f4292016-01-21 07:39 AM
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. JW2016-01-21 10:38 AM
Timer1 output is negated. How can I change the negation, using libraries?
2016-01-21 10:45 AM
I think you have to change your model about what's ON vs OFF
2016-01-21 11:19 AM
> 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.
JW2016-01-26 04:18 AM
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); } }2016-02-01 07:06 AM
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-2016-02-03 09:33 AM
Thanks I'll try.
2016-02-03 10:58 AM
> 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.
JW2016-02-03 06:26 PM
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).