cancel
Showing results for 
Search instead for 
Did you mean: 

Input capture timer - measure the correct frequency

mfcprog
Associate II
Posted on April 17, 2012 at 15:01

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
This discussion is locked. Please start a new topic to ask your question.
10 REPLIES 10
Cesar cfg
Associate II
Posted on February 28, 2013 at 08:09

Hi Clive: 

After searching in the NET i found this example but also we have a problem the results are not Ok .

the code:

  TIM_DeInit(TIM3 );

 /* TIM3 clock enable */

 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

 /* GPIOC clock enable */

 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE);

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;

 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;

 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

 GPIO_Init(GPIOC, &GPIO_InitStructure);

GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_0 );

GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_0 );

 GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_0 );

 GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_0 );

 /* Enable capture*/

 TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;

 TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;

 TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;

 TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;

 TIM_ICInitStructure.TIM_ICFilter = 0;

 TIM_ICInit(TIM3, &TIM_ICInitStructure);

 TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;

 TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;

 TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;

 TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;

 TIM_ICInitStructure.TIM_ICFilter = 0;

 TIM_ICInit(TIM3, &TIM_ICInitStructure);

 TIM_ICInitStructure.TIM_Channel = TIM_Channel_3;

  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;

 TIM_ICInit(TIM3, &TIM_ICInitStructure);

 TIM_ICInitStructure.TIM_Channel = TIM_Channel_4;

  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;

 TIM_ICInit(TIM3, &TIM_ICInitStructure);

 /* Enable TIM3 */

 TIM_Cmd(TIM3, ENABLE);

 /* Enable CC1-4 interrupt */

 TIM_ITConfig(TIM3, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);

 /* Clear CC1 Flag*/

 TIM_ClearFlag(TIM3, TIM_FLAG_CC1 | TIM_FLAG_CC2 | TIM_FLAG_CC3 | TIM_FLAG_CC4 );

    

   NVIC_InitStructure.NVIC_IRQChannel =  TIM3_IRQn;

   NVIC_InitStructure.NVIC_IRQChannelPriority=2;

   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

   NVIC_Init(&NVIC_InitStructure);

}

 void TIM3_IRQHandler() 

{

  TIM_ICInitTypeDef                       TIM_ICInitStructure;

 if (TIM3 ->SR & TIM_IT_CC1 ) {

  TIM3 ->SR &= (~TIM_IT_CC1 );

  if (pulseState == 0) {

   TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;

   // Any time we get a rising edge on CH1, we reset the counter. All channels are

   // phase aligned, so they all use this as a reference.

   TIM_SetCounter(TIM3,0);

  } 

  else 

  {

   TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;

   // Pull the value on the falling edge.

   ccr[0] = TIM_GetCapture1(TIM3 );

  }

  pulseState = !pulseState;

  // Reverse polarity.

  TIM_ICInit(TIM3, &TIM_ICInitStructure);

 }

 if (TIM3 ->SR & TIM_IT_CC2 )

 {

  TIM3 ->SR &= (~TIM_IT_CC2 );

  ccr[1] = TIM_GetCapture2(TIM3 );

 }

 if (TIM3 ->SR & TIM_IT_CC3 )

 {

  TIM3 ->SR &= (~TIM_IT_CC3 );

  ccr[2] = TIM_GetCapture3(TIM3 );

 }

 if (TIM3 ->SR & TIM_IT_CC4 ) 

 {

  TIM3 ->SR &= (~TIM_IT_CC4 ); 

  ccr[3] = TIM_GetCapture4(TIM3 );

 }

}