AnsweredAssumed Answered

Input capture timer - measure the correct frequency

Question asked by bauer.hans on Apr 17, 2012
Latest reply on Feb 28, 2013 by Amor.Ben_amor
Hi,

I want to capture a signal with 30Hz frequency by a timer input capture. The timer is already working but the measured frequency is not 30Hz. I always measure a frequency of 29.85Hz or 30.3Hz. Are there any mistakes according to may selected period or prescaler values? By the way I`m using the STM32F103XC processor.


void TIMER_InitInputCaptureTimer(TIM_TypeDef* TIMx, unsigned short tmrchannel, unsigned short period)
{
  TIM_ICInitTypeDef  TIM_ICInitStructure;
 TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
 unsigned short PrescalerValue = (unsigned short) (SYSTEM_TIMERCLOCK / TIMER_TAKT) - 1;

 TIM_TimeBaseStructure.TIM_Period       = period -1; //65535;
   TIM_TimeBaseStructure.TIM_Prescaler     = (TIMER_TAKT - 1); //0;
   TIM_TimeBaseStructure.TIM_ClockDivision    = 0;
   TIM_TimeBaseStructure.TIM_CounterMode     = TIM_CounterMode_Up;
   TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure);

 TIM_PrescalerConfig(TIMx, PrescalerValue, TIM_PSCReloadMode_Immediate);

 TIM_ICInitStructure.TIM_Channel = tmrchannel; //TIM_Channel_3;
   TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
   TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
   TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;      // Div:1, every edge
   TIM_ICInitStructure.TIM_ICFilter = 0x3;
   TIM_ICInit(TIMx, &TIM_ICInitStructure);

 /* Enable the CC3 Interrupt Request */
   TIM_ClearITPendingBit(TIM1, tmrchannel); //TIM_IT_CC3);
 TIM_ITConfig(TIMx, tmrchannel, ENABLE);

}


void TIMER_Init(TIM_TypeDef* TIMx, unsigned char mode, unsigned short tmrchannel, unsigned char irqchannel,
 unsigned short period, unsigned short fps)
{
 NVIC_InitTypeDef NVIC_InitStructure;

 switch(mode)
 {
 case TMR_MODE_UPD:
  TIMER_InitUpdTimer(TIMx, tmrchannel, fps);
  break;

 case TMR_MODE_INPUTCAPTURE:
  TIMER_InitInputCaptureTimer(TIMx, tmrchannel, period);
  break;

 default:
  return;
 }
 
 
 NVIC_InitStructure.NVIC_IRQChannel = irqchannel; //TIM1_CC_IRQChannel;
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);
}


And that`s my call of the timer function:

volatile unsigned short IC3ReadValue1 = 0, IC3ReadValue2 = 0;
volatile unsigned short CaptureNumber = 0;
volatile unsigned int Capture = 0;
volatile unsigned int TIM1Freq = 0; 

int d2i(float d)
{
 float value;
 value = d;
 value /= 10;
 value += 0.5;
 return value;
}


TIMER_Init(TIM1, TMR_MODE_INPUTCAPTURE, TIM_Channel_3, TIM1_CC_IRQChannel, 64800, 0);
TIM_Cmd(TIM1, ENABLE);


My Interrupt ISR:

void TIM1_CC_IRQHandler (void)
{
   TIM1->SR & TIM_IT_CC3)
 {  /* capture timer */
    
  //clear pending bit
  TIM1->SR = (unsigned short)~TIM_FLAG_CC3;

  if(CaptureNumber == 0)
     {
       /* Get the Input Capture value */
       IC3ReadValue1 = TIM1->CCR3;
       CaptureNumber = 1;
     }
  else if(CaptureNumber == 1)
     {
       /* Get the Input Capture value */
       IC3ReadValue2 = TIM1->CCR3;

       /* Capture computation */
       if (IC3ReadValue2 > IC3ReadValue1)
       {
         Capture = (IC3ReadValue2 - IC3ReadValue1);
       }
       else
       {
         Capture = ((0xFFFF - IC3ReadValue1) + IC3ReadValue2);
       }
       /* Frequency computation */
    TIM1Freq =  d2i ((float)(2 * TIMER_TAKT * 10 / Capture));

          CaptureNumber = 0;
   }

  /* flag: new rising edge interrupt INTR received */
  captureFlag++;

 
 /* clear all flags */   
 TIM1->SR = ~0xFF;  
 }
}



I hope someone of you could give me some hints to measure the exact frequency of the input signal.

best regards
Hans

Outcomes