PIC e Linux: 2) Il timer

Il timer è un’altra periferica importantissima. Per comprenderla appieno rimando alla apposita lezione del corso di settorezero.

Qui mi basta dire che il timer deve essere pensato come un contatore alla rovescia, che quando arriva a zero manda un segnale di allarme (interrupt) e poi riprende a contare. A noi non resta altro da fare che utilizzare l’allarme per fare le operazioni che abbiamo deciso di compiere.

Per utilizzare il timer a piacere nostro possiamo impostare tante opzioni. Quasi tutte le opzioni hanno a che fare con il registro T0CON

  1. Da quale valore massimo deve partire il timer. Possiamo innanzitutto scegliere se far lavorare il timer a 8 bit, e in tal caso partirebbe a contare da 255, oppure a 16 bit, ed in tal caso il valore di conteggio partirebbe  da 65535
      • T0CONbits.T08bit = 0  (timer a 16 bit)
      • T0CONbits.T08bit = 1  (timer a 8 bit)
  2. Dato il valore massimo, possiamo decidere di farlo partire da un valore inferiore, ad esempio 123 invece di 255
      • dare un valore a TMR0H e TMR0L
  3. Possiamo inoltre decidere quanto dura ciascuna singola istruzione di conteggio. La durata di una istruzione è sempre in funzione della frequenza del nostro oscillatore del pic, come spiegato da Giovanni Bernardo, quindi siccome ogni singola istruzione si porta via 4 cicli macchina, se usiamo un oscillatore a 20Mhz, verranno eseguite 5 milioni di istruzioni al secondo, perciò ogni singola istruzione verrà eseguita in 0,2 milionesimi di secondo (microsecondi). In questo modo un intero “giro di timer” a 16 bit dura 65536 * 0,2microsecondi = 13107,2 microsecondi, cioè poco più di 13 millesimi di secondo.
  4. Se però vogliamo far rallentare il conteggio, allora invece di utilizzare direttamente la frequenza dell’oscillatore, la dividiamo per un fattore che va da 2 a 256 volte. A dividere la frequenza dell’oscillatore ci pensa il “prescaler”, un modulo che appunto consente di ottenere una frequenza più lenta a partire da quella del PIC.
      • dare un valore a T0CONbits.T0PS0
      • dare un valore a T0CONbits.T0PS1
      • dare un valore a T0CONbits.T0PS2

Ovviamente ci sono alcune scelte migliori delle altre. Ad esempio, se scelgo i seguenti valori:

  • Oscillatore: 16Mhz
  • Prescaler: 16
  • Lunghezza registro timer: 8bit
  • Valore di partenza del timer: 6

ottengo che ogni giro di timer è esattamente 1 millesimo di secondo.

Ecco allora come si può realizzare un semplice timer che fa lampeggiare un led. Provate voi per esercizio a capire in che modo ho impostato il timer e quanto dura il lampeggio

void main() {
TRISB = 0b11110000;
PORTB = 0xFF;

T0CONbits.T0PS0 = 0;// questi tre impostano il prescaler a 128
T0CONbits.T0PS1 = 1;
T0CONbits.T0PS2 = 1;

T0CONbits.PSA = 0; //il prescaler viene assegnato al timer
T0CONbits.T0SE = 0;
T0CONbits.T0CS = 0; //il timer è impostato per agire da timer e non da contatore 

T0CONbits.T08BIT= 0; //il timer è configurato per 16 bit
T0CONbits.TMR0ON =1; // accendo il timer
INTCONbits.TMR0IF=0; // azzero l'allarme di fine timer

// imposto un valore iniziale al timer: sono due registri da 8 bit
TMR0H = 0b01100111; //importante: impostare prima TMR0H!!!!
TMR0L = 0b01101001;

while (1)
{
   ritardo();
   PORTB = 0x00;
   ritardo();
   PORTB = 0x0F;
}
}

La funzione ritardo() non fa altro che far fare un giro completo al timer:

void ritardo()
{
 while( !INTCONbits.TMR0IF );
 INTCONbits.TMR0IF=0;
 TMR0H = 0b01100111;
 TMR0L = 0b01101001;
}

Come vedete inizia con un ciclo while durante il quale non accade nulla, semplicemente si resta in attesa che scatti l’allarme (arrivi l’interrupt) di fine timer: TMR0IF

Quando ciò accade, si fa ripartire il timer, avendo l’accortezza di rimettere a 0 il segnalatore di interrupt e reimpostare il corretto valore di partenza.

A proposito del valore iniziale del timer, va segnalata una cosa importantissima: quando si usa il timer a 16 bit, il suo valore è contenuto dentro due registri a 8 bit, il TMR0H contiene gli 8 bit “più a sinistra”, quelli più significativi, mentre TMT0L contiene i bit “più a destra”. Per impostare correttamente il valore, occorre iniziare dal TMR0H, e subito dopo dal TMR0L, e non viceversa.

Annunci

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...