cancel
Showing results for 
Search instead for 
Did you mean: 

Changing frequency in PWM

sajeed
Associate II
Posted on February 12, 2013 at 06:19

Hi All

I am using TIM2 for generating a pattern of pulses like pulse with 30 % duty cycle followed by pulse with 40% duty cycle and 50% duty cycle. I am able to generate it however I am not able to get the accuracy of the desired frequency. Also the frequency in the oscilloscope is varying for ex for 500 Hz it varies from 502.5 to 502.6 when it is supposed to be 500 Hz. Below is my code can someone please explain what is going wrong .

/*For Timer for channel*/

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE);

 

  /* Time Base configuration */

  TIM_TimeBaseStructure.TIM_Prescaler = 0;

  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseStructure.TIM_Period = (uint32_t)TimerPeriod;

  TIM_TimeBaseStructure.TIM_ClockDivision = 0;

  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

  /* Enable the TIM2 gloabal Interrupt */

  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

 

 

  /* Channel Configuration in PWM mode */

  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;

  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

  TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;

  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

  TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;

 

  TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;

  TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;

  ChannelPulse = (uint16_t) (((uint32_t) 5 * (TimerPeriod- 1)) / 10);  

  TIM_OCInitStructure.TIM_Pulse = ChannelPulse;

  TIM_OC2Init(TIM2, &TIM_OCInitStructure);

  /*Added Sajeed*/

  TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);

  TIM_ARRPreloadConfig(TIM2, ENABLE);  

 

  /*Enable the interrupt*/

  TIM_UpdateRequestConfig(TIM2,TIM_UpdateSource_Regular);

  TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

  TIM_GenerateEvent(TIM2,TIM_EventSource_Update);

  TimerPeriod =  (SystemCoreClock / ConstFreq) - 1;

  TimerPeriod1 = (uint32_t)((TimerPeriod  * TIMER1_PERCENT)/100.0);

  TimerPeriod2 = (uint32_t)((TimerPeriod  * TIMER2_PERCENT)/100.0);

  TimerPeriod3 = (uint32_t)(TimerPeriod - (TimerPeriod1 + TimerPeriod2));

  PulseVals[0][0] = TimerPeriod1;

  PulseVals[0][1] = (uint32_t)((30 * (TimerPeriod1 - 1)) / 100);               

 

  PulseVals[1][0] = TimerPeriod2;

  PulseVals[1][1] = (uint32_t)((40 * (TimerPeriod2 - 1)) / 100);               

  PulseVals[2][0] = TimerPeriod3;

  PulseVals[2][1] = (uint32_t)((50 * (TimerPeriod3 - 1)) / 100);               

void TIM2_IRQHandler(void)

{

  if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)

  {

      /* Clear the IT pending Bit */

      TIM2->SR = (uint16_t)~TIM_IT_Update;

      /*Load the new Timerperiod*/

      TIM2->ARR = PulseVals[PulseNo][ARR_INDEX];

      /* Set the Capture Compare Register value */

      TIM2->CCR2 = PulseVals[PulseNo][CCR_INDEX];        

      PulseNo = (PulseNo + 1)% NO_OF_PULSES;

  }

}

Later to check if varying the pulsewidth is creating the problem .

I loaded the array with constant values

  PulseVals[0][ARR_INDEX] = TimerPeriod;

  PulseVals[0][CCR_INDEX] = (uint32_t)((50 * (TimerPeriod - 1)) / 100);               

 

  PulseVals[1][ARR_INDEX] = TimerPeriod;

  PulseVals[1][CCR_INDEX] = (uint32_t)((50 * (TimerPeriod - 1)) / 100);               

  PulseVals[2][ARR_INDEX] = TimerPeriod;

  PulseVals[2][CCR_INDEX] = (uint32_t)((50 * (TimerPeriod - 1)) / 100); 

but still I get variable frequency.

Any help on this will be of great help.

Thanks in advance

Sajeed

#pwm #pwm #frequency
1 REPLY 1
sajeed
Associate II
Posted on April 16, 2013 at 15:50

I changed the workspace and found that the variation in frequency is reduced but still I am not getting the required accuracy. Can someone please let me know if you have faced similar problems.

Thanks

Sajeed