Le port série

Introduction

Malgré son grand âge, le port série est très largement utilisé par les ordinateurs pour communiquer avec des périphériques (imprimante, souris, modem...) car il est très simple à utiliser et ne nécéssite que peu de fils. Plus difficile à mettre en oeuvre que le port parallèle, il se révèle cependant plus puissant et plus universel.

Le support physique utilisé

Le connecteur utilisé à l'origine pour le port série est le connecteur DB25, mais depuis quelques années, on trouve de plus en plus de connecteurs DB9. Au niveau du PC, on utilise des connecteurs mâles, tandis qu'au niveau du périphérique, on trouve des connecteurs femelles. Prise DB9 Prise DB25

Quelque soit le type de connecteur utilisé, une liaison série comporte 8 signaux différents, plus une ou deux masses :

Broche DB9 Broche DB25 Nom DTE DCE Description
x 1 PG x x Masse de protection (PG = Protecting Ground)
Ne pas utiliser comme masse du signal !
3 2 TD S E Transmission de données (TD = Transmit Data)
2 3 RD E S Réception de données (RD = Receive Data)
7 4 RTS S E Demande d'autorisation à émettre (RTS = Request To Send)
8 5 CTS E S Autorisation d'émettre (CTS = Clear To Send)
6 6 DSR E S Prêt à recevoir (DSR = Data Set Ready)
5 7 SG E S Masse du signal (SG = Signal Ground)
1 8 DCD E S Détection de porteuse (DCD = Data Carrier Detect)
4 20 DTR S E Équipement prêt (DTR = Data Terminal Ready)
9 22 RI E S Détection de sonnerie (RI = Ring Indicator)

DTE signifie Data Terminal Equipment et correspond en général au PC, alors que DCE signifie Data Communication Equipement et correspond au périphérique.

D'un point de vue électrique, les différents signaux présents sur le port série sont définis par la norme RS232. Afin d'avoir une plus grande immunité au parasites, on utilise des tensions comprises entre -25 et +25V. Une tension comprise entre -3V et -25V représente un 1 logique (mark), alors qu'une tension comprise entre +3V et +25V représente un 0 logique (space).

Certains périphériques comme des microprocesseurs utilisent une logique TTL, bien connue des électroniciens. Afin de passer d'une logique RS232, dite inversée, à une logique TTL, certains fabricants ont développé des circuits intégrés spécifiques. Par exemple, le fabricant Maxim produit un composant appelé MAX232 pour adapter ces niveaux.

Le protocole utilisé

L'interruption 14H du BIOS

L'interruption 14h du BIOS propose plusieurs fontions pour la communication série du PC. A chaque appel, le registre AH doit contenir le numéro de l'interface. La première interface (COM1) possède le numéro 0. Notez que l'interruption vérifie la validité de la valeur passée à DX. Les fonctions ne sont pas executées si le numéro de l'interface n'est pas valide.

Fonction 0 - Initialisation du port série

Entrée :
AH = numéro de la fonction, c'est à dire 0
DX = numéro de l'interface (0 à 3)
AL = paramètres de configuration
Sortie :
AH = état de l'interface
AL = état du modem

La première interface série porte ne numéro 0, la seconde le numéro 1, etc ...

