AnsweredAssumed Answered

Changing frequency in PWM

Question asked by m.a.sajeed on Feb 12, 2013
Latest reply on Apr 16, 2013 by m.a.sajeed
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

Outcomes