cancel
Showing results for 
Search instead for 
Did you mean: 

Frequency capture in STM32F7

Edwin kaus
Associate II
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
16 REPLIES 16
RomainR.
ST Employee
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.

S.Ma
Principal
Posted on October 30, 2017 at 13:32

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

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.,

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
Up vote any posts that you find helpful, it shows what's working..
Posted on October 30, 2017 at 18:35

Yes, 32-bit, so read the manual, should have range to measure fractional Hz

http://www.st.com/content/ccc/resource/technical/document/datasheet/group3/c5/37/9c/1d/a6/09/4e/1a/DM00273119/files/DM00273119.pdf/jcr:content/translations/en.DM00273119.pdf

 
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on October 30, 2017 at 19:28

Clive One is right TIM5 is 32bit. And you need to cast

uwIC2Valuex variable to uint32_t for computation.

To achieve low frequency measurement, you can apply a prescaler to TIMER 5 internal clock

such as 

htim5.Init.Prescaler = 54 - 1; /* - 1 because Timer count from 0 to 0xFFFF FFFF */

Which give you a new TIMER resolution of APB1 = 54MHz / (54) = 1MHz ie to 1µs resolution.

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.

Posted on October 30, 2017 at 21:25

Even at 54 MHz a 32-bit timer can measure over a minute between pulses, I'd take the additional precision.

Would cast the delta computation to a double before doing the math on frequency.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on October 31, 2017 at 05:13

Take the lowest frequency to measure, make the timer overflow longer than that.

Then for as many MSB unused timer bits, crank up the timer frequency more more LSB of precision (optional)

When the frequency is too high, we usually prescale it before measurement (to measure multiple periods).

This way, the timer other channels are still useable.

Otherwise, you can also use the incoming signal as the timer's clock and measure the pulses over 1 second... or more, as Clive said.

Multiple options, best fit depends on knowing what's the application needs and constrains.

Posted on October 31, 2017 at 07:10

Hi Clive One.,

Yes TIM5 is 32bit and I have changed  Period = 0xFFFFFFFF , now I can able to measure frequency of 1Hz , 10Hz and so on . but when I tried to measure 500KHz its not working. Is there any Max frequency limit for this MCU, if so it relate to which parameter. If I suppose to measure all frequency in range of 1Hz to 1MHz what procedure should I follow. 

Can please elaborate the usage timer in input capture mode, and how it works internally . 

Thank you.,