Les paramètres de configuration (octet dans AL lors de l'appel) sont les suivants :

En sortie, le registre AL retourne le contenu du registre d'état du modem de l'UART :

En sortie, le registre AH retourne le contenu du registre d'état de ligne de l'UART :

Le bit 7 fournit une information particulière qui n'est pas associée à une ligne de communication. En effet si une erreur est détectée, l'interruption 14h exécute un certain nombre de nouvelles tentatives avant de reandre son véritable verdict. Si toutes les tentatives échouent, l'état de l'interface série est alors retourné dans AH, dont le bit 7 est mis à 1 pour signaler que le temps imparti est dépassé.

Fonction 1 - Emission d'un caractère

Entrée :
AH = numéro de la fonction, c'est à dire 1
DX = numéro de l'interface (0 à 3)
AL = caractère à émettre
Sortie :
AH = état de l'interface (voir fonction 0)

Fonction 2 - Réception d'un caractère

Entrée :
AH = numéro de la fonction, c'est à dire 2
DX = numéro de l'interface (0 à 3)
Sortie :
AH = état de l'interface (voir fonction 0)
AL = caractère reçu (si le bit 7 de AH est à 0)

Fonction 3 - Test de l'état de la communication

Entrée :
AH = numéro de la fonction, c'est à dire 3
DX = numéro de l'interface (0 à 3)
Sortie :
AH = état de l'interface (voir fonction 0)
AL = état du modem (voir fonction 0)

Remarque 1 : Les fonctions 1, 2 et 3 de l'interruption 14h peuvent affecter le registre de contrôle du modem de l'UART. Si vous souhaitez gérer ce registre de manière spécifique, il est préférable de manipuler directement l'UART, sans passer par l'interruption 14h. Voir paragraphe suivant.

Remarque 2 : Cette interruption est maintenant dépassée, il faut l'utiliser uniquement dans le cadre d'une programmation sous DOS. Dans le cas contraire, il est conseillé d'utiliser la fonction du système d'exploitation utilisé ou un accès direct à l'interface série via les ports d'entrée/sortie. Pour un système POSIX (par exemple GNU/Linux), voir le paragraphe programmation POSIX avec TERMIOS.

Les ports d'entrée/sortie des interfaces séries

Dans beaucoupe de cas, l'interruption 14h ne sera pas suffisante pour piloter un périphérique connecté à l'interface série. Il faut alors gérer directement les ports d'E/S.

Cette interface se programme à l'aide de huit registres différents. Si le PC possède plusieurs ports série, il y aura autant de groupe de huits registres que de nombre de ports série.

En général, le première interface série est associée au ports 3f8h à 3ffh, et la seconde aux ports 2f8h à 2ffh. Néanmoins, ces valeurs ne sont pas universelles. Pour en connaître la valeur, le BIOS possède une table à l'adresse 0040h:0000h comportant les adresses de base des quatres interfaces série :

Les adresses ci-dessus sont remplies par le POST (Power On Self Test) au démarrage de l'ordinateur. Le POST ne laisse jamais d'intervalle. Les numéros des ports série peuvent être redéfinis en changeant ces valeurs.

Venons en maintenant à la description des différents registres.

Adresse de base : registre de transmission et de réception

En lecture, ce registre est un tampon qui contient le dernière caractère reçu.

En écriture, ce registre est un tampon, dans lequel doit être placé un caractère à émettre.

Adresse de base + 1 : registre d'autorisation des interruptions

Ce registre conserve un masque des interruptions autorisées. Lorsqu'un des bits 0 à 3 est mis à 1, l'UART est autorisé à effectuer une demande d'interruption si la condition correspondante est réalisée :

Notez que, sur le PC, l'UART n'exécute une demande d'interruption que si le bit 3 du registre de contrôle du modem est mis à 1. Voir le commentaire concernant ce registre.

Adresse de base + 2 : registre d'indentification des interruptions

Il ne faut pas écrire dans ce registre. Il peut être lu afin d'identifier le niveau de priorité d'une interruption demandée par l'UART. Lorsque le bit 0 est à 1, aucune demande d'interruption n'est en cours. Si une interruption est en attente, le niveau de priorité est retourné dans les bits 1 et 2.

Adresse de base + 3 : registre de contrôle de ligne

Ce registre de contrôle permet de spécifier les différentes caractéristiques de la communication série.

Adresse de base + 4 : registre de contrôle du modem

Ce registre contrôme l'interface avec le modem :

Remarque : L'interface du PC utilise la ssortie OUT2 pour valider l'autorisation des interruptions électronique par les UART (compatibilité Hayes). Le bit 3 doit donc être mis à 1 pour activer les demandes d'interruption.

Adresse de base + 5 : registre d'état de ligne

Il est conseillé de ne jamais écrire dans se registre. Il peut être lu afin de connaître l'état courant de la ligne série.

Remarque : Les bits 1 à 4 signalent des états d'erreur et peuvent provoquer une demande d'interruptions si le bit 2 du registre d'autorisation des interruptions est à 1. Les bits 0 et 5 peuvent également déclencher une demade d'interruption si le registre d'autorisation des interruptions le permet.

Adresse de base + 6 : registre d'état du modem

Ce registre donne l'état des lignes de contrôle en provenance du modem et signale les éventuels changements survenus sur ces lignes depuis la dernière lecture de ce registre.

Remarque : Les bits 0 à 3 signalent des changement d'état et peuvent provoquer une demande d'interruption si le bit 3 du registre d'autorisation des interruptions est à 1.

Adresse de base + 7 : registre inutilisé (Scratch)

Programmation POSIX avec TERMIOS

La programmation des ports série sous les systèmes d'exploitation POSIX (par exemple GNU/Linux) utilise l'interface TERMIOS. Le principe est d'appliquer un ensemble de paramètres définis dans une structure termios à un descripteur de fichier (file-descriptor) ouvert sur un terminal donné (par exemple un ligne série). Lorsque le descripteur de fichier est correctement configuré, on peut l'exploiter grâce aux appels systèmes standards, read, write, select, etc.

Le but de ce paragraphe n'est pas de fournir une description complète de termios : vous pouvez pour cela vous référer au man termios ou au divers documents consacrés au sujet.

Le premier exemple ci-dessous permet de forcer le raccrochage (hangup) d'un modem en faisant chuter le signal DTR. Dans la définition de l'interface POSIX des terminaux, cela s'effectue simplement en positionnant la vitesse à 0 (valeur B0) :

#include <fcntl.h>
#include <termios.h>

main(int argc, char *argv[])
{
  int fd;
  struct termios tty, old;
  /* Ouverture du device */
  if ((fd = open(argv[1], O_RDWR)) < 0)
  {
    perror(argv[1]);
    exit(1);
  }
  /* Lecture des paramètres */
  tcgetattr(fd, &tty);
  tcgetattr(fd, &old);
  /* On passe la vitesse à 0 ==> hangup */
  cfsetospeed(&tty, B0);
  cfsetispeed(&tty, B0);
  /* On applique le nouveau paramètrage pendant 1s */
  tcsetattr(fd, TCSANOW, &tty);
  sleep(1);
  /* On revient à l'ancien et on quitte */
  tcsetattr(fd, TCSANOW, &old);
  close(fd);
}
    

Par défaut, une ligne série est ouverte en mode canonique. Le mode canonique consiste à traiter les entrées d'un terminal comme une ligne terminée par un séparateur (le plus souvent LF : line-feed correspondant à la touche Entrée). Cela signifier que le programme applicatif ne pourra disposer de la saisie que lorsque le séparateur sera reçu. Dans le mode canonique, un certain nombre de caractères de contrôle sont disponibles (effacement, etc.).

Ce comportement est adapté au traitement d'un terminal réel avec un dialogue opérateur mais il n'est pas utilisable dans le cas du dialogue avec un équipement de type modem, par exemple. Le deuxième exemple permet donc de positionner une ligne série en mode direct (raw) et donc d'inhiber le mode canonique :

/* Fixe un device en mode RAW */
void raw_mode (int fd, struct termios *old_term)
{
  struct termios term;
  tcgetattr(fd, &term);
  /* Sauve l'ancienne config dans le paramètre */
  tcgetattr(fd, old_term);
  /* mode RAW, pas de mode canonique, pas d'écho */
  term.c_iflag = IGNBRK;
  term.c_lflag = 0;
  term.c_oflag = 0;
  /* Controle de flux hardware (RTS/CTS) */
  term.c_cflag |= (CREAD | CRTSCTS);
  /* 1 caractère suffit */
  term.c_cc[VMIN] = 1;
  /* Donnée disponible immédiatement */
  term.c_cc[VTIME] = 0;
  /* Inhibe le contrôle de flux XON/XOFF */
  term.c_iflag &= ~(IXON | IXOFF | IXANY);
  /* 8 bits de données, pas de parité */
  term.c_cflag &= ~(PARENB | CSIZE);
  term.c_cflag |= CS8;
  /* Gestion des signaux modem */
  term.c_cflag &= ~CLOCAL;
  tcsetattr(fd, TCSANOW, &term);
}
    

Un descripteur de fichier sur un port série sera ouvert par une ligne du type fd = open(device_name, OR_RDWDR). Par défaut cette ligne est ouverte en mode bloquant, ce qui peut parfois poser des problèmes dans le cas de l'utilisation du device /dev/ttySx. On peut alors ouvrir le device en mode non bloquant par l'appel : fd = open(device_name, OR_RDWDR | O_NDELAY).

Protocoles de quelques périphériques RS232

Les souris

Les modems

La plupart des modems se laissent commander par le jeu de commande HAYES. Chaque ligne de commande commence par AT, suivie d'une des nombreuses commandes listées ici et d'un retour chariot. Cette liste n'est pas exhaustive ; la plupart des modems ont leur propres commandes, mais celles listées ici sont disponibles avec la plupart des modems.

A/
Répéter la dernière commande (non précédé de AT)
A
Décrocher - Engager une connexion sans appel
B
Selectionner le standard de communication :
  • B0 - CCITT
  • B1 - Bell
C
Active ou désactive la porteuse :
  • C0 - porteuse activée
  • C1 - porteuse désactivée
D
Composer un numéro. Normallement suivi par :
  • T - numérotation par tonalités
  • P - numérotation par impulsions
  • rien - numérotation en fonction de la configuration (voir ATP/ATT)

puis par une séquence composée des caractères suivants :
  • 0-9 - the numbers to be dialed
  • W - attendre la tonalité
  • , - attendre 2 secondes
  • @ - attendre 5 secondes
  • ! - flash (racrocher la ligne pendant une demi-seconde)
  • ; - retour au mode commande après numérotation
  • R - démarrer la connexion juste après la numérotation (par ex. ATDPR équivaut à ATA)
  • S=n - Sélection du numéro mémorisé (ATDS sélectionne le numéro mémorisé sous S=0, ATDS=1 le numéro mémorisé sous S=1, etc.)

Si vous entrez juste ATD, le modem décroche sans numéroter.
E
Active ou désactive l'écho local
  • E0 - commandes sans écho
  • E1 - commandes avec écho
H
Raccrocher