Timer ESP32: guida alla configurazione e utilizzo con interrupt
Introduzione
Il Timer è un elemento hardware essenziale per ogni microcontrollore.
La maggior parte dei microcontrollori moderni ne hanno almeno uno integrato.
Il timer è un contatore che svolge la funzione di misurare il tempo con estrema precisione, esso fornisce la base dei tempi per i sistemi operativi come FreeRTOS.
Può sincronizzare le operazioni del microcontrollore e fornisce un controllo preciso della temporizzazione.
In questa guida, ti mostrerò come configurare uno dei timers integrato nel microcontrollore ESP32, come utilizzarlo per misurare il tempo e scrivere un codice non bloccante, con l’uso degli interrupt.
Descrizione del timer
I microcontrollori ESP32 contengono da 2 a 4 timer integrati.
Tutti i timer sono a 64 bit ( eccetto per ESP32-C3 54 bit) con un prescaler a 16 bit (che descriveremo in seguito) e possono contare in up/down e ricaricati in modo automatico.
Il timer (a volte è chiamato contatore) è una parte di circuito indipendente, cioè il conteggio non è eseguito dalla ALU del microcontrollore, ma viene solo configurato tramite dei registri.
Il principio di funzionamento è molto semplice, contano il numero di impulsi di un clock di riferimento, che può essere fornito dall’esterno o integrato nel device.
Ad esempio, un timer a 64 bit, come quello integrato nel microcontrollore ESP32, conta l’evento d’ingresso per:
1.8 x 1019
Il timer dell’ES32 può contare in entrambe le direzioni, e supponiamo che il timer è stato configurato per contare valori incrementali, quando il conteggio ha raggiunto il valore massimo esso si resetterà in modo automatico.
Come anticipato in precedenza, il timer può essere configurato tramite dei registri interni per modificarne il funzionamento.
Ad esempio, invece di contare fino a un massimo di 1.8 x 1019, è possibile impostare il conteggio massimo a 2000, e al raggiungimento di questo valore, si può attivare una segnalazione per eseguire una determinata funzione.
Di seguito ti riporto alcune applicazioni pratiche del timer:
- Output compare (OC): cambia lo stato di un pin quando il timer raggiunge il valore impostato
- Input capture (IC): Conta il tempo trascorso tra due eventi su degli ingressi del microcontrollore.
- Modulazione larghezza impulsi (PWM): cambia lo stato di un pin d’uscita quando il timer raggiunge il valore impostato.
Comprendere il Timer e il Prescaler nell’ESP32
Un timer può misurare il tempo a diverse velocità in funzione della sorgente di clock e del Prescaler.
Utilizzando un Prescaler, la velocità di conteggio del timer può essere rallentata per misurare eventi temporali più lunghi.
Il Prescaler è un’unità hardware che divide la sorgente di clock.
Nel caso dell’ESP32, viene utilizzata una sorgente di clock a 80 MHz.
Se si imposta il Prescaler a 80, il clock verrà diviso per 80 e il timer conterà un clock di 1 MHz.
Codice
Apprendere il Timer e il Prescaler nell’ESP32 attraverso un’applicazione pratica.
int contatore, TimeFromReset; hw_timer_t *My_timer = NULL; void IRAM_ATTR onTimer(){ contatore++; TimeFromReset = millis(); Serial.print("Numero. "); Serial.print(contatore); Serial.print(" a "); Serial.print(TimeFromReset); Serial.println(" ms"); } void setup() { Serial.begin(115200); My_timer = timerBegin(0, 80, true); timerAttachInterrupt(My_timer, &onTimer, true); timerAlarmWrite(My_timer, 1000000, true); timerAlarmEnable(My_timer); //abilitiamo il timer } void loop() { }
hw_timer_t *My_timer = NULL;
“hw_timer_t” è un tipo di dati definito nella libreria per il microcontrollore ESP32, del timer hardware integrato.
Inizializzare un puntatore con NULL, perché non è configurato e inizializzato e verrà eseguito successivamente.
void IRAM_ATTR onTimer()
questa funzione verrà chiamata ogni volta che il timer ha raggiunto la fine del conteggio che abbiamo impostato.
“IRAM_ATTR” è un attributo fornito al precompilatore che deve allocare la funzione nella RAM in questo modo l’esecuzione della routine associata all’Interruput può essere eseguita nel più breve tempo possibile.
IsrCounter++;
Incrementiamo la variabile ogni volta che scatta il conteggio del timer e si attiva l’interrupt
lastIsrAt = millis();
La variabile “lastIsrAt” viene impostata al valore che restituisce la chiamata alla funzione “millis()”.
Questa funzione restituisce il tempo in millisecondi trascorsi dall’avvio del sistema.
My_timer = timerBegin(0, 80, true);
Questa funzione configura un timer su un microcontrollore ESP32. “timerBegin” è una funzione di libreria che inizializza un timer.
I parametri sono i seguenti:
- 0: indica la periferica timer da utilizzare, in questo caso la periferica 0.
- 80: è il prescaler del clock del timer, che determina la frequenza del timer.
- true: indica che il timer deve essere abilitato all’avvio.
La funzione restituisce un handle al timer, che viene assegnato alla variabile “My_timer” e che può essere utilizzato in seguito per gestire il timer.
Con questa configurazione, dato che il microcontrollore ESP32 usa, per il timer, il clock a 80 Mhz e il prescaler impostato a 80, il contatore si incrementa ogni microsecondo.
Conclusioni
Spero che le informazioni fornite siano fonti di ispirazione per nuovi progetti.
Se hai domande o osservazioni, sarò felice di aiutarti, lascia un commento di seguito.
Inoltre, ti invito a condividere i tuoi progetti e risultati con la comunità, in modo che possano essere di ispirazione per gli altri.
Buona fortuna con i tuoi progetti futuri!