cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F407 update PWM duty cycle after complete PWM period only

vindhyachal
Associate II

I have made a code for PWM for STM32F407. It is working fine for generating PWM.

1. Currently what happens is I have made a PWM period of 5seconds in total.

2. Suppose in code I call TIM_SetCompare2(TIM9 , 32767), now outout will be 2.5 seconds on & 2.5 seconds off.

where 32767 is 50% duty cycle, & 65535 is 100% duty cycle.

3. Now suppose on time of 2.5seconds is running & I suddenly change TIM_SetCompare2(TIM9 , 10000), it will now be roughly 15% on and 15% off.

This happens even if previous 2.5 duty cycle was running

4. I want that next compare value updates only after completion of first compare match cycle.

5. I have no way to sync both, because compare value is coming from a another setup at random stage, & when a new compare value comes, I have to set a display to user, and it should run for that compare cycle only, not to get updated by new compare cycle.

6. How to do it?

void initialize_pwm(void) 
{
    uint16_t Channel2Pulse = 0U;    
    
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_OCInitTypeDef  TIM_OCInitStructure;
    
/* GPIOA Configuration: Channel 2 as alternate function push-pull */
    RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOA , ENABLE);
    GPIO_InitStructure.GPIO_Pin    = GPIO_Pin_3;
    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(GPIOA, &GPIO_InitStructure);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_TIM9);
      
/* TIM9 clock enable */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9 , ENABLE);
  
/* Time Base configuration */
    TIM_TimeBaseStructure.TIM_Prescaler = 12816U;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseStructure.TIM_Period = 65535;//PWM_PERIOD_VALUE;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM9, &TIM_TimeBaseStructure);
 
/* Channel 2 Configuration in PWM mode */
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
    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_Reset;
    TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
    TIM_OC2Init(TIM9, &TIM_OCInitStructure);
 
/* TIM9 counter enable */
    TIM_Cmd(TIM9, ENABLE);
 
/* TIM9 Main Output Enable */
    TIM_CtrlPWMOutputs(TIM9, ENABLE); 
 
    TIM_SetCompare2(TIM9 , 32767);
 
} /* function ends here */ 

1 REPLY 1
berendi
Principal

Set the TIM_CCMR1_OC2PE (output compare 2 preload enable) bit. Then the effective compare value will be updated at the next update event, i.e. when the counter overflows. Is that what you want?

You will have to rearrange your code to set the first compare value before enabling the preload bit, otherwise it will not be effective in the very first cycle.