PIC - Periferiche e Moduli
 
  Box
Il modulo Timer0

Vedere anche:

Le informazioni contenute in questi appunti si riferiscono principalmente al PIC16F877A (vedi datasheet), ma possono essere applicate a molti altri modelli con periferiche uguali o quasi.
In ogni caso, una lettura del datasheet appropriato, è obbligatoria.

Il timer0 a 8 bit (con prescaler condiviso col Watchdog timer)

La periferica che, sicuramente, è comune a tutti i PIC, è il Timer0 e, nella figura seguente, possiamo vederne il diagramma a blocchi semplificato.
Questo timer è ad 8 bit, con prescaler condiviso col Watchdog Timer (WDT).
Per prima cosa, notiamo il registro TMR0, che è interfacciato con il bus dei normali registri, quindi leggibile e scrivibile come un comune registro ad 8 bit.
Abbiamo un prescaler ad 8 bit con rapporto programmabile, una sorgente di impulsi, che può essere interna oppure esterna, con possibilità di scelta del fronte (in salita o discesa) del segnale.

   

Oltre questo, è presente anche una segnalazione di overflow tramite un interrupt dedicato.
Il registro TMR0 viene incrementato di una unità a seconda degli eventi che più avanti vedremo.
Quando questo registro raggiunge lo 0 (ovvero passa da 255 a 255+1=0 e, quindi, va in overflow), viene settato il bit T0IF nel registro INTCON, generando un interrupt (se abilitato).
Il funzionamento del Timer0 è regolato dall'impostazione di alcuni bit, leggibili e scrivibili, che troviamo nel registro OPTION_REG.
Da notare che, il bit 6 ed il bit 7, non vengono usati nel funzionamento del Timer0, ma per altri scopi.

   
T0CS (TMR0 Clock Source)
  1 = Ingresso dal pin T0CKI
  0 = Clock interno (Fosc/4)

Il bit T0CS seleziona la sorgente degli impulsi da contare.

1

