Page suivantePage pr�c�denteTable des mati�res

3. Exemples de programmes

Tous les exemples ont �t� extraits de miniterm.c. Le tampon d'entr�e est limit� � 255 caract�res, tout comme l'est la longueur maximale d'une ligne en mode canonique (<linux/limits.h> ou <posix1_lim.h>).

R�f�rez-vous aux commentaires dans le code source pour l'explication des diff�rents modes d'entr�e. J'esp�re que le code est compr�hensible. L'exemple sur l'entr�e canonique est la plus comment�e, les autres exemples sont comment�s uniquement lorsqu'ils diff�rent, afin de signaler les diff�rences.

Les descriptions ne sont pas compl�tes, mais je vous encourage � modifier les exemples pour obtenir la solution la plus int�ressante pour votre application.

N'oubliez pas de donner les droits corrects aux ports s�rie (par exemple, chmod a+rw /dev/ttyS1) !

3.1 Traitement canonique

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
/* les valeurs pour la vitesse, baudrate, sont d�finies dans <asm/termbits.h>, qui est inclus
dans <termios.h> */
#define BAUDRATE B38400
/* changez cette d�finition pour utiliser le port correct */
#define MODEMDEVICE "/dev/ttyS1"
#define _POSIX_SOURCE 1 /* code source conforme � POSIX */
#define FALSE 0
#define TRUE 1
volatile int STOP=FALSE;
main()
{
 int fd,c, res;
 struct termios oldtio,newtio;
 char buf[255];
/*
 On ouvre le p�riph�rique du modem en lecture/�criture, et pas comme
 terminal de contr�le, puisque nous ne voulons pas �tre termin� si l'on
 re�oit un caract�re CTRL-C.
*/
 fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
 if (fd <0) {perror(MODEMDEVICE); exit(-1); }
 tcgetattr(fd,&oldtio); /* sauvegarde de la configuration courante */
 bzero(&newtio, sizeof(newtio)); /* on initialise la structure � z�ro */
/*
 BAUDRATE: Affecte la vitesse. vous pouvez �galement utiliser cfsetispeed
 et cfsetospeed.
 CRTSCTS : contr�le de flux mat�riel (uniquement utilis� si le c�ble a
 les lignes n�cessaires. Voir la section 7 du Serial-HOWTO).
 CS8     : 8n1 (8 bits,sans parit�, 1 bit d'arr�t)
 CLOCAL  : connexion locale, pas de contr�le par le modem
 CREAD   : permet la r�ception des caract�res
*/
 newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
/*
 IGNPAR  : ignore les octets ayant une erreur de parit�.
 ICRNL   : transforme CR en NL (sinon un CR de l'autre c�t� de la ligne
 ne terminera pas l'entr�e).
 sinon, utiliser l'entr�e sans traitement (device en mode raw).
*/
 newtio.c_iflag = IGNPAR | ICRNL;
/*
 Sortie sans traitement (raw).
*/
 newtio.c_oflag = 0;
/*
 ICANON  : active l'entr�e en mode canonique
 d�sactive toute fonctionnalit� d'echo, et n'envoit pas de signal au
 programme appelant.
*/
 newtio.c_lflag = ICANON;
/*
 initialise les caract�res de contr�le.
 les valeurs par d�faut peuvent �tre trouv�es dans
 /usr/include/termios.h, et sont donn�es dans les commentaires.
 Elles sont inutiles ici.
*/
 newtio.c_cc[VINTR]    = 0;     /* Ctrl-c */
 newtio.c_cc[VQUIT]    = 0;     /* Ctrl-\ */
 newtio.c_cc[VERASE]   = 0;     /* del */
 newtio.c_cc[VKILL]    = 0;     /* @ */
 newtio.c_cc[VEOF]     = 4;     /* Ctrl-d */
 newtio.c_cc[VTIME]    = 0;     /* compteur inter-caract�re non utilis� */
 newtio.c_cc[VMIN]     = 1;     /* read bloquant jusqu'� l'arriv�e d'1 caract�re */
 newtio.c_cc[VSWTC]    = 0;     /* '\0' */
 newtio.c_cc[VSTART]   = 0;     /* Ctrl-q */
 newtio.c_cc[VSTOP]    = 0;     /* Ctrl-s */
 newtio.c_cc[VSUSP]    = 0;     /* Ctrl-z */
 newtio.c_cc[VEOL]     = 0;     /* '\0' */
 newtio.c_cc[VREPRINT] = 0;     /* Ctrl-r */
 newtio.c_cc[VDISCARD] = 0;     /* Ctrl-u */
 newtio.c_cc[VWERASE]  = 0;     /* Ctrl-w */
 newtio.c_cc[VLNEXT]   = 0;     /* Ctrl-v */
 newtio.c_cc[VEOL2]    = 0;     /* '\0' */
/*
 � pr�sent, on vide la ligne du modem, et on active la configuration
 pour le port
*/
 tcflush(fd, TCIFLUSH);
 tcsetattr(fd,TCSANOW,&newtio);
/*
 la configuration du terminal est faite, � pr�sent on traite
 les entr�es
 Dans cet exemple, la r�ception d'un 'z' en d�but de ligne mettra
 fin au programme.
*/
 while (STOP==FALSE) {     /* boucle jusqu'� condition de terminaison */
 /* read bloque l'ex�cution du programme jusqu'� ce qu'un caract�re de
 fin de ligne soit lu, m�me si plus de 255 caract�res sont saisis.
 Si le nombre de caract�res lus est inf�rieur au nombre de caract�res
 disponibles, des read suivant retourneront les caract�res restants.
 res sera positionn� au nombre de caract�res effectivement lus */
 res = read(fd,buf,255);
 buf[res]=0;       /* on termine la ligne, pour pouvoir l'afficher */
 printf(":%s:%d\n", buf, res);
 if (buf[0]=='z') STOP=TRUE;
 }
 /* restaure les anciens param�tres du port */
 tcsetattr(fd,TCSANOW,&oldtio);
}

