Measure pulse width using Input Capture in STM32

I have already covered how to measure the frequency using input capture in STM32 in my previous tutorial.
Today in this tutorial we will cover another feature of the input capture mode, and that is measurement of the pulse width using single channel input capture.

I am using STM32F103C8 and this method will work in every other STM32 devices too, that supports input capture.


I will try to explain in the best possible way I can. Let’s first see the CubeMx setup and I’ll explain along as we move on


As shown above the APB1 clock is at 72 MHz and I will use TIM2 for the input capture.


The picture above shows that the prescalar is set to (72-1). The reason behind this is I want to measure the pulse width in microseconds so I further divided the TIM2 clock to 1 MHz i.e. (72MHz)/72 = 1 MHz. This will give me a period of 1 us. With this setup, Timer counter will increment every 1 us.
If you want the pulse time to be in millisecond, than lower your TIMx clock to let’s say 60 MHz and set the prescalar to 60000. This is because the timer is 16 bit Timer and the maximum value it can have is 65536.

Also make sure the polarity selection is for RISING edge and interrupt is turned on. In case you don’t see the rising edge interrupt, turn on the global interrupt.


The counter starts counting from 0, it increments every 1 us (in my case) and counts upto the value set in ARR.
1.) Whenever a rising edge is detected, interrupt gets triggered and the first timestamp is captured. the polarity is changed for the falling edge now.
2.) On detecting the falling edge, another timestamp is captured.
3.) Now because the counter is counting every microsecond, the difference in these to Timestamps will also be in microseconds. Which basically gives us the time for which the pulse was high in microseconds.

But hey How will the falling edge be captured, We only enabled the rising edge ? Well inside the HAL_TIM.h, There is a function called __HAL_TIM_SET_CAPTUREPOLARITY and we can use it to change the polarity during the runtime. So basically whenever the rising edge is captured, we are going to change the polarity to falling edge and vice versa.

Some Insight into the CODE

IC_Val1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);


Captures the first Timestamp on the rising edge and stores it in the IC_Val1 variable. Once the value is successfully stored, the Polarity is now switched to the falling edge

IC_Val2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);



Second Timestamp is captured on detecting the falling edge and stored in a variable called IC_Val2. After that the counter resets to 0 and the polarity switches back to the rising edge.

Difference = IC_Val2-IC_Val1;

The difference between the two captured values gives the pulse width of the signal.


Note both the PW values

As you can see above, the value of Pulse Width (PW) is same is both on the oscilloscope, and that we calculated using the Input capture mode.

Check out the VIDEO Below

Notify of
1 Comment
Oldest Most Voted
Inline Feedbacks
View all comments