STM32F401RE - Using Input Capture Timers to measure frequency

Hi everyone,

I’m trying to measure a couple of low frequency signals (0-10000Hz) using input capture timers on F401RE. Currently I’m trying to port over the PWMInput example from STM32CubeF4 to work with Mbed, but haven’t any luck. Feeding a 2KHz signal to TIM4 Ch2 pin (PB_7), I don’t see my interrupt handler function getting triggered at all.

#include "mbed.h"
#define TIM_USR      TIM4
#define TIM_USR_IRQ  TIM4_IRQn
#define tim_irq       TIM4_IRQHandler

DigitalOut myled(LED2);
PwmOut pwm(PB_9);
TIM_HandleTypeDef mTimUserHandle;
TIM_SlaveConfigTypeDef sSlaveConfig;
TIM_IC_InitTypeDef sConfigIC;
TIM_MasterConfigTypeDef sMasterConfig;
__IO uint32_t period;
__IO  uint32_t pulse;

void tim_init()

  mTimUserHandle.Instance = TIM_USR;
  mTimUserHandle.Init.Prescaler = 0;
  mTimUserHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
  mTimUserHandle.Init.Period = 65535;
  mTimUserHandle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  mTimUserHandle.Init.RepetitionCounter = 0;

  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET;
  sSlaveConfig.InputTrigger = TIM_TS_TI2FP2;
  sSlaveConfig.TriggerPrescaler = TIM_ICPSC_DIV1;
  sSlaveConfig.TriggerFilter = 0;
  HAL_TIM_SlaveConfigSynchronization(&mTimUserHandle, &sSlaveConfig);

  sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
  sConfigIC.ICFilter = 0;
  HAL_TIM_IC_ConfigChannel(&mTimUserHandle, &sConfigIC, TIM_CHANNEL_1);

  HAL_TIM_IC_ConfigChannel(&mTimUserHandle, &sConfigIC, TIM_CHANNEL_2);

  //Enable interrupt
  HAL_TIM_IC_Start_IT(&mTimUserHandle, TIM_CHANNEL_2);
  HAL_TIM_IC_Start_IT(&mTimUserHandle, TIM_CHANNEL_1);

void tim_irq()
  period = HAL_TIM_ReadCapturedValue(&mTimUserHandle, TIM_CHANNEL_2);
  pulse = HAL_TIM_ReadCapturedValue(&mTimUserHandle, TIM_CHANNEL_1);
  pc.printf("%d %d\n", period, pulse);
int main() {
  pwm.period(0.0005); // 2KHz to test

  while(1) {}

Are there anything missing with the way I’m setting things up?

Kind Regards,

Hi Jon,

In general don’t use printf anything which looks like interrupt. Do printings outside of interrupt.

You could try for frequency / PWM measurement just one interrupt line and timer.
When you start measurement enable interrupt. On rising edge start timer if it is not running (use flag). Then on next x rising edge and read timer time and add that to cumulative variable and take timer value to total period variable. Use also fall timer and take the same timer value and substrack previous rising timer value from fall timer value to get high time and add that to cumulative high time variable. After x time disable rise and fall interrupts. Divide both values by x to get average. Now you have average high time and period time. It is easy to convert period time to frequency.
Timer accuracy is microsecond - you should be able to reach 10 kHz measurements.


Hi Pekka,

Thank you for responding. I have considered that option, and have tested with the PWMIn library by Simon. It’s a great library but will be too slow for my application.

I did eventually port over the TIM_PWMInput example from STM32Cube to MBEDby following this simple porting guide. What mainly missing was the calling the NVIC_SetVector(), and making sure that the system clock was configured the same as the example. One other thing to keep in mind was choosing a Timer that does not collide with the one used by MBED, which was TIM5 for my board.


Hi Jonathan,
I’m trying to make a frequency counter several years.
You can see my latest program as follows.

I cannot answer you directory because;
1.You used Timer4(16bit) but I’m using Timer2(32bit)
2. You decided to use pin PB9
3.I can’t imagine how to use it(how to connect which kind of signal)
But I hope this library and sample program help your project.
I run it on F401 and check functionality.

In addition, please check my notebook.

Kenji Arai