3.2 Entr�e non canonique

Dans le mode non canonique, les caract�res lus ne sont pas assembl�s ligne par ligne, et ils ne subissent pas de traitement (erase, kill, delete, etc...). Deux param�tres contr�lent ce mode : c_cc[VTIME] positionne le timer de caract�res, et c_cc[VMIN] indique le nombre minimum de caract�res � recevoir avant qu'une lecture soit satisfaite.

Si MIN > 0 et TIME = 0, MIN indique le nombre de caract�res � recevoir avant que la lecture soit satisfaite. TIME est �gal � z�ro, et le timer n'est pas utilis�.

Si MIN = 0 et TIME > 0, TIME est utilis� comme une valeur de timeout. Une lecture est satisfaite lorsqu'un caract�re est re�u, ou que la dur�e TIME est d�pass�e (t = TIME * 0.1s). Si TIME est d�pass�, aucun caract�re n'est retourn�.

Si MIN > 0 et TIME > 0, TIME est employ� comme timer entre chaque caract�re. La lecture sera satisfaite si MIN caract�res sont re�us, ou que le timer entre deux caract�res d�passe TIME. Le timer est r�initialis� � chaque fois qu'un caract�re est re�u, et n'est activ� qu'apr�s la r�ception du premier caract�re.

Si MIN = 0 et TIME = 0, le retour est imm�diat. Le nombre de caract�res disponibles, ou bien le nombre de caract�res demand� est retourn�. Selon Antonino (voir le paragraphe sur les participations), vous pouvez utiliser un fcntl(fd, F_SETFL, FNDELAY); avant la lecture pour obtenir le m�me r�sultat.

