PrettyPrint

lunedì 19 luglio 2010

Timer AVR in 5min: 1) Partiamo da zero





Ultima revisione: 29/Apr/2012 



Il timer di un microcontrollore è una periferica hardware interna impiegata per la generazione, la misura, di tempi ed eventi, che, lavorando separatamente dall'esecuzione del programma, consente di ottenere una notevole efficienza e precisione rispetto alle tecniche software basate su cicli di ritardo.

Un timer è un registro a n bit, il cui dato viene incrementato di un'unità a ogni impulso di clock.

Il timer inizia così a contare da 0 e arriva fino a un numero massimo 2n-1, per poi ricominciare da zero e così via di nuovo fino al massimo numero (tutti bit a 1), continuamente.

Ad esempio, un elementare timer da 2bit conterà continuamente, in sequenza, quattro numeri:





0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3....


ossia in codice binario:




00, 01, 10, 11, 00, 01, 10, 11, 00, 01, 10, 11....


In questo caso, diremo anche che la risoluzione del timer è di 2bit.

La direzione del conteggio può anche essere verso il "basso", cioè dal numero più grande al numero più piccolo.

Un numero resta memorizzato nel registro per una durata di tempo pari a quella di un periodo di clock (Tc).

Per esempio, se Tc=0,25s, partendo dal primo zero e finquando il registro del timer conterrà il primo numero 3 sarà trascorso un tempo pari a 4 * Tc sec ossia 1s.

Dal successivo zero e fino a tutto il secondo numero tre verrà di nuovo impiegato 1s e così via, per il terzo tre...il comportamento è dunque periodico di periodo T

Il timer va in overflow, quando passa dal massimo numero rappresentable (registro con tutti bit a 1) allo zero.

Una possibile raffigurazione dell'esempio è riportata di seguito, nella quale ogni cella rappresenta il valore dell'ipotetico registro dati del timer che memorizza il numero:



In generale, il numero N al quale corrisponde un intervallo di tempo T, dato il tempo di clock Tc è dato da:




N.B. si aggiunge 1, perché anche lo zero "impegna" un ciclo di clock.

Possiamo sfruttare questo periodo di 1s per il nostro programma: per esempio, far compiere ogni secondo un'operazione: accendere o spegnere un LED oppure realizzare un orologio, per esempio ricorrendo a un'interruzione software.

Esempio:

Ogni sec:
{
   Accendi il LED sul pin PortB.2 se è spento, viceversa spegnilo se è acceso
}


oppure:

Ogni sec:
{
   secondi = secondi + 1;

   se (secondi==60) allora:
   {
      minuti = minuti + 1;
      secondi = 0;
   }

   se (minuti==60) allora:
   {
      ora = ora + 1;
      minuti = 0;
      secondi = 0;
   }

   se (ore==24) allora:
   {
      ore=0;
      minuti=0;
      secondi=0;
   }  
}


Un timer può essere usato non solo per schedulare eventi in uscita, come gli esempi fatti sopra, ma anche per contare eventi d'ingresso: quante volte è stato premuto un pulsante, quanto tempo è trascorso fra uno start e uno stop di un cronometro, la frequenza di un segnale, la durata di un impulso oppure il duty cicle di un segnale rettangolare.

In tal caso, cioè quando l'impulso di clock proviene dal mondo esterno, il nome più appropriato è quello di contatore. Perciò, nella letteratura si parla indistintamente di timer/contatore a secondo del particolare contesto d'utilizzo, se per creare tempi (out) o per contare eventi (in)


 I registri dell'AVR ATmega168

Un AVR ATmegax8 (48, 88, 168, 328) contiene tre timer:

Timer0, da 8 bit
Timer1, da 16 bit
Timer2, da 8 bit



Il registro dati del timer a 16bit è costituito dall'unione di due registri a 8bit: il primo che memorizza il byte inferiore e il secondo quello superiore.

Quindi il registro dati (che contiene il numero) del Timer1 sarà composto da due registri: TNCT1L e TCNT1H.

L'intero registro dati, in alcuni linguaggi, può comunque essere direttamente accessibile mediante l'etichetta TCNT1:

Una descrizione grafica molto usata per i timer è quella di rappresentare l'andamento nel tempo del numero contenuto nel registro dati

Nel caso del timer1 (TCNT1), che conti da 0 fino al suo valore massimo, il grafico assume un andamento "a rampa crescente":

Quando il timer conta da 0 fino al massimo valore dato dal numero di bit del suo registro dati, si dice che opera in modo normale o naturale; tale modalità è in effetti poco flessibile in quanto "rigidamente" legata al numero di bit e alla frequenza di clock; esistono invece diverse modalità e tecniche che consentono di controllare in modo preciso e affidabile i tempi generati, come si vedrà più avanti.






I contenuti di questo documento, sono stati resi possibili grazie ai seguenti strumenti gratuiti:
- LaTeX equation editor
- FidoCADJ (disegno grafici)
- Google Code Prettify (sorgenti con sintassi evidenziata)