Un segnale generato da un circuito esterno può essere applicato al pin T0CKI (che, nel PIC16F877A, corrisponde all'ingresso RA4).

0

Il segnale arriverà dal clock del PIC, con frequenza pari a quella dell'oscillatore, divisa per 4.

T0SE (TMR0 Source Edge)
  1 = Transizione da alto a basso
  0 = Transizione da basso a alto

Il bit T0SE determina se l'incremento di TMR0 debba avvenire sul fronte di discesa o di salita, dell'impulso proveniente dal pin T0CKI.

1

Transizione su fronte di discesa.

0

Transizione su fronte di salita.

PSA (PreScaler Assignment)
  1 = Prescaler al WDT
  0 = Prescaler al TMR0

Il bit PSA assegna il prescaler al Timer0 oppure al Watchdog timer.

1

Il prescaler viene assegnato al Watchdog timer.

0

Il prescaler viene assegnato al TMR0.

PS(2:0) (Prescaler rate Select)
 PS2 PS1 PS0    TMR0      WDT
  0   0   0  =  1:2       1:1
  0   0   1  =  1:4       1:2
  0   1   0  =  1:8       1:4
  0   1   1  =  1:16      1:8
  1   0   0  =  1:32      1:16
  1   0   1  =  1:64      1:32
  1   1   0  =  1:128     1:64
  1   1   1  =  1:256     1:128

I bit PS2:PS1:PS0 selezionano il rapporto di divisione del prescaler.

I rapporti di divisione sono differenti per il TMR0 rispetto al WDT.

Assegnando il prescaler al WDT, faremo in modo che, il segnale che andrà ad incrementare il TMR0, non venga diviso (rapporto 1:1).

Quando diamo alimentazione al PIC (POR - Power On) o dopo un reset, il registro OPTION_REG sarà impostato con tutti i bit a 1.
Con questa impostazione, il Timer0 è abilitato come contatore ed il registro TMR0 verrà incrementato dagli impulsi che arrivano sul pin T0CKI, su fronte di discesa, senza prescaler, il quale sarà assegnato al WDT, con rapporto 1:128.

   

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.
In "Prove di comportamento del Timer0", possiamo vedere il comportamento del registro TMR0 senza prescaler oppure con prescaler, quando modifichiamo il suo valore.

L'incremento del registro TMR0 può avvenire a causa di uno di due eventi selezionabili da programma.
Il bit T0CS del registro OPTION_REG indica se l'incremento deve avvenire a ogni ciclo di clock (Fosc/4) oppure alla presenza di un fronte di segnale sul pin T0CKI.

Nel secondo caso è possibile decidere, impostando il bit T0SE sempre nel registro OPTION_REG, se l'incremento deve avere luogo sul fronte di salita o sul fronte di discesa del segnale.

Se, per esempio, desideriamo contare degli eventi (passaggio di oggetti, pressioni di un pulsante, segnali di allarme, ecc.) il modulo del Timer0 configurato come contatore esterno è l'ideale, perché pensa a tutto lui.
Per sapere il numero dei conteggi, basterà andarsi a leggere, quando vogliamo, il contenuto del registro TMR0.
Se, invece, desideriamo avere una base dei tempi per cui, dopo un certo numero di millisecondi, dobbiamo fare una certa cosa, allora il modulo Timer0 va selezionato per l'incremento automatico legato al ciclo di clock del microcontroller.

Nel caso della lettura del fronte però, ci sono delle limitazioni legate alla sincronizzazione del segnale esterno con la fase del clock del controller.
Riferendoci alla figura sotto, la sincronizzazione viene fatta dopo il modulo del prescaler.

   

L'uscita di tale modulo viene campionata due volte ad ogni ciclo di istruzione (4 di clock) per la determinazione del fronte di salita o di discesa.
Per questo motivo, è necessario che il tempo di uscita del modulo prescaler rimanga alta per almeno 2*tosc, basso per almeno altri 2*tosc, dove tosc = periodo di clock (in figura, Qn).

Parliamo ora del prescaler disponibile sul Timer0.
Per prima cosa, non è leggibile o scrivibile e non è necessariamente dedicato al Timer0, ma potrebbe anche essere destinato alla periferica Watchdog, poiché essendo in comune tra le due, dovremo scegliere noi la sua assegnazione, impostando il bit PSA nel registro OPTION_REG.

Con i bit PS2, PS1, PS0 del registro OPTION_REG, è possibile impostare il valore del rapporto di divisione, che nel caso dell'abbinamento al Timer0 è visibile nella figura sottostante.

   

Abbiamo detto che quando il registro TMR0 passa da 0xFF a 0x00, viene settato il bit T0IF del registro INTCON e viene generato un interrupt, se è abilitato il bit T0IE, nel registro INTCON (vedere "interrupt del Timer0").
Il Timer0, dopo una istruzione SLEEP, viene spento e, quindi, non potrà risvegliare il PIC.

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.
Per passare il prescaler dal Timer0 al Watchdog o viceversa, si devono usare le istruzioni seguenti:

 
Per passare il prescaler dal Timer0 al Watchdog
OPTION_REG = %xx0x0xxx  ' Seleziona TMR0, prescaler diverso da 1:1 e sorgente clock
TMR0 = 0                ' Azzera TMR0 e prescaler
OPTION_REG = %xxxx1xxx  ' Seleziona WDT, non cambia valore prescaler
CLRWDT                  ' Azzera watchdog e prescaler
OPTION_REG = %xxxx1xxx  ' Seleziona WDT e nuovo valore prescaler

Per passare il prescaler dal Watchdog al Timer0
CLRWDT                  ' Azzera watchdog e prescaler
OPTION_REG = %xxxx0xxx  ' Seleziona TMR0, valore prescaler e sorgente clock

Inizializzazione per modo sorgente clock interna

TMR0 = 0                ' Azzera TMR0 e prescaler
INTCON = 0              ' Disabilita interrupt e azzera T0IF
OPTION_REG = %11000011  ' Seleziona TMR0, prescaler 1:16 e clock interno
'setbit(INTCON, T0IE)    '
'setbit(INTCON, GIE)     '
' TMR0 interrupt disabilitato, provo col polling per l'overflow
T0_OVFL_wait:
if INTCON.T0IF = 0 then
   goto T0_OVFL_wait
end if
...

Inizializzazione per modo sorgente clock esterna

 
TMR0 = 0                ' Azzera TMR0 e prescaler
INTCON = 0              ' Disabilita interrupt e azzera T0IF
OPTION_REG = %00110111  ' Seleziona TMR0, prescaler 1:256 e clock esterno, fronte discesa
'setbit(INTCON, T0IE)    '
'setbit(INTCON, GIE)     '
' TMR0 interrupt disabilitato, provo col polling per l'overflow
T0_OVFL_wait:
if INTCON.T0IF = 0 then
   goto T0_OVFL_wait
end if
...
   

Esempi di codice con uso del Timer0:

  • MPASM
  • MikroBasic

 

Moduli Timer - Introduzione

Il Timer1

Bibliografia:
Datasheet Microchip PIC16F877A

 

Ultima modifica  

 
Privacy Policy Cookie Policy