Interfaccia di conteggio 82C54
Dopo aver per l'ennesima volta studiato come configurare ed utilizzare correttamente il timer del PC implementato grazie all'interfaccia di conteggio 82C54 ed al controllore delle interruzioni ho deciso di scrivere questo documento in modo da riassumere le caratteristiche più esotiche del contatore assumendo che il lettore conosca già il dispositivo. Aggiungo i sorgenti di un driver che ho realizzato a scopo didattico per chi voglia approfondire qualche dettaglio.
L'interfaccia dal punto di vista hardware consiste in tre contatori a 16 bit
indipendenti tutti collegati ad una sorgente di impulsi periodici con periodo di
circa 0.838192us.
Dal punto di vista software si hanno a disposizione quattro registri da un byte
di cui uno comune di sola lettura ed uno per ciascun contatore accessibili sia
in lettura che in scrittura.Ogni contatore può essere configurato tramite il
registro comune Control Word Register per funzionare in uno dei 6 possibili modi
e per eseguire particolari operazioni accesso.
Contatore 0 | 40H | R/W | Legge lo stato e/o il conteggio del
contatore 0. Imposta un nuovo conteggio. |
Contatore 1 | 41H | R/W | Legge lo stato e/o il conteggio del
contatore 1. Imposta un nuovo conteggio. |
Contatore2 | 42H | R/W | Legge lo stato e/o il conteggio del
contatore 2. Imposta un nuovo conteggio. |
Control Word Register | 43H | W | Invia una Configuration Word. Invia una Read Back Word. |
Mappatura dell'interfaccia di conteggio nell'I/O del PC
La parola di configurazione (Configuration Word) scritta nel Control Word Register è composta dei seguenti campi:
Bit 0 | BCD:
|
||||||||||||
Bit 1..3 | MODE:
|
||||||||||||
Bit 4,5 | Read/Write:
|
||||||||||||
Bit 6,7 | Select Counter:
|
Significato dei bit di una parola di configurazione
E' possibile "fotografare" lo stato del conteggio o leggerlo "in
corsa" con il rischio però, in questo caso, di effettuare una lettura
errata.
La lettura dei 16bit dello stato del conteggio infatti avviene tramite due
letture successive ciascuna di un byte (8bit) pertanto se non si è provveduto a
"fotografare" preventivamente lo stato del contatore potrebbe avvenire
che tra la lettura di un byte ed il successivo il contatore cambi stato rendendo
inconsistente la coppia di byte.
Tempo | t | t+1 |
Stato del conteggio | 01200H | 011FFH |
Byte letto ("in corsa") | LSB=0H | MSB=011H |
Byte letto ("fotografando" in t) | LSB=0H | MSB=012H |
Esempio di errore di lettura e della soluzione
La lettura al volo può essere effettuata con la seguente espressione dove <n> è il numero del contatore da leggere:
CounterCount[n]=inportb(0x40+n)+(unsigned)inportb(0x40+n)*256;
Per fotografare lo stato del contatore ci sono due vie:
1) Inviando una parola di configurazione al registro di controllo (Control Word)
settando il bit
"Counter Latch Count" che impone al contatore <n> di memorizzare
lo stato del conteggio.
//Fotografa lo stato del conteggio del <n>
tramite il "Counter Latch Count"
outportb(0x43,n<<6);
//Legge il conteggio
"fotografato"
CounterCount[n]=inportb(0x40+n)+(unsigned)inportb(0x40+n)*256;
2) Inviando un Read Back Command al registro di controllo (Control Word) il che si ottiene settando i bit 6 e 7 e interpretando i restanti come mostrato nella tabella sottostante. Si noti che questo metodo è più flessibile del precedente consentendo di "fotografare" più contatori contemporaneamente basta settare i relativi bit <n> inoltre è possibile ottenere informazioni sullo stato dei singoli contatori.
//Fotografa lo stato del conteggio del contatore
<n> tramite un "Read-Back Command"
outportb(0x43,(2<<n)+0xD0);
//Legge il conteggio
"fotografato"
CounterCount[n]=inportb(0x40+n)+(unsigned)inportb(0x40+n)*256;
Una volta fotografato lo stato lo si può leggerlo come nel caso precedente certi di una corretta lettura, nel caso di "fotografie" contemporanee di più canali si può leggere il valore in qualsiasi ordine basta ricordare la prima lettura della porta di un contatore estrae il byte meno significativo (LSB) e la successiva il più significativo (MSB) a meno che non si sia specificato diversamente con una "Configuration Word"!
Bit 0 | Deve essere 0 | ||||
Bit 1..3 | Seleziona il contatore su cui agire: Bit1=Contatore 0 Bit2=Contatore 1 Bit3=Contatore 2 |
||||
Bit 4 | nSTATUS:
|
||||
Bit 5 | nCOUNT:
|
||||
Bit 6,7 | 11 essendo un "Read-Back Command" |
Significato dei bit nel Read-Back Command
Dunque scrivendo nel Control Word Register un Read-Back Command nel formato
appena indicato è possibile nella configurazione più complessa selezionare
contemporaneamente tutti i contatori per fotografarne contemporaneamente lo
stato ed il conteggio che potranno essere letti successivamente in qualunque
ordine (di contatore) tenendo in mente che prima si legge lo stato poi il
conteggio.
//Invia
un Read-Back Command in modo che
//
tutti i counters salvino nei latch
// il
relativo stato ed il relativo
//
conteggio per una successiva lettura.
outportb(0x43,0xCE);
//Per ogni contatore va letto prima lo stato
// e successivamente il conteggio.
//Legge lo stato del
contatore 0
CounterStatus[0]=inportb(0x40);
//Legge lo stato del contatore 1
CounterStatus[1]=inportb(0x41);
//Legge lo stato del contatore 2
CounterStatus[2]=inportb(0x42);
//Legge il conteggio del contatore 0
CounterCount[0]=inportb(0x40)+(unsigned)inportb(0x40)*256;
//Legge il conteggio del contatore 1
CounterCount[1]=inportb(0x41)+(unsigned)inportb(0x41)*256;
//Legge il conteggio del contatore 2
CounterCount[2]=inportb(0x42)+(unsigned)inportb(0x42)*256;
Bit 0 | BCD come da Control Word Register |
Bit 1..3 | MODE come da Control Word Register |
Bit 4,5 | Read/Write come da Control Word Register |
Bit 6 | NULL COUNT: E' settato se l'ultima ricarica inviata al contatore selezionato non è ancora stata caricata. Ha senso visto che in alcuni modi di funzionamento (Es: Mode2) una ricarica non viene eseguita prima della fine del conteggio in corso (a meno che non si invii una nuova parola di configurazione). |
Bit 7 | OUTPUT: Mostra il valore del pin OUT (Hardware) del conatore selezionato. |
Significato del Byte di status restituito dopo un Read-Back Command (nSTATUS=0)
Nel codice precedente lo stato veniva memorizzato nella array CounterStatus[i]
dunque i bit di questa variabile andranno letti come da tabella.
Si noti come i bit da 0 a 5 sono la copia dell'ultima configurazione effettuata
per il contatore selezionato mentre gli ultimi due bit portano un'informazione
nuova, da non sottovalutare l'importanza del NULL COUNT infatti tra un
caricamento e l'effettiva esecuzione passa un CLK a bassa frequenza rispetto a
quella dei PC attuali il che comporta la possibilità di leggere un valore non
ricaricato anche dopo aver eseguito parecchie righe di codice. Un possibile
rimedio che non usa il bit di NULL COUNT è quello di eseguire sempre una
lettura a vuoto subito dopo aver impostato una nuova ricarica infatti solo la
prima lettura dopo una ricarica può essere errata dunque se la si attende
subito non si avranno più problemi successivamente.
Nota sul Mode 3
Un ultima nota sui modo di operare dei contatori (MODE 0..5) faccio notare come il MODE 3 per ottenere un duty cycle vicino al 50% decrementa la ricarica di due in due e non uno alla volta come tutti gli altri dunque un ciclo non termina con un conteggio da MaxCount..1 ma con due di questi cicli. E' possibile notarlo andando a monitorare il bit di OUT una volta impostato il contatore al MODE 3 si noterà che il pin d'uscita cambia di stato ad ogni fine conteggio e dunque il periodo termina con due conteggi.
Download sorgenti ed informazioni.
Il sorgente del driver che ho realizzato per leggere lo stato ed il conteggio di ogni contatore e di configurarlo come si desidera è disponibile con un programma di test, premi qui per il download.
Per sapere tutto sull'82C54 scaricare il datascheet della INTEL
Ultimo aggiornamento:Thursday 05 September 2002 | Visitatori dal 27 maggio 2001 |