I have the L432KC Nucleo. I'm trying to measure low speeds with a 1 PPR (pulse per revolution) sensor. For low PPRs, using the Period Measurement Method is suggested. If I get the period of the signal, then I can apply the formula:

RPM = 60/(Pulse Period)

This is what I have:

In CubeMx I've set Timer 2, Channel 3 Input Capture Mode. My APB2 frequency is 1 MHz. The TIM2 prescaler is 1000 and the counter period is 10000. Everytime a pulse is given, a falling edge occurs.

Now, in the code I have:

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
  /* Prevent unused argument(s) compilation warning */

  /* NOTE : This function should not be modified, when the callback is needed,
            the HAL_TIM_IC_CaptureCallback could be implemented in the user file
  if(htim->Instance == TIM2){
      inputCaptureVal = __HAL_TIM_GetCounter(htim);

In the while loop I have another variable:

counterVal = __HAL_TIM_GetCounter(htim2);

Is this the right way to get the period? I would appreciate any guidance as this is my first time using input capture.


1 Answer 1


There's a few things wrong with it so far, so it will be difficult to get to the right answer in one go. Work on the following tips and see if you can get to somewhere with more specific questions to answer.

For starters you should heed the comments in the HAL boilerplate code: 1) implement your own HAL_TIM_IC_CaptureCallback so CubeMX doesn't overwrite your code. 2) don't use UNUSED if you use the argument.

As for the logic, the callback looks okay - you grab the timer value when the PPR trigger occurs. But then you need to use that value somewhere to do your RPM calculation.

I'm not sure what you mean by "the while loop" but the code snippet doesn't look useful. You've already called _GetCounter so no need to do it again. Just use the inputCaptureVal from your callback. Also be careful of concurrency - if you attempt to use inputCaptureVal while it is being updated in interrupt context, your calculation may be corrupted.

Finally, check your units. It sounds like your counter is in milliseconds (1MHz divided by 1000 prescaler), so to get RPM you'll need: RPM = 60000/counter.

  • \$\begingroup\$ Can I do the RPM calculation within the callback? That is, void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if(htim->Instance == TIM2){ inputCaptureVal = __HAL_TIM_GetCounter(htim); __HAL_TIM_SetCounter(htim,0); RPM = 6000/inputCaptureVal; } } \$\endgroup\$
    – user115094
    Sep 23, 2018 at 5:12
  • \$\begingroup\$ Yeah sure. In general you want to keep your callbacks very lean, but a single division is probably fine. \$\endgroup\$ Sep 23, 2018 at 12:18
  • \$\begingroup\$ A brief question.. Can I also use PWM input method where 2 channels are needed? Or just one channel in input capture mode is enough? \$\endgroup\$
    – user115094
    Sep 23, 2018 at 20:20
  • \$\begingroup\$ Brief answer: not sure what 2 channel method you're referring to. \$\endgroup\$ Sep 24, 2018 at 3:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy