Input capture timer - measure the correct frequency
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