Timer - Input PWM Mode

📚 Lesson: Measuring Period and Duty Cycle Using Input PWM Mode (Multi‑Channel Capture)

🎯 Learning Objectives

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

  • Explain how Input PWM Mode differs from basic input capture.

  • Configure a timer with two capture channels to measure:
    • Period
    • High‑time
    • Duty cycle
  • Understand how the timer internally routes TI1/TI2 signals.

  • Implement a dual‑channel capture ISR.

  • Apply this to real‑world signals (PWM, servo pulses, tachometers).

1️⃣ Why Input PWM Mode Exists?

In the previous lesson, we captured only the period by measuring rising‑to‑rising (or falling-to-falling) edges. But many real signals encode information in duty cycle, not just frequency:

  • RC servo control pulses
  • Tachometer outputs
  • PWM‑encoded sensors
  • Motor controllers
  • Communication protocols using pulse width

To measure duty cycle, you need:

  • Period (rising → rising)

  • High time (rising → falling)

\[\text{Duty Cycle} = \frac{T_{\text{HIGH}}}{T_{\text{PERIOD}}} \times 100\] \[\text{Duty Cycle} = \frac{\text{CCR}_{\text{fall}} - \text{CCR}_{\text{rise}}} {\text{CCR}_{\text{rise}} - \text{CCR}_{\text{prev rise}}} \times 100\]

You could do this manually by interrupting on both rising and falling edges and checking the GPIO Pin, but STM32 timers give you something better:

Input PWM Mode = two capture channels working together on one input pin

  • Channel 1 captures rising edges → period
  • Channel 2 captures falling edges → high time

Both channels are synchronized by hardware.

2️⃣ How Input PWM Mode Works (Block Diagram)

A simple conceptual diagram:

flowchart LR
    A[External PWM Signal] --> B(TI1 Input)
    B --> C[IC1
Rising Edge Capture
→ CCR1] B --> D[IC2
Falling Edge Capture
→ CCR2] C --> E[Period Measurement] D --> F[High‑Time Measurement] E --> G[Duty Cycle Calculation] F --> G

Timer hardware automatically:

  • Routes TI1 to both channels

  • Applies opposite edge polarity

  • Computes period and duty cycle with minimal software overhead.

3️⃣ Register Configuration Overview

For a timer with at least two channels (TIM2, TIM3, TIM1, TIM15, etc.):

Step 1 - Configure GPIO as AF for TIMx_CH1

  • Example for PA6 (TIM3_CH1):
GPIO_InitAlternateF(GPIOA, 6, 1); // AF1 for TIM3_CH1

Step 2 — Configure Timer Base

Timer_Init(TIM3, 40, 0); // 1 MHz tick = 1 µs resolution, assuming 40[MHz] BUS speed

Step 3 — Configure Input PWM Mode

This is the key part.

  • Channel 1: map to TI1, capture rising edges
TIM3->CCMR1 &= ~TIM_CCMR1_CC1S_Msk;
TIM3->CCMR1 |=  TIM_CCMR1_CC1S_0;   // CC1 mapped to TI1
TIM3->CCER  &= ~TIM_CCER_CC1P;      // Rising edge
  • Channel 2: map to TI1, capture falling edges
TIM3->CCMR1 &= ~TIM_CCMR1_CC2S_Msk;
TIM3->CCMR1 |=  TIM_CCMR1_CC2S_1;   // CC2 mapped to TI1
TIM3->CCER  |=  TIM_CCER_CC2P;      // Falling edge

Step 4 — Enable both captures

TIM3->CCER |= TIM_CCER_CC1E | TIM_CCER_CC2E;

Step 5 — Enable interrupts

TIM3->DIER |= TIM_DIER_CC1IE | TIM_DIER_CC2IE;
NVIC_EnableIRQ(TIM3_IRQn);

Step 6 — Start timer

Timer_SetEnable(TIM3, 1);

4️⃣ ISR Logic: Extracting Period and Duty Cycle

volatile uint16_t lastRise = 0;
volatile uint16_t lastFall = 0;
volatile uint16_t period = 0;
volatile uint16_t highTime = 0;


void TIM3_IRQHandler(void)
{
    // Rising edge → CCR1
    if (TIM3->SR & TIM_SR_CC1IF)
    {
        TIM3->SR &= ~TIM_SR_CC1IF;
        uint16_t now = TIM3->CCR1;
        period = now - lastRise;
        lastRise = now;
    }

    // Falling edge → CCR2
    if (TIM3->SR & TIM_SR_CC2IF)
    {
        TIM3->SR &= ~TIM_SR_CC2IF;
        uint16_t now = TIM3->CCR2;
        highTime = now - lastRise; // time from rise → fall
    }
}


Duty Cycle Calculation
float duty = (highTime * 100.0f) / period;

5️⃣ Can we interrupt only on the falling edge?

Activity:

Modify the Input PWM Mode configuration so that only the falling edge (CC2) generates an interrupt.

  • Verify that CCR1 still updates on rising edges

  • Compute high‑time and period using only the CC2 interrupt

  • Compare the results with the dual‑interrupt version

  • Discuss advantages and limitations