Timer - Input Capture Mode

📚 Lesson: Measuring Time Using Input Capture

🎯 Learning Objectives

By the end of this lesson, students will be able to:

  • Explain what input capture is and how it differs from output compare/PWM.
  • Configure a timer channel in input capture mode on the STM32G0.
  • Use interrupts to record timestamps of external events.
  • Compute the period of an incoming signal using captured timer values.
  • Apply the same technique to real sensors such as the HC‑SR04 ultrasonic module.

1️⃣ What Is Input Capture?

Input capture is a timer feature that records the current timer count when an external event occurs on a specific input pin. This allows you to measure:

  • The time between events (period)
  • The duration of a pulse (high time, low time)
  • The frequency of a signal

From Output Compare → Input Capture

In CMPE1250, students learned:

  • A timer counts up at a known rate.

  • Output compare compares the counter to a programmed value.

  • PWM toggles an output pin based on compare events.

Now we flip the direction:

  • Input Capture = “Record the timer value when something happens on a pin.”

This allows us to measure:

  • Period of a waveform
  • Frequency
  • Pulse width
  • Time between any two edges
  • Sensor timing (e.g., HC‑SR04 echo pulse)

2️⃣ How Input Capture Works (Step‑by‑Step)

  • Timer counts continuously at a known tick rate
  • In your demo: 40 MHz / 40 = 1 MHz timer clock → 1 µs per tick
  • An edge arrives on the capture pin (rising by default)
  • Hardware copies the current timer value into CCR1
  • Timer sets the CC1IF flag
  • Interrupt fires (if enabled)
  • Software reads CCR1 and computes timing differences

3️⃣ Timeline Example

3.1 Timer Setup

Timer_Init(TIM14, 40, 0);

This sets:

  • Prescaler = 40 → timer ticks at 1 MHz

  • Auto‑reload = max (0 = full 16‑bit range)

We also decide to use TIM14 channel 1, which is mapped to PC12 on the STM32G0.

GPIO_InitAlternateF(GPIOC, 12, 2); // PC12 = TIM14_CH1

3.2 Configure Channel 1 as Input

TIM14->CCMR1 &= ~TIM_CCMR1_CC1S_Msk;
TIM14->CCMR1 |= TIM_CCMR1_CC1S_0;

Meaning:

  • CC1S = 01 → CC1 is mapped to TI1 (input)

3.3 Enable Capture

TIM14->CCER |= TIM_CCER_CC1E;

3.4 Enable Interrupt

TIM14->DIER |= TIM_DIER_CC1IE;
NVIC_EnableIRQ(TIM14_IRQn);

3.5 ISR Logic

periodTicks = TIM14->CCR1 - lastEdge;
lastEdge = TIM14->CCR1;
  • Because the timer is free‑running, subtracting timestamps gives the period in microseconds.

  • The periodTicks variuble now holds the time between the last two rising edges.

  • You can convert this to frequency: frequencyHz = 1,000,000 / periodTicks;