UART
COM1 : 0x3F8 COM2 : 0x2F8
Il y a plus de 8 registres différents et on ne dispose que de 3 bits d'adresse. La solution est d'utiliser un bit d'un registre spécial, DLAB. Suivant l'état du bit DLAB, on va sélectionner tel ou tel registres.
Adresse |
Registre |
|||
A2 |
A1 |
A0 |
||
Si DLAB=0 |
0 |
0 |
0 |
RBR :
Receiver Buffer (registre de réception) en lecture THR : Transmitter Holding Register (registre d'émission) en écriture |
Si DLAB=1 |
0 |
0 |
0 |
DLL : Divisor Latch LSB (poids faible diviseur horloge) |
Si DLAB=1 |
0 |
0 |
1 |
DLM : Divisor Latch MSB (poids fort diviseur horloge) |
Si DLAB=0 |
0 |
0 |
1 |
IER : Interrupt Enable Register |
0 |
1 |
0 |
IIR : Interrupt Identification Register | |
0 |
1 |
1 |
LCR : Line Control Register | |
1 |
0 |
0 |
MCR : Modem Control Register | |
1 |
0 |
1 |
LSR : Line Status Register | |
1 |
1 |
0 |
MSR : Modem Status Register | |
1 |
1 |
1 |
Non utilisé |
Exemple : si l'adresse de base de l'interface est par exemple 3F8H, l'adresse du registre RBR sera 3F8H + 000 = 3F8H et celle de IIR 3F8H + 010b = 3F8H + 2H = 3FAH.
On voit, comme nous l'avons dit plus haut, que les registres DLM et IER (par exemple) possèdent la même adresse (001b). Si le bit DLAB est 0, cette adresse permet d'accéder à DLM, et si DLAB=1 à IER.
Le bit DLAB est le bit de poids fort du registre LCR.
Choix de la rapidité de modulation = Débit
115200 / vitesse = 256 * DLM + DLL
( en C : division modulo 256 : %
).
Registre THR : ( ) Registre d'émission.
Registre RBR : ( ) Registre de réception.
Registre LCR (Line Control Register) : Registre de commande pour définir certains paramètres de la transmission.
B7 |
B6 |
B5 |
B4 |
B3 |
B2 |
B1 |
B0 |
DLAB |
0 |
0 |
0 : parité impaire |
0: Sans parité |
0 : 1 bit stop |
B1B0=00 : 5 bits de
data |
Registre IER : Utilisé pour les entrées/sorties par interruption.
Bit 0 : interruption lorsque donnée reçue dans RBR;
Bit 1 : interruption lorsque registre THR vide;
Bit 2 : interruption lorsque l'un des 4 bits de poids faible de LSR passe à 1;
Bit 3 : interruption sur état du modem.
Registre LSR : Registre d'état rendant compte du fonctionnement en réception (bits 0 à 4) et en émission (bits 5 et 6).
Bit 0 |
passe à 1 lorsqu'une donnée a été reçue et chargée dans RBR. |
Bit 1 |
signale erreur d'écrasement. 1 si donnée reçue et chargée dans RBR alors que la précédente n'avait pas été lue. Remis automatiquement à 0 par la lecture du registre LSR. |
Bit 2 |
passe à 1 à la suite d'une erreur de parité. Remis à 0 par la lecture de LSR. |
Bit 3 |
passe à 1 lorsque le niveau du bit STOP n'est pas valide (erreur de format). Remis à 0 par la lecture de LSR. |
Bit 4 |
passe à 1 lorsque le niveau de la liaison est resté à 0 pendant la durée d'émission de la donnée (problème de l'emetteur). Remis à 0 par la lecture de LSR. |
Bit 5 |
passe à 1 lorsqu'une donnée est transférée de THR vers le registre à décalage d'émission (THR est alors libre pour le caractère suivant). |
Bit 6 |
passe à 1 lorsque le registre à décalage d'émission est vide. |
Bit 7 |
Toujours à 0 |
Registre IIR :
IIR est utilisé pour les E/S par interruption. Son contenu permet d'identifier la cause de l'interruption émise par l'UART.
Registre MCR : MCR est le registre de commande du modem.
Bit 0 : commande le niveau de DTR qui
informe le modem que le µP est prêt à communiquer;
Bit 1 : commande RTS qui demande au
modem d'émettre.
Registre MSR : MSR est
le registre d'état du fonctionnement du modem.
Bit 0 : Changement de CTS
Bit 1 : Changement de DSR
Bit 2 : Changement de RING
II) Programmation de l'interface en langage C
unsigned char inportb( int address ) lit un octet à l'adresse (de l'espace d'entrées/sorties) indiquée et le retourne.
void outportb( int address, unsigned char *data ) écrit l'octet (argument data) à l'adresse (E/S) indiquée.
#include <dos.h>
/* Constantes pour ameliorer la lisibilite: */
#define PORT (0x3F8) /* adresse de l'interface */
#define RBR PORT
#define THR PORT
#define LSR (PORT+5)
#define IIR (PORT+2)
#define LCR (PORT+3) /* DLAB ... */
#define DLL PORT /* DLAB = 1 */
#define DLM (PORT+1) /* DLAB = 1 */
#define IER (PORT+1)
#define MCR (PORT+4)
#define MSR (PORT+6)
Init :
DLAB à 1 : ouptortb(LCR,0x80)
DLL en adbase
DLM en adbase+1
Config en LCR
Lecture_bit_registre :
Lire val, Masque=1,
masque=masque<<n°bit, val = val&masque ( & = ET
binaire pas logique )
Si val nul alors return 0 sinon return 1
Set_bit_registre
Masque=1, masque=masque<<n°bit ( 0
à 7 ), lire val, val = val | masque
Reset_bit_registre
Masque=1, masque=masque<<n°bit,
masque = ~masque, lire val, val = val & masque
Réception carac :
Tant que bit 0 de LSR = 0 : attendre
Lire la registre de données
Emission carac :
Ecrire le registre de données
Tant que bit 6 de LSR = 0 : attendre
Interruptions :
Il faut détourner les interruptions
( void interrupt (*ancien_sousprg ), void
interrupt nouveau_sousprog(); ,
getvect , setvect avec 0x0C pour COM1, 0x0B
pour COM2 )
Il faut autoriser les interruptions sur le
PIC ( mettre à 0 le bit 4 pour COM1 ou 3 pour COM2 de 0x21 )
Remarques :
1) Sur certaines cartes, la sortie OUT2 de
lUART intervient dans le contrôle dinterruption.
Il est parfois nécessaire de la mettre à
1 ( bit 3 mis à 1 dans MCR )
2) Il faut acquitter les interruptions dans
le sous prog : outportb(0x20,0x20)