STM32: How to use Timer Input Capture

STM32 HAL Tutorial: Measuring Signal Frequency, Period, and Pulse Width

Abstract

Learn how to configure STM32 timers for input capture using HAL. Measure signal frequency, period, and pulse width with hands-on example.

1. Introduction

Timer Input Capture (IC) is used to:

  • Measure external signal frequency

  • Measure period or pulse width

  • Trigger actions on rising/falling edges

Key concepts:

  • Timer counts with a configured prescaler

  • IC pin captures timer value when edge occurs

  • Difference between captures allows time calculation

STM32 timers support multiple channels, each configurable as input capture.

2. Prerequisites

  • STM32 board with TIMER
  • STM32CubeIDE or VS Code installed
  • Knowledge of HAL and TIMER

3. Timer Output Compare Overview

Parameter

Description

Timer

Counts clock cycles at configured frequency

Prescaler

Reduces timer clock to match expected signal

Input channel

GPIO pin connected to signal

Polarity

Rising, Falling, or Both edges

Capture register

Stores timer value at input edge

 

The hardware block diagram is usually shown like this, where the input signal goes into the TIMx_CH1:

In Input capture mode, the Capture/Compare Registers are used to latch the value of the Counter after a transition detected by the corresponding ICx signal. When a capture occurs, the corresponding flag is set and an interrupt or a DMA request can be sent if they are enabled.

The input capture module is used to capture the value of the counter after a transition is detected by the corresponding input channel. To get the external signal period, two consecutive captures are needed. The period is calculated by subtracting these two values:

  • Period = Capture(1) /(TIMx_CLK *(PSC+1)*(ICxPSC)*polarity_index(2))

The capture difference between two consecutive captures CCRx_tn and CCRx_tn+1:

  • If CCRx_tn < CCRx_tn+1: capture = CCRx_tn+1 – CCRx_tn
  • If CCRx_tn > CCRx_tn+1: capture = (ARR_max – CCRx_tn) + CCRx_tn+1.

The polarity index is 1 if the rising or falling edge is used, and 2 if both edges are used.

4. CubeMX Configuration

1. Select Timer (e.g., TIM2)

2. Set Counter Mode = Up

3. Enable Input Capture Mode on channel 1

4. Set IC Polarity = Rising (or as needed)

5. Configure GPIO pin PA5 as alternate function for TIMx_CH1

6. Configure TIM3 as the PWM source

7. Configure the Clock tab

8. Generate HAL code

5. HAL Example: Timer Input Capture

				
					/* USER CODE BEGIN PV */
uint32_t u32CaptureValue = 0;
uint32_t u32PreviousCaptureValue = 0;
uint32_t u32Frequency = 0;
/* USER CODE END PV */

				
			
				
					/* USER CODE BEGIN 2 */
 HAL_TIM_Base_Start(&htim2);
 HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
 HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
 /* USER CODE END 2 */

				
			
				
					/* USER CODE BEGIN 4 */
uint32_t u32Delta = 0;
uint32_t u32ICValue1 = 0;
uint32_t u32ICValue2 = 0;
uint8_t u8FirstCapture = 0;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) {
	if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
	{
#ifdef SIMPLE_MEASUREMENT
		u32CaptureValue = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
		u32Frequency = HAL_RCC_GetPCLK1Freq()/ (u32CaptureValue - u32PreviousCaptureValue);
		u32PreviousCaptureValue = u32CaptureValue;
#else
		if(u8FirstCapture == 0)
		{
			u32ICValue1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
			u8FirstCapture = 1;
		}
		else
		{
			u32ICValue2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
			if(u32ICValue2 > u32ICValue1) //roll over did not happen
			{
				u32Delta = u32ICValue2 - u32ICValue1;
			}
			else
			{
				u32Delta = (0xFFFFFFFF - u32ICValue1) + u32ICValue2; //roll over happened
			}
			u32Frequency = HAL_RCC_GetPCLK1Freq()/ u32Delta;
			htim->Instance->CNT = 0; //reset the counter
			u8FirstCapture = 0;
		}
#endif
	}
	// this code does not deal with overflow
}
/* USER CODE END 4 */

				
			
  • HAL_TIM_IC_Start_IT() enables input capture interrupt

  • HAL_TIM_IC_CaptureCallback() is triggered on edge capture

  • Frequency or period can be calculated from timer counts

6. Hands-On Lab Example

  1. Connect a square wave signal to TIM2_CH1 pin

  2. Initialize timer in input capture mode

  3. Enable interrupts for input capture

  4. Observe captured values in u32ICValue1 and u32ICValue2

  5. Calculate signal frequency and period using formula

  6. Optional: Capture pulse width by measuring time between rising and falling edges

Tip: For precise measurement, choose prescaler to scale timer clock so that timer doesn’t overflow

7. Advantages

  • Measures external signals accurately

  • Works for frequency, period, and pulse width

  • Can trigger events in firmware

  • Can be combined with DMA for high-speed capture

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top