Retrouvez cet article dans : Linux Magazine Hors série 23
Rappels sur le port série
Principe du port série
Le port série est une interface hardware permettant de transmettre des informations binaires de manière séquentielle (1 par 1). Par opposition, un port parallèle comme le port Centronics des imprimantes transmet les bits de manière simultanée (8 à la fois). Le mode de transmission sur une ligne série (appelée aussi RS-232) est décrit dans le schéma ci-dessous :
Fig. 1
L’arrivée des données est indiquée par un bit de START. Les données sont transmises sous forme d’une suite de 5 à 8 bits contenant éventuellement un bit de PARITE utilisé pour la détection des erreurs de transmission. La fin de la transmission est indiquée par un bit de STOP. La fréquence de transmission des bits indique la vitesse de la ligne : 9600 bits/s, 19200 bits/s, etc.Connectique et signaux
Concrètement, un port série est matérialisé par un connecteur contenant 25 points (DB25) ou 9 points (DB9). Ce dernier est le plus répandu sur les machines modernes lorsqu’elles ont encore la chance de disposer d’un tel port. Au besoin, on pourra acquérir une carte PCI/Série pour quelques euros. Un port série à bas débit n’a besoin que de trois lignes :

- Le signal DTR indique au MODEM que le calculateur est actif. La chute de ce signal provoquera la déconnexion du MODEM, ce qui est bien pratique si l’on veut éviter de rincer excessivement France Télécom ;-))
- Le signal DCD indique au calculateur que le MODEM est connecté au MODEM distant. La chute de ce signal (indiquant la déconnexion) sera détectable par le programme applicatif afin de déclencher la procédure adéquate.

Détection du hardware RS-232 par LINUX
Il existe de nombreux circuits permettant de gérer des ports RS-232. Les plus anciens se souviendront avec nostalgie de l’ACIA 6850, périphérique bien connu de l’antique processeur 6800 de chez MOTOROLA. Les PC d’aujourd’hui utilisent des circuits appelés UART comme le 16550A. Le noyau Linux contient naturellement des pilotes pour ce type de périphérique. La détection des ports série par le noyau est indiqué au démarrage de Linux par les lignes :Serial: 8250/16550 driver $Revision: 1.90 $ 48 ports, IRQ sharing enabled ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A ttyS1 at I/O 0x2f8 (irq = 3) is a 16550APour cela il faut avoir validé l’option suivante lors de la compilation du noyau :
Standard/generic serial support (CONFIG_SERIAL) [Y/m/n/?]Si le système dispose d’une carte série additionnelle, on verra apparaître à la suite les messages :
tty02 at I/O 0x03e8 (irq = 4) is a 16550ADans cet exemple, on voit que la deuxième carte est bien détectée à une adresse différente (3e8), mais que le système lui a attribué la même interruption (IRQ) que le premier port série. Pour assurer le bon fonctionnement, il sera nécessaire de modifier le niveau d’interruption en accord avec la configuration de la carte. Pour cela, on utilisera la commande
/bin/setserial /dev/cua2 irq 5On voit que les ports série sont utilisables à travers les fichiers spéciaux
Utilisation à travers le shell
La commande stty
Cette commande permet de visualiser et modifier les paramètres d’un terminal. Cette dénomination est à prendre au sens large et l’utilisation depierre@mmxpf % stty -a speed 9600 baud; rows 24; columns 80; line = 0; intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = ; eol2 = ; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0; -parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany -imaxbel opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echokeL’option
stty -a < /dev/modemLe device
pierre@mmxpf % ls -l /dev/modem lrwxrwxrwx /dev/modem -> cua0Le paramétrage d’une ligne série par un shell-script utilisant stty est de la même veine :
#!/bin/sh ( stty 115200 stty cs8 stty -parenb stty -parodd stty -clocal stty crtscts stty -echo # Suite du script ... ) < /dev/cua0 > /dev/cua0Dans cet exemple, on effectue le paramétrage suivant :

La commande chat
Le mot chat signifie en anglais " bavarder, discuter ". La commandechat -v "" ATM0\&C1\&D2\&K3 OK ATDT3611 CONNECTCe qui signifie :

