[Search] [Contact Us]
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sponsor di 8052.it ![]() µC Family FAQ Strumenti di Sviluppo Libri Bookmarks Mailing List Forum Download Area Prodotti Il sito 8052.it e' in continua evoluzione: se avete suggerimenti o richieste contattateci |
Corso 8051 CAPITOLO 7 - I Timer L'8051 classico dispone di due timer, che possono essere configurati, controllati e letti in maniera indipendente. I timer dell'8051 hanno tre funzioni generali: Tenere traccia del tempo totale trascorso e/o calcolare il tempo
trascorso
tra due eventi,
Contare il numero degli eventi o
Generare il baud rate per la porta seriale.I tre modi di usare un timer verranno discussi separatamente. I primi due saranno affrontati in questo capitolo mentre l'uso del timer come generatore di baud rate verra' discusso nel capitolo relativo alla porta seriale. Come fa un timer a contare? La risposta e' semplice. Esso conta
sempre
incrementando il suo valore. Non importra se viene usato come timer o
come
contatore o come generatore di baud rate. E' sempre incrementato dal
microcontrollore.
Ovviamente uno degli usi primari dei timer e' quello di misurare il
tempo. Parleremo prima di questo uso e poi di quello relativo al
conteggio
di eventi. Quando un timer e' usato per misurare il tempo e' anche
chiamato
"interval timer" poiche' esso sta misurando l'intervallo temporale tra
due eventi.
Quanto tempo impiega un timer a contare? Quando il timer e' nel modo "interval timer" ed e' correttamente
configurato,
esso viene incrementato di uno ogni ciclo macchina, ovvero 12 impulsi
di
clock.
Ovviamente non e' molto utilie sapere che sono trascorsi 0,0542 secondi. Se voi voleste far partire un evento ogni secondo dovreste aspettare il conteggio del timer da 0 a 50.000 per 18,45 volte. Come si puo' aspettare per un tempo non intero? Non e' possibile. Allora proviamo a fare un calcolo imporatnte. Supponiamo di voler sapere quante volte il timer viene incrementato
ogni 0,05 secondi. Possiamo fare questo semplice calcolo:
Una volta stabilito che esso impiega un ventesimo di secondo e vogliamo eseguire un evento ogni secondo sara' sufficiente che il timer conti da 0 a 46.079 per venti volte; a questo punto eseguite le azioni richieste dall'evento, resettate il timer e aspettate che il timer completi di nuovo il conteggio altre venti volte. In questa maniera eseguirete effettivamente il vostro evento una volta al secondo con una precisione al ventesimo di secondo. Abbiamo ora un sistema capace di misurare il tempo. Quello che ci serve ora e' sapere come controllare il timer e inizializzarlo in maniera che possiamo dargli le informazioni corrette. Come precedentemente affermato, l'8051 ha due timer che funzionano ambedue nella stessa maniera. Uno e' chiamato TIMER0 e l'altro TIMER1. I due timer condividono due registri SFR (TCON e TMOD) che servono a controllarli. Ciascun timer pero' dispone di due SFR per loro uso esclusivo (TH0/TL0 e TH1/TL1). Ai registri SFR abbiamo dato un nome mnemonico per individuarli facilmente, in effetti essi hanno un valore numerico. E' spesso utile conoscere l'indirizzo corrispondente al nome mnemonico del registro SFR. Per quello che riguarda i timer essi sono:
Quando inserite il nome di un registro SFR nell'assembler, esso
viene
internamente automaticamente convertito in un indirizzo, Per esempio:
Per ricordarvi come funziona la notazione byte basso/alto,
ricordatevi
di moltiplicare il byte alto per 256 e addizionare il byte basso al
risultato
ottenuto. Ovvero:
Poiche' solo due byte sono usati per ogni timer risulta evidente che il massimo valore che un timer puo' assumere e' 65.535 (decimale). Nel momento in cui viene raggiunto tale valore un ulteriore impulso di clock lo resettera' o per meglio dire lo mandera' in overflow. Il registro TMOD e' usato per controllare il modo operativo di ambedue i timer. Ogni bit del registro fornisce al microntrollore una specifica informazione che riguarda il funzionamento del timer. I 4 bit piu' significativi (da 4 a 7) sono relativi al timer 1 mentre i 4 bit meno significativi (da 0 a 3) hanno il medesimo significato ma sono relativi al timer 0. I bit del registro TMOD hanno il seguente significato : TMOD (89h) SFR
Come potete vedere dalla tabella di sopra, quattro bit, due per ciascun timer sono usati per specificare il modo operativo. I modi operativi sono:
Il modo "0" corrisponde al funzionamento del timer a 13 bit. Questo
e' un retaggio del passato che e' stato mantenuto per avere la
compatibilita'
con il suo predecessore: l'8048.
In questa modalita' di funzionamento, TLx contera' da 0 a 31. Quando TLx viene incrementato da 31, esso si resettera' e incrementera' THx. Percio' effettivamente, soltanto 13 bit del timer a 2 byte sono utlizzati: i bit 0-4 di TLx e i bit 0-7 di THx. Questo significa anche in definitiva che il timer puo' contare solo fino ad un valore pari a 8192. Se caricate il timer con il valore 0, esso andra' in overflow e quindi a 0 dopo 8192 cicli macchina. Il modo "1" corrisponde al funzionamento del timer a 16 bit. Questo e' un modo molto utilizzato. TLx e' incrementato da 0 a 255. All'overflow di TLx, THx viene incrementato di 1. Tenuto conto che e' un timer a 16 bit, esso puo' assumere 65536 valori distinti. Se caricate il timer con il valore 0, esso andra' in overflow e quindi a 0, dopo 65536 cicli macchina. Il modo "2" corrisponde al funzionamento del timer ad 8 bit con auto-reload. Quando il timer e' configurato in modo 2, THx contiene il valore che deve essere caricato in TLx quando va in overflow. TLx inizia a contatore in avanti. Quando raggiunge 255 e viene ulteriormente incrementato invece di tornare a 0 (come nei modi 0 e 1), assume il valore caricato in THx. Se per esempio TH0 contiene il valore FDh e TL0 il valore FEh il conteggio procedera' nella seguente maniera:
Notate che il valore di TH0 non cambia mai e TL0 viene incrementato. Una volta raggiunto un valore pari a FFh, al successivo ciclo macchina TL0 assume lo stesso valore di TH0. Ma qual'e' il vantaggio di usare tale modo di funzionamento? Ipotizziamo che vogliate che il timer assuma dei valori compresi tra 200 e 255. Nel modo 0 e 1 siete costretti a verificare da programma quando il timer va in overflow e quindi settarlo al valore 200. Questo lavoro richiede tempo prezioso e non vi garantisce un elevata accuratezza a meno che non vogliate rimanere a controllare solo lo stato del timer. Quando usate il modo 2, non dovete preoccuparvi di tutto questo, poiche' l'hardware del microcontrollore lo fara' automaticamente per voi. Il modo 2 e' usato molto spesso per generare il baud rate. Ne parleremo piu' approfondidamente nel capitolo dedicato alla Comunicazione Seriale. Il modo "3" e' il cosidetto modo a timer separati. Quando il timer 0 e' configurato per lavorare in questa modalita', si trasforma in due timer a 8 bit separati. Per capirci meglio, il timer 0 diventa TL0 e il timer 1 diventa TH0. Ambedue i timer contano da 0 a 255 e dopo l'overflow tornano a 0. Tutti i bit relativi al Timer 1 vengono assegnati a TH0. Una volta che il Timer 0 e' configurato in modo split, il vero Timer 1 (cioe' TH1 e TL1) puo' essere configurato nei modi 0, 1, 2 come sempre, ma non puo' essere abilitato/disabilitato poiche' i suoi bit di controllo sono assegnati a TH0. Allora, il vero Timer 1 funzionera' in maniera libera e si incrementera' ad ogni ciclo macchina senza condizioni. L'unico vero uso di questa modalita' e' quello per cui sia necessario avere due timer separati e, in aggiunta, un generatore di baud rate. In questo caso il Timer 1 viene utilizzato come baud generator e i due registri TH0 e TL0 come se fossero due timer separati. Come ultimo c'e' un altro registro SFR che controlla i due timer e fornisce importanti informazioni sul loro funzionamento. Il registro TCON ha la seguente struttura: TCON (88h) SFR
Come potete notare, abbiamo definito solo 4 degli 8 bit. Cio' e' dovuto al fatto che gli altri 4 bit del registro TCON non hanno nulla a che vedere con i timer. Essi sono relativi agli interrupt e quindi ne discuteremo nel capitolo dedicato a questo argomento. Nella tabella precedente, c'e' un ulteriore colonna che riguarda
l'indirizzo
a bit. E' stata riportata perche' tale registro puo' essere indirizzato
a bit, cio' vuol dire che, se vogliamo settare il bit TF1, che e' il
bit
piu' significativo di TCON, potremmo eseguire la seguente istruzione:
Ora che conoscaiamo tutti i registri SFR relativi ai timer, siamo in grado di scrivere il codice per inizializzare un timer e farlo partire. Come vi ricordate, bisogna per prima cosa decidere in quale modalita' il timer verra' utilizzato. In questo caso scegliamo un modo a 16 bit che non ha alcuna dipendenza da pin esterni. Dobbiamo per prima cosa, inizializzare il registro TMOD. Se
lavoriamo
con il timer 0 useremo i 4 bit meno significativi di TMOD. I primi due
bit GATE0 e C/T0 vanno ambedue posti a 0 poiche' vogliamo che il timer
sia indipendendente da pin esterni. Il modo a 16-bit corrisponde al
modo
"1" e quindi dobbiamo: resettare T0M1 e settare T0M0. In breve l'unico
bit da settare e' il bit 0 di TMOD. Per inizializzare il timer
eseguiremo
la seguente istruzione:
Ci sono due maniere per leggere lo stato di un timer a 16-bit in funzione della specifica applicazione. Voi potete o leggere il valore attuale a 16 bit oppure stabilire soltanto se il timer e' andato in overflow. Se il timer e' configurato nel modo ad 8 bit, sia nel modo con auto-reload che in split mode, la lettura del valore e' effettuata semplicemente leggendo il byte corrispondente al timer che state usando. Quando pero' state usando il modo a 13 o 16 bit la lettura e' leggermente piu' complessa. Cio' e' dovuto al fatto che mentre state leggendo il valore del byte meno significativo del timer e questo valore e' pari a 255, potreste leggere un valore errato del byte piu' significativo che, in quel momento si sta incrementando. Per esempio se lo stato del timer e' 14/255 (byte alto = 14, byte basso = 255), potremmo leggere il valore 15/255 nel momento in cui il timer sta cambiando di stato al valore 15/0. Quale potrebbe essere la soluzione? In verita' essa non e' molto
complessa.
Dovreste leggere prima il byte alto, poi quello basso e rileggere
nuovamente
il byte alto confrontandolo con il valore letto precedentemente. Sei i
due valori coincidono, il timer non ha cambiato stato durante la
lettura
e quindi il valore letto e' utile, altrimenti va ripetuto il ciclo
precedente.
Il codice sara' del tipo:
Rivelare l'Overflow di un timer In alcuni casi e' sufficiente conoscere soltanto se il timer e' stato resettato o meno. Questo quando non interessa conoscere il valore del timer ma solo sapere se il timer ha raggiunto il massimo del conteggio (overflow). Una volta che il timer raggiunge il valore di 255, il microcontrollore lo riporta automaticamente a zero e setta il bit TFx corrispondente nel registro TCON. Per cui quando il bit TF0 e' settato vuol dire che il timer 0 ha raggiunto l'overflow e alla stessa maniera se TF1 e' settato vuol dire che il timer 1 e' tornato a zero. Possiamo usare questo approccio per costringere il programma ad
eseguire
delle operazioni ad intervalli di tempo prestabiliti. Riprendiamo pure
l'esempio precedente nel quale era richiesto il conteggio da 0 a 46.079
per un periodo di un ventesimo di secondo. Se vogliamo impostare un
tempo
pari a quello indicato, tenuto conto che il timer segnala l'overflow
quando
passa per lo zero, dobbiamo settare il timer ad un valore pari a 65.536
meno 46.079, cioe' 19.457. Quindi per eseguire una pausa di un
ventesimo
di secondo usiamo il seguente frammento di codice:
Misurare la durata di un evento L'8051 dispone di un altro utile modo che puo' essere usato per misurare la durata di un evento. Facciamo un esempio: vogliamo risparmiare energia in un ufficio e vogliamo conoscere quanto tempo una lampada rimane accesa durante la giornata. Quando la lampada e' accesa vogliamo conteggiare il tempo. Quando la lampada e' spento fermiamo il conteggio. Una possibile soluzione e' quella di collegare lo stato dell'interruttore ad un pin del micro. A questo punto il programma deve continuamente monitorare lo stato del pin utilizzato e attivare o disattivare il timer in funzione dello stato del pin stesso. Anche se il sistema funziona correttamente, In realta', l'8051 fornisce un metodo piu' semplice di quello appena prospettato. Se diamo un'occhiata al registro TMOD, c'e' un bit chiamato GATE0. Finora abbiamo lasciato sempre il bit a zero perche' volevano che il timer continuasse a girare indipendentemente dallo stato dei fili esterni. Adesso pero', tale capacita' ci torna utile. Tutto quello che serve e' di collegare lo stato dell'interruttore al pin INT0 (P3.2) dell'8051 e settare il bit GATE0. A questo punto, il timer eseguira' il conteggio solo quando il pin P3.2 si trovera' nello stato alto (interruttore on, luce accesa). Quando il pin P3.2 si trovera' nello stato basso (interruttore off, luce spenta) il timer si blocchera' automaticamente. USARE I TIMER COME CONTATORI DI EVENTI Finora abbiamo discusso di come un timer possa tener traccia del tempo trascorso, ma l'8051 ci permette di usare il timer come contatore di eventi. Quando puo' essere utile questa funzione? Supponiamo di avere un
sensore
nel mezzo di una strada che invia un impulso ogni volta che passa
un'auto.
Questo potrebbe essere utilizzato per misurare l'intensita' del
traffico
su quella strada. Potremmo allora collegare il sensore ad un pin di I/O
dell'8051 e monitorare lo stato del pin per contare il numero degli
impulsi.
Fare questo non e' eccessivamente difficile, ma richiede l'utilizzo di
un po' di codice. Supponiamo per esempio di aver collegato il sensore
al
pin P1.0; il codice che conta il numero di auto che passano sara' del
tipo:
Fortunamente l'8051 ci fornisce un'alternativa per usare il timer come contatore di eventi senza doverci preoccupare di come realizzarlo in software. E' estremamente semplice e indolore: basta configurare un bit addizionale. Per esempio vogliamo utilizzare il Timer 0 per conteggiare il numero delle auto che transitano. Allora, se diamo uno sguardo al registri TCON possiamo notare la presenza di un bit chiamato C/T0, bit 2 di TCON (TCON.2). Se tale bit e' settato, il timer 0, invece di incrementare se stesso ad ogni ciclo macchina, effettuera' il monitoring della linea P3.4. In questa maniera incrementera' se stesso ogni volta che la linea passa dal valore alto a quello basso. A questo punto e' sufficiente collegare il sensore sulla linea P3.4 e configurare il registro TCON opportunamente. E' importante pero' notare che l'8051 controlla lo stato della linea P3.4 una volta per ciclo macchina. Questo significa che, se la frequenza con la quale cambia lo stato del pin e' troppo elevata, l'8051 non riuscira' piu' a contare il numero di eventi in maniera corretta. Piu' precisamente, l'8051 riesce a contare un numero di eventi ad un massimo di un ventiquattresimo della frequenza di clock. Cio' vuol dire che, se per esempio usiamo un quarzo che oscilla a 12 MHz, esso riesce a conteggiare fino a 500.000 eventi al secondo (12 MHz * 1/24 = 500.000). ![]() < Informazioni a basso livello > Porta Seriale Le informazioni sono fornite senza alcuna garanzia (vedi dettagli) Contattate l'autore Craig Steiner (presso 8052.com) per l'uso e/o il permesso di divulgazione di questo corso. Traduzione italiana di: Sergio Salvitti |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Timer |
Site made with Sworg - Simple Web Organizer
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||