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.

Tabella 1

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.

Figura 1

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!

Lascia una risposta

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Ti sei iscritto alla newsletter

There was an error while trying to send your request. Please try again.

Quattrodispositivi utilizzerà le informazioni fornite in questo modulo per restare in contatto con te e fornire aggiornamenti del sito