Sep 26 21:31:01 mmxpf chat[463]: send (ATM0&C1&D2&K3^M) Sep 26 21:31:02 mmxpf chat[463]: expect (OK) Sep 26 21:31:03 mmxpf chat[463]: -- got it Sep 26 21:31:03 mmxpf chat[463]: send (ATDT3611^M) Sep 26 21:31:03 mmxpf chat[463]: expect (CONNECT) Sep 26 21:31:05 mmxpf chat[463]: -- got itLorsque le script est au point, il suffit de rediriger l’entrée et la sortie sur le device du modem :
chat -v "" ATM0\&C1\&D2\&K3 OK ATDT3611 CONNECT < /dev/cua0 > /dev/cua0Forts de notre expérience de la commande stty, nous pourrons donc combiner l’initialisation de la ligne série avec le chat-script à envoyer au modem :
#!/bin/sh ( # Init ligne série stty 115200 stty cs7 stty parenb stty -clocal stty crtscts stty -echo # Init modem et appel chat -v "" ATM0\&C1\&D2\&K3 OK ATDT3611 CONNECT ) < /dev/cua0 > /dev/cua0Le man chat vous donnera beaucoup plus d’informations concernant les possibilités de ce petit programme comme par exemple la définition du chat-script dans un fichier séparé.
Programmation des ports série en C
Interface POSIX (termios)
La programmation des ports série sous Linux utilise l’interface POSIX définie dans le fichier#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <fcntl.h>
main (int ac, char **av)
{
int fd;
struct termios tty, old;
/* Ouverture du device */
if ((fd = open (av[1], O_RDWR)) < 0) {
perror (av[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);
}
On pourra faire exactement la même chose en shell en faisant :
stty 0 < /dev/cua0 > /dev/cua0Par défaut, une ligne série sous Linux 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 RETURN). Cela signifie que le programme applicatif ne pourra disposer de la saisie que lorsque le séparateur est reçu. Dans le mode canonique, un certain nombre de caractères de contrôles sont disponibles (effacement, etc. voir la commande
/* Fixe un device en mode RAW */
void raw_mode (fd, old_term)
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’echo */
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 controle 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);
}
Autre type de configuration
Un descripteur de fichier sur un port série sera ouvert par une ligne du typefd = open (device_name, O_RDWR)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
fd = open (device_name, O_RDWR | O_NDELAY)
Conclusion
Malgré son grand âge, le port série est largement utilisé dans de nombreuses applications industrielles (acquisition de données, pilotage d’équipement). La maîtrise des techniques d’exploitation de cette interface est souvent indispensable pour la réalisation d’un système industriel complexe. En dépit de son apparente complexité, l’interface POSIX utilisée sous LINUX est d’une grande efficacité et laisse peu de place aux comportements imprévus. Liens- Le Serial-HOWTO sur : http://www.freenix.fr/unix/linux/HOWTO-vo/Serial-HOWTO.html
- Le Serial-Programming-HOWTO sur : http://www.freenix.fr/unix/linux/HOWTO-vo/Serial-Programming-HOWTO.html
- Le document Serial Programming Guide for POSIX Compliant Operating Systems sur : http://dns-gate.easysw.com/~mike/serial
- L’ouvrage Programmation Linux 2.0 (Card/Dumas/Mével) aux éditions EYROLLES
- L’utilitaire Kermit sur : http://www.columbia.edu/kermit/ck60.html
- L’utilitaire Minicom sur : http://www.pp.clinet.fi/~walker/minicom.html
Retrouvez cet article dans : Linux Magazine Hors série 23





Bonjour,
les ports séries sont de moins en moins présents sur nos PC (surtout sur les portables !). Précisons qu’il existe des convertisseurs USB-Série qui permettent de résoudre le problème. Pour les plus curieux ces convertisseurs utilisent souvent un chipset Prolific PL 2303. http://www.prolific.com.tw/eng/Download-2.asp?ID=17 ou comme les FTDI FT232 http://www.ftdichip.com ou les Silicon Laboratories CP2102 CP2103 USB
http://www.silabs.com
On peut trouver des vendeurs comme SparkFun http://www.sparkfun.com qui montent ce genre de chipsets (souvent des Composants Montés en Surface CMS) directement sur des circuits imprimés appelés “Breakout board”
http://www.sparkfun.com/commerce/product_info.php?products_id=718 Breakout Board for FT232RL USB to Serial
D’autres références de chipsets permettant la convertion USB/série peuvent être trouvés en regardant la liste des Vendor ID (VID) / Product ID (PID) de périphériques USB : http://www.linux-usb.org/usb.ids et en recherchant le mot “serial”.
Cordialement