2008-11-05 01:04 AM
TIM4 looses input capture events
2011-05-17 03:50 AM
Hi,
i´m using TIM4/CH4 for input capture. Because TIM4/CH3 generates PWM i have to count the update events for correct input capture calculation. I calculate the IC period like this: period= ( overflowcounter * TIM4->ARR + TIM4_CC4) - LastValueOf_TIM4_CC4; overflowcoutner = 0; LastValueOf_TIM4_CC4 = TIM4_CC4; With this calculation sometimes the result is the double of the correct value. In this case the overflowcounter is the double of the correct value. It seams that some edges were lost!!! My signal is fine (voltage/frequency). Regards, Wolfgang Beck2011-05-17 03:50 AM
Hi Wolfgang,
It is hard to make a conclusion only from a peace of code, but here some guidelines are: - Is the calculation part of ISR, or from the main loop? In the second case you indeed could have big latency in checking the capture event. - Even if both - incrementing of overflowcounter and capture processing are parts of a ISR it could happen that the both events happen very close each to other. In this case you should make a decision whether to increment the counter or not based on the value of TIM4_CC4 register.2011-05-17 03:50 AM
Hi,
Here my complete code. TIM4_SR_UPDATE and TIM4_SR_CC4 are defines for the interrupt flags (i use bitbanding). They both work fine.Code:
u32 ulPeriod, ulCounter; void TIM4_IRQHandler(void) { static u16 old=0; if (TIM4_SR_UPDATE) { TIM4_SR_UPDATE=0; ulCounter++; } if (TIM4_SR_CC4) { TIM4_SR_CC4=0; ulPeriod=((TIM4->ARR*ulCounter)+TIM4->CCR4)-old; ulCounter=0; old=TIM4->CCR4; } }2011-05-17 03:50 AM
2011-05-17 03:50 AM
Hi,
that´s right for errors +/- one timer overflow. I did your suggestion in the past an could solve this issue. I didn´t mention it to keep it simple. My problem is that the result vor ulPeriod is sometimes the DOUBLE of the correct value!!! (This error appears independent from the small capture error above) Regards2011-05-17 03:50 AM
2011-05-17 03:50 AM
Hi,
thanks a lot for your advise. Know it´s a littlebit better: As i wrote in my older posting the TIM4_SR_UPDATE and TIM4_SR_CC4 are bitbanding defines for the interrupt flags. Unfortunatelley they didn´t work, because your suggestion to reset these bits works better. My code now is:Code:
u32 ulPeriod, ulCounter; void TIM4_IRQHandler(void) { static u16 old=0; TIM_Cmd(TIM4, DISABLE); if (TIM4_SR_UPDATE) { TIM4->SR = 0xFFFE; ulCounter++; } if (TIM4_SR_CC4) { TIM4->SR = 0xFFEF; if (TIM4->CNT<TIM4->CCR4) //overflow after Capture till now? { ulPeriod=((TIM4->ARR*(ulCounter-1))+TIM4->CCR4)-old; ulCounter=1; } else { ulPeriod=((TIM4->ARR*(ulCounter ))+TIM4->CCR4)-old; ulCounter=0; } old=TIM4->CCR4; } TIM_Cmd(TIM4, ENABLE); } this code messures stable values. But there is a difference to the correct value because of stopping and starting the timer. Without these start/stop instructions the values are wrong. How can i get stable values WITHOUT stopping the timer? I know this challange seems to be easy. But i worked much time on it, and i can´t solve it till now. Regards,2011-05-17 03:50 AM
Wolfgang, it is really complicated...
If the timer runs it could overflow between checking the TIM4_SR_UPDATE and condition (TIM4->CNT < TIM4->CCR4). In this case you will wrongly use (ulCounter-1). Try to use a different condition for calculating ulPeriod. May be if you remember that you incremented ulCounter in this ISR entry and TIM4_SR_CC4 is also set check if TIM4->CCR4 is bigger than half of TIM4->ARR - in this case the capture happened before timer overflow. One more correction - the timer overflow period is (TIM4->ARR + 1), not TIM4->ARR.2011-05-17 03:50 AM
Hi,
thanks a lot for your tips. Now it seems to work!!! Here´s my codeCode:
u32 ulPeriod, ulCounter; void TIM4_IRQHandler(void) { static UW_16 old=0; BOOL bUpdateFlag=FALSE; if (TIM4_SR_UPDATE) { TIM4->SR = 0xFFFE; ulCounter++; bUpdateFlag=TRUE; } if (TIM4_SR_CC4) { TIM4->SR = 0xFFEF; if ( (bUpdateFlag==TRUE)&& (TIM4->CCR4 > (TIM4->ARR>>1)) ) { ulPeriod=(((TIM4->ARR+1)*(ulCounter-1))+TIM4->CCR4)-old; ulCounter=1; } else { ulPeriod=(((TIM4->ARR+1)*(ulCounter))+TIM4->CCR4)-old; ulCounter=0; } old=TIM4->CCR4; } } Regards, Wolfgang Beck