STM32 Timer Input Capture: Misurare Frequenza e Duty Cycle a Livello di Registro

2026-06-01 · Davide Carrese
STM32 · Timer · Firmware Debugging

Misurare la frequenza e il duty cycle di un segnale esterno egrave; uno dei compiti embedded piugrave; comuni — sensori RPM, linee di feedback PWM, impulsi encoder e debug temporale di protocolli richiedono tutti una cattura accurata del periodo. La modalitagrave; input capture dei timer STM32 permette di timestampare i fronti con risoluzione del timer. Questo articolo illustra la configurazione a livello di registro, copre il metodo a doppio canale per la misura simultanea di frequenza e duty cycle, e affronta la gestione dell'overflow indispensabile in ogni firmware di produzione.

Come funziona l'input capture

Ogni timer general-purpose STM32 (TIM2–TIM5, TIM9–TIM17 su F4; TIM2–TIM8, TIM15–TIM17 su G4) dispone di canali capture/compare. In modalitagrave; input capture, il canale rileva un fronte programmato sul suo pin di ingresso (TI1, TI2) e cattura il valore corrente del contatore nel registro di capture (CCR). La sequenza base:

  1. Il contatore TIMx_CNT scorre liberamente, tipicamente alla frequenza di clock del timer divisa dal prescaler PSC.
  2. Un fronte sul pin di ingresso attiva una capture: TIMx_CCRx riceve il valore corrente di CNT.
  3. Il flag CCxIF in TIMx_SR si attiva; puograve; essere generato un interrupt o una richiesta DMA.
  4. Leggendo capture successive e calcolando la differenza, si ottengono il periodo e la larghezza d'impulso del segnale.

Il percorso di ingresso include filtraggio programmabile, selezione della polaritagrave; del fronte e un prescaler opzionale (ogni 2°, 4° o 8° fronte). Questi sono configurati in TIMx_CCMR1 (canali 1, 2) o TIMx_CCMR2 (canali 3, 4).

Misura a canale singolo: solo frequenza

Con un canale configurato sul fronte di salita, ogni capture fornisce un timestamp di fronti di salita consecutivi. La differenza tra due capture successive egrave; il periodo del segnale in tick del timer.

f_segnale = clock_timer / (PSC + 1) / tick_periodo

Funziona bene per segnali stabili ma non puograve; misurare il duty cycle.

Configurazione registri: TIM2 canale 1, fronte di salita, STM32F401

// Clock TIM2 = 84 MHz, PSC = 83 -> 1 MHz tick
TIM2->PSC = 83;
TIM2->ARR = 0xFFFF;
TIM2->CCMR1 = TIM_CCMR1_CC1S_0;  // IC1 su TI1
TIM2->CCER = TIM_CCER_CC1E;      // fronte di salita
TIM2->DIER = TIM_DIER_CC1IE;
TIM2->CR1 = TIM_CR1_CEN;

Misura a doppio canale: frequenza e duty cycle

Per misurare sia frequenza che duty cycle servono due capture per periodo: una sul fronte di salita (timestamp A), una sul fronte di discesa (timestamp B). Il tempo alto = B - A, il periodo = prossimo_salita - A. L'architettura dei timer STM32 supporta questa modalitagrave; attraverso due canali sullo stesso ingresso:

Si configura tramite TI1FP1 (salita) e TI1FP2 (discesa) nel registro CCMR1. Entrambi i canali condividono lo stesso pin, ma ciascuno ha la propria polaritagrave; in CCER.

// CCMR1: IC1 su TI1, IC2 su TI1
TIM2->CCMR1 = TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0;
// CCER: CC1 salita, CC2 discesa
TIM2->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC2P;
TIM2->DIER = TIM_DIER_CC1IE | TIM_DIER_CC2IE;
TIM2->CR1 = TIM_CR1_CEN;

Gestione dell'overflow del timer (rollover 16-bit)

I timer 16-bit eccedono ogni 65536 tick. Se il periodo del segnale supera questo valore, il calcolo del delta si rompe. La soluzione egrave; contare gli overflow nell'interrupt di update ed estendere il valore a 32 bit:

static volatile uint32_t conteggio_overflow = 0;

void TIM3_IRQHandler(void) {
    if (TIM3->SR & TIM_SR_UIF) {
        TIM3->SR = ~TIM_SR_UIF;
        conteggio_overflow++;
    }
}
uint32_t now_ext = (conteggio_overflow << 16) | TIM3->CCR1;

Filtraggio d'ingresso e reiezione del rumore

I segnali reali presentano glitch. Il filtro digitale programmabile STM32 sull'ingresso TIx si configura nei bit ICxF di CCMR1/CCMR2. Il filtro campiona a f_DTS e attesta un fronte solo dopo N campioni concordi.

Per feedback PWM su controllo motori, uso ICF = 4 o 5 (N = 6–8 a f_DTS).

Esempio pratico: misura di un segnale PWM servo su STM32F401

Un PWM servo RC standard ha 50 Hz (20 ms) con impulso 1–2 ms. Con PSC = 83 e 84 MHz, il tick egrave; 1 MHz: periodo 20000 tick, impulso 1000–2000 tick. TIM3 16-bit egrave; sufficiente.

Problemi comuni

Frequenza di clock del timer errata

Il clock del timer non egrave; sempre SYSCLK. Su F4, se APB1 prescaler non egrave; 1, i timer APB1 girano a 2 x clock APB1.

Rimappatura del canale (TI1 vs TI2)

Il doppio canale (IC2 su TI1) funziona solo se CCMR1 CC2S = 01. Se CC2S = 10 o 11, il canale 2 passa a TI2 o TRC.

Overflow 16-bit su segnali lenti

Un segnale a 1 Hz a 1 MHz necessita 1000000 tick. Su F4, TIM2 e TIM5 sono 32-bit. Su G4, solo TIM2.

Sequenza fronti mancante

Se la scheda viene collegata a metagrave; ciclo, il primo fronte potrebbe essere di discesa. Aggiungere sincronizzazione: ignorare le prime 2–3 capture.

Checklist pratica

Come lo affronterei su un progetto cliente

Scrivo un modulo di misura con macchina a stati, coda risultati e struttura di configurazione. L'ISR egrave; minimale — scrive capture in un ring buffer — mentre il calcolo di frequenza e duty cycle gira nel contesto applicativo. La configurazione vive in bsp_timers.h; il cliente modifica la tabella, non l'ISR.

Fonti e approfondimenti

Comments

Have comments? Send me an email.