Vous pouvez tester tous les modes d�crit ci-dessus en modifiant newtio.c_cc[VTIME] et newtio.c_cc[VMIN].

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#define BAUDRATE B38400
#define MODEMDEVICE "/dev/ttyS1"
#define _POSIX_SOURCE 1 /* code source conforme � POSIX */
#define FALSE 0
#define TRUE 1
volatile int STOP=FALSE;
main()
{
 int fd,c, res;
 struct termios oldtio,newtio;
 char buf[255];
 fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
 if (fd <0) {perror(MODEMDEVICE); exit(-1); }
 tcgetattr(fd,&oldtio); /* sauvegarde de la configuration courante */
 bzero(&newtio, sizeof(newtio));
 newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
 newtio.c_iflag = IGNPAR;
 newtio.c_oflag = 0;
 /* positionne le mode de lecture (non canonique, sans echo, ...) */
 newtio.c_lflag = 0;
 newtio.c_cc[VTIME]    = 0;   /* timer inter-caract�res non utilis� */
 newtio.c_cc[VMIN]     = 5;   /* read bloquant jusqu'� ce que 5 */
 /* caract�res soient lus */
 tcflush(fd, TCIFLUSH);
 tcsetattr(fd,TCSANOW,&newtio);
 while (STOP==FALSE) {       /* boucle de lecture */
 res = read(fd,buf,255);   /* retourne apr�s lecture 5 caract�res */
 buf[res]=0;               /* pour pouvoir les imprimer... */
 printf(":%s:%d\n", buf, res);
 if (buf[0]=='z') STOP=TRUE;
 }
 tcsetattr(fd,TCSANOW,&oldtio);
}

3.3 Lecture asynchrone

