📚 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
periodTicksvariuble now holds the time between the last two rising edges. -
You can convert this to frequency:
frequencyHz = 1,000,000 / periodTicks;