cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F407VG sometimes reads one additional Timer overflow.

EmbeddedPepe
Associate III

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: 

  • X1 = First Capture
  • X2 = Second Capture
  • OV = number of overflow
  • ARR = Period

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:

  • The code assign to a global variable, which is not declared as volatile, and used in the main process. Volatile doesn't make any difference.
  • I disable interrupts in CRITICAL SECTIONS of other interrupts, but this should not cause the issue (?)
  • Can't access in debug mode to check value.
  • Signals are phase shifted of 90 degrees ( in this case)
  • Edit: The IRQ of various interfaces is set to the same priority.

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;

	}



}

 

0 REPLIES 0