#include <termios.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <sys/types.h>
#define BAUDRATE B38400
#define MODEMDEVICE "/dev/ttyS1"
#define _POSIX_SOURCE 1 /* code source conforme � POSIX */
#define FALSE 0
#define TRUE 1
volatile int STOP=FALSE;
void signal_handler_IO (int status);   /* le gestionnaire de signal */
int wait_flag=TRUE;              /* TRUE tant que re�u aucun signal */
main()
{
 int fd,c, res;
 struct termios oldtio,newtio;
 struct sigaction saio;        /* d�finition de l'action du signal */
 char buf[255];
 /* ouvre le port en mon non-bloquant (read retourne imm�diatement) */
 fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
 if (fd <0) {perror(MODEMDEVICE); exit(-1); }
 /* installe le gestionnaire de signal avant de passer le port en
 mode asynchrone */
 saio.sa_handler = signal_handler_IO;
 saio.sa_mask = 0;
 saio.sa_flags = 0;
 saio.sa_restorer = NULL;
 sigaction(SIGIO,&saio,NULL);
 /* permet au processus de recevoir un SIGIO */
 fcntl(fd, F_SETOWN, getpid());
 /* rend le descripteur de fichier asynchrone (la page de manuel
 indique que seuls O_APPEND et O_NONBLOCK fonctionnent avec
 F_SETFL...) */
 fcntl(fd, F_SETFL, FASYNC);
 tcgetattr(fd,&oldtio); /* sauvegarde de la configuration courante */
 /* positionne les nouvelles valeurs pour lecture canonique */
 newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
 newtio.c_iflag = IGNPAR | ICRNL;
 newtio.c_oflag = 0;
 newtio.c_lflag = ICANON;
 newtio.c_cc[VMIN]=1;
 newtio.c_cc[VTIME]=0;
 tcflush(fd, TCIFLUSH);
 tcsetattr(fd,TCSANOW,&newtio);
 /* on boucle en attente de lecture. g�n�ralement, on r�alise
 des traitements � l'int�rieur de la boucle */
 while (STOP==FALSE) {
 printf(".\n");usleep(100000);
 /* wait_flag = FALSE apr�s r�ception de SIGIO. Des donn�es sont
 disponibles et peuvent �tre lues */
 if (wait_flag==FALSE) {
 res = read(fd,buf,255);
 buf[res]=0;
 printf(":%s:%d\n", buf, res);
 if (res==1) STOP=TRUE; /* on arr�te la boucle si on lit une
 ligne seule */
 wait_flag = TRUE;      /* on attend de nouvelles donn�es */
 }
 }
 /* restaure les anciens param�tres du port */
 tcsetattr(fd,TCSANOW,&oldtio);
}
/***************************************************************************
* gestionnaire de signal. Positionne wait_flag � FALSE, pour indiquer �    *
* la boucle ci-dessus que des caract�res ont �t� re�us.                    *
***************************************************************************/
void signal_handler_IO (int status)
{
 printf("r�ception du signal SIGIO.\n);
 wait_flag = FALSE;
}

3.4 Multiplexage en lecture

Cette section est r�duite au minimum, et n'est l� que pour vous guider. Le code source d'exemple pr�sent� est donc r�duit au strict minimum. Il ne fonctionnera pas seulement avec des ports s�rie, mais avec n'importe quel ensemble de descripteurs de fichiers.

L'appel syst�me select et les macros qui lui sont attach�es utilisent un fd_set. C'est un tableau de bits, qui dispose d'un bit pour chaque descripteur de fichier valide. select accepte un fd_set ayant les bits positionn�s pour les descripteurs de fichiers qui conviennent, et retourne un fd_set, dans lequel les bits des descripteurs de fichier o� une lecture, une �criture ou une exception sont positionn�s. Toutes les manipulations de fd_set sont faites avec les macros fournies. Reportez vous �galement � la page de manuel de select(2).

#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
main()
{
 int    fd1, fd2;  /* entr�es 1 et 2 */
 fd_set readfs;    /* ensemble de descripteurs */
 int    maxfd;     /* nombre max des descripteurs utilis�s */
 int    loop=1;    /* boucle tant que TRUE */
 /* open_input_source ouvre un p�riph�rique, configure le port
 correctement, et retourne un descripteur de fichier. */
 fd1 = open_input_source("/dev/ttyS1");   /* COM2 */
 if (fd1<0) exit(0);
 fd2 = open_input_source("/dev/ttyS2");   /* COM3 */
 if (fd2<0) exit(0);
 maxfd = MAX (fd1, fd2)+1; /* num�ro maximum du bit � tester */
 /* boucle d'entr�e */
 while (loop) {
 FD_SET(fd1, &readfs);  /* test pour la source 1 */
 FD_SET(fd2, &readfs);  /* test pour la source 2 */
 /* on bloque jusqu'� ce que des caract�res soient
 disponibles en lecture */
 select(maxfd, &readfs, NULL, NULL, NULL);
 if (FD_ISSET(fd1))         /* caract�res sur 1 */
 handle_input_from_source1();
 if (FD_ISSET(fd2))         /* caract�res sur 2 */
 handle_input_from_source2();
 }
}

L'exemple ci-dessus bloque ind�finiment, jusqu'� ce que des caract�res venant d'une des sources soient disponibles. Si vous avez besoin d'un timeout, remplacez juste l'appel � select par :

int res;
struct timeval Timeout;
/* fixe la valeur du timeout */
Timeout.tv_usec = 0;  /* millisecondes */
Timeout.tv_sec  = 1;  /* secondes */
res = select(maxfd, &readfs, NULL, NULL, &Timeout);
if (res==0)
/* nombre de descripteurs de fichiers avec caract�res
 disponibles = 0, il y a eu timeout */

Cet exemple verra l'expiration du delai de timeout apr�s une seconde. S'il y a timeout, select retournera 0, mais fa�tes attention, Timeout est d�cr�ment� du temps r�ellement attendu par select. Si la valeur de timeout est 0, select retournera imm�diatement.


Page suivantePage pr�c�denteTable des mati�res

Hosting by: Hurra Communications GmbH
Generated: 2007-01-26 18:01:16