TIMER 0
E' un contatore in avanti a 8 bit, che può essere scritto e letto in ogni momento ed è dotato, se attivato, di prescaler programmabile via software. Il prescaler non è altro che un divisore di clock. Es. se il prescaler viene attivato con il valore ¼, il registro avanza ogni 4 impulsi, mentre sarebbe avanzato di 4 unità senza il prescaler.
L'impulso che fa incrementare il contatore (clock) può essere :
interno (Fosc/4, cioè stesso periodo del ciclo macchina TCY)
esterno (pin RA4/T0CKI).
Può generare, se attivato, un interrupt nell'overflow da FFh a 00h.
Quindi, con il clock interno può servire da temporizzatore (timer), con quello esterno funziona da contatore (counter) di eventi.
Il registro che contiene il suo valore è TMR0.
Lo schema a blocchi della periferica è :
Per
controllare i parametri di questa periferica usiamo il registro
OPTION_REG
T0CS : seleziona la sorgente di clock :
“0” - clock interno (ciclo macchina CTY)
“1” - clock esterno sul pin RA4/T0CK1 (default)
T0SE : seleziona il fronte di lettura del pin esterno RA4/T0CK1 :
“0” - fronte di discesa
“1” - fronte di salita (default)
PSA : attribuisce il prescaler al TIMER 0 (TMR0) oppure al watchdog :
“0” - prescaler abbinato al TIMER 0
“1” - prescaler abbinato al watchdog (default)
PS2:PS0 : definiscono il rapporto di divisione del prescaler secondo la tabella sotto riportata. Come si può vedere, il rapporto di divisione del prescaler nei confronti del TIMER 0 e del watchdog è differente.
VALORE |
TMR0 |
WDT |
000 |
1/2 |
1/1 |
001 |
1/4 |
1/2 |
010 |
1/8 |
1/4 |
011 |
1/16 |
1/8 |
100 |
1/32 |
1/16 |
101 |
1/64 |
1/32 |
110 |
1/128 |
1/64 |
111 |
1/256 |
1/128 |
PS2-PS1-PS0 |
|
|
Normalmente il TIMER 0 è abilitato, e di default usa la sorgente esterna ( pin RA4/T0CK1). Si disabilita quando il microcontrollore va in SLEEP.
Il
registro TMR0 ha la particolarità che, quando viene modificato
dal programma, l'incremento
avviene dopo due cicli macchina e
di questo si deve tener conto durante il calcolo dei tempi.
Senza prescaler : dopo aver azzerato o aggiornato il contenuto di TMR0, ci saranno due cicli macchina in cui il TMR0 rimarrà immutato;
con prescaler : dopo aver azzerato o aggiornato il contenuto di TMR0, ci saranno due cicli macchina in cui il TMR0 rimarrà immutato, poi incrementerà in base al rapporto di divisione del prescaler;
Quando
il segnale è esterno, ci sono degli accorgimenti da valutare,
infatti a causa del sincronismo interno che campiona ogni due
periodi di clock, devo avere un segnale che permane per almeno
questo tempo nei due stati per rilevare un cambiamento (vedi sotto).
Al TIMER0 vengono abbinati anche due flag del registro INTCON per abilitare e gestire l'interrupt che si attiverebbe ad ogni overflow del registro TMR0 (passaggio da FF a 00).
Impostiamo a 1 il bit GIE di INTCON per abilitare tutti gli interrupt.
Impostiamo a 1 il bit TMR0IE di INTCON, abilitando le interruzioni sull'azzeramento di TMR0.
Quando
verrà generato un'interruzione il programma interromperà
l'esecuzione e salterà all'indirizzo del vettore di interrupt
dove c'è la sub procedura interrupt ed eseguirà il
test del bit TMR0IF di INTCON.
Se
questo bit sarà a 1, vorrà dire che l'interrupt è
stato richiesto dall' overflow del TMR0.
Un'altra cosa molto importante da sapere è che, qualsiasi istruzione che si riferisce al registro TMR0 o al WDT, azzera il conteggio contenuto nel prescaler, che ripartirà a contare da zero. Per questo motivo, si deve prestare attenzione quando, nel corso del programma, si vuole assegnare il prescaler da una all'altra periferica e viceversa.
Il Timer0, dopo una istruzione SLEEP, viene spento e, quindi, non potrà risvegliare il PIC.
PRESCALER
Ecco come si presenta lo schema a blocchi della periferica, quando il prescaler è assegnato al TIMER 0 :