Skip to main content
Edwin kaus
Associate III
October 30, 2017
Question

Frequency capture in STM32F7

  • October 30, 2017
  • 16 replies
  • 2441 views
Posted on October 30, 2017 at 13:15

I am working with STM32F765BIT MCU in our custom board, In that I need to measure some external signal frequency.

I am using timer in input capture mode to measure the frequency. I have taken some reference example and made same changes in my code. With that i am able to get capture complete call back interrupt ,but getting zero frequency. 

I am running MCU at 216MHz clock and using channel1 of Timer5 as input capture mode.

I am not able to get what could be the problem, Can anyone please help me in resolving this issue.

/**************************************************Init ************************************************************/

static void MX_TIM5_Init(void)

{

TIM_MasterConfigTypeDef sMasterConfig;

TIM_IC_InitTypeDef sConfigIC;

htim5.Instance = TIM5;

htim5.Init.Prescaler = 0;

htim5.Init.CounterMode = TIM_COUNTERMODE_UP;

htim5.Init.Period = 0;

htim5.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

htim5.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

if (HAL_TIM_IC_Init(&htim5) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;

sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

if (HAL_TIMEx_MasterConfigSynchronization(&htim5, &sMasterConfig) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;

sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;

sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;

sConfigIC.ICFilter = 15;

if (HAL_TIM_IC_ConfigChannel(&htim5, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

}

/**********************************************call back function****************************************************************/

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)

{

if(htim != &htim5 )

return;

if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)

{

if(uhCaptureIndex == 0)

{

/* Get the 1st Input Capture value */

uwIC2Value1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);

uhCaptureIndex = 1;

}

else if(uhCaptureIndex == 1)

{

/* Get the 2nd Input Capture value */

uwIC2Value2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);

/* Capture computation */

if (uwIC2Value2 > uwIC2Value1)

{

uwDiffCapture = (uwIC2Value2 - uwIC2Value1);

}

else if (uwIC2Value2 < uwIC2Value1)

{

/* 0xFFFF is max TIM3_CCRx value */

uwDiffCapture = ((0xFFFF - uwIC2Value1) + uwIC2Value2) + 1;

}

else

{

/* If capture values are equal, we have reached the limit of frequency

measures */

Error_Handler();

}

/* Frequency computation: for this example TIMx (TIM3) is clocked by

2xAPB1Clk */

uwFrequency = (2*HAL_RCC_GetPCLK1Freq()) / uwDiffCapture;

    printf('Frequency = %d\r\n',uwFrequency);

  uhCaptureIndex = 0;

}

}

}

/**************************************************************************************************************/

 The control is coming to this call back function but I am getting uwDiffCaputre as zero.

Thank you.,

#timer #stm32f7
This topic has been closed for replies.

16 replies

RomainR.
ST Employee
October 30, 2017
Posted on October 30, 2017 at 13:29

Hello,

See your TIM5 configuration structure.

htim5.Init.Period = 0;

You should set a larger Period (depending of your maximum period of input signal)

On your F765 device TIM5 is clocked by APB1 at 54MHz.

As you don't set a prescaler, your timer count at 1/54MHz.  

Can you try with 

htim5.Init.Period = 0xFFFF and manage a second callback to manage Period Timeout.

Regards

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
Edwin kaus
Associate III
October 30, 2017
Posted on October 30, 2017 at 18:15

Thank you for the reply.

I have made suggested changes and now its absolutely working fine , I am able capture frequency of input signal. But it works only in the range of 3Khz to 999Khz. What I suppose to do if I want to measure very lower frequency in the range of 50Hz ,100hz and so on.   

Thank you.,

Tesla DeLorean
Guru
October 30, 2017
Posted on October 30, 2017 at 18:31

Isn't TIM5 a 32-bit timer? Use the range properly, ie Period = 0xFFFFFFFF

Also this code is overly complicated, unsigned math of appropriately size variables will wrap automatically

if (uwIC2Value2 > uwIC2Value1)

{

uwDiffCapture = (uwIC2Value2 - uwIC2Value1);

}

else if (uwIC2Value2 < uwIC2Value1)

{

/* 0xFFFF is max TIM3_CCRx value */

uwDiffCapture = ((0xFFFF - uwIC2Value1) + uwIC2Value2) + 1;

}

This will work for ALL values, assuming you use uint16_t or uint32_t depending on the TIM range

uwDiffCapture = (uwIC2Value2 - uwIC2Value1);

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
S.Ma
Principal
October 30, 2017
Posted on October 30, 2017 at 13:32

What is the incoming frequency range vs the timer clock frequency?

waclawek.jan
Super User
October 31, 2017
Posted on October 31, 2017 at 10:48

... or speed up your code, by setting higher optimization setting of compiler, and getting rid of superfluous code (aka Cube).

JW

AVI-crak
Senior
October 31, 2017
Posted on October 31, 2017 at 12:28

There are two methods for measuring frequency.

1) Measure the duration of the low and high state of the input, followed by the accumulation of the result and the calculation of the mean value. This method is suitable for changing low frequencies. The accumulated result is processed: first, the total average value is found, and then each report is multiplied by the logarithmic difference between the mean and the current value modulo. This cuts noisy distortions much higher or lower than the average level - peak values beyond the boundaries. This filtering is performed three to four times - until averaging is complete. In fact, the code works in real time, between capturing a new piece of data.

2) Measurement of the number of clock pulses per precise time interval. Filtering is possible, but its work will be visually noticeable. Because the length of time is chosen close to one second. This method allows you to measure high frequencies.

Both methods can be executed simultaneously, the processor resources are sufficient for such operations.

Variant when a phase detector is required to extract information from a frequency-modulated signal - other filters are used, but the general meaning remains the same.

Oliver Sedlacek
Senior
November 2, 2017
Posted on November 02, 2017 at 10:54

If the diff is always zero but the ISR is being triggered then there must be a program flow bug. I didn't find a specific bug, but I would simplify the code. The ISR has a state, which is whether it is expecting the first or second edge (stored in uhCaptureIndex). The code would be simpler and hence easier to debug if the state were eliminated. This can be done by storing the previous capture time and always subtracting that from the TIM capture time (which is then stored as the previous time).