2025-01-22 03:05 AM - last edited on 2025-01-22 03:35 AM by Andrew Neil
Hello!
I'm writing a software to read the frequency that I receive on two channels of the same 16bit timer. (Channel 1 and Channel 2)
The channels are set on rising edge captures. Timer prescaler is set 21 - 1. ARR = 0xFFFF.
Given:
Formula = X2 + (OV * ARR) - X1.
I have the TIM interrupt where I basically read the SR register for which interrupt got fired, clear the flag and proceed to do the operations.
The problem is that given the same frequency (with a frequency generator ) at 400hz I read 400hz (most of the time) but I sometimes read 52ish HZ which is basically the formula with an additional overflow, although I reset the overflow counter at every first capture. Sometimes the problem is on CH1, sometimes on CH2.
Additional info:
code below:
void TIM4_IRQHandler_FRQ(void)
{
static uint8_t CH1_capture_flag = 0;
static uint8_t CH2_capture_flag = 0;
static uint32_t CH1_captures[2] = {0, 0};
static uint32_t CH2_captures[2] = {0, 0};
static uint32_t result_ch1 = 0;
static uint32_t result_ch2 = 0;
tmyFRQ2Input *p = &Z; //(Global variable, not declared as volatile)
if( TIM4->SR & TIM_FLAG_Update )// overflow occurs
{
TIM4->SR = ~TIM_FLAG_Update;
if(p->overflow < 0xFFFFFFFF)
{
p->overflow++;
}
if(p->overflow2 < 0xFFFFFFF)
{
p->overflow2++;
}
}
if(TIM4->SR & TIM_FLAG_CC1)
{
TIM4->SR = ~TIM_FLAG_CC1;
p->pulseCount1++;
if ( CH1_capture_flag == 0)
{
p->overflow = 0;
CH1_captures[0] = TIM4->CCR1;
CH1_capture_flag = 1;
}
else
{
CH1_captures[1] = TIM4->CCR1;
result_ch1 = (uint32_t)((p->my_clk) / CH1_captures[1] + (p->overflow * p->TIM_TimeBaseStructure.TIM_Period ) - CH1_captures[0] + 1);
CH1_capture_flag = 0;
}
}
}
if(TIM4->SR & TIM_FLAG_CC2)
{
TIM4->SR = ~TIM_FLAG_CC2;
p->pulseCount2++;
if ( CH2_capture_flag == 0 )
{
p->overflow2 = 0;
CH2_captures[0] = TIM4->CCR2;
CH2_capture_flag = 1;
}
else
{
CH2_captures[1] = TIM4->CCR2;
result_ch2 = ((p->my_clk )/ CH2_captures[1] + (p->overflow2 * p->TIM_TimeBaseStructure.TIM_Period) - CH2_captures[0] + 1;);
CH2_capture_flag = 0;
}
}
}
//Both calculation are done
if ( result_ch1 != 0 && result_ch2 != 0)
{
p->Frequency = result_ch1;
p->Frequency2 = result_ch2;
result_ch1 = 0;
result_ch2 = 0;
}
}
2025-01-22 06:34 AM
Forget the overflow, simply subtract two capture values and store the result as uint16_t.
2025-01-22 06:41 AM
But if the signal changes to (for example 5hz) how do I manage to calculate it?
2025-01-22 07:56 AM
First, decide on the input frequency range, then setup the timer to cover the required range. Overflow counting in software is almost never reliable.
2025-01-22 07:58 AM
Unfortunately the range depends. It could go from 1 hz to 10khz or more. Can't do much about that.