> Le Mercredi 24 Septembre 2003 15:40, PierreDu a écrit :
> > Je suis en train de programmer un petit truc en Python, qui doit envoyer
> > des données sur port série... Quelqu'un sait-il comment on fait sous
> > linux (un didacticiel en français serait le bienvenu !!!)
>
> Probablement en utilisant le fichier /dev/ttyS0 (ou les autres, suivant le
> port que tu veux utiliser), mais je n'en sais pas plus.
Pour python je n'ai rien.
Mais pour le port série c'est la après :
Le port série sous LINUX :
Il existe pas mal d'aide sur le net, je m'en suis inspiré pour tapper cela.
Vous trouverez qcq lien a la fin de ce document.
Avant toute chose prenez la peine de lire le how to linux sur la
programmation serie, cela donne une bonne entrée en matière.
Voyons maintenant ce qui est utile pour la programmation :
* Les options de open :
SYNOPSIS
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
int creat(const char *pathname, mode_t mode);
DESCRIPTION
open essaye d'ouvrir un fichier et retourne un descripteur de
fichier (petit entier non négatif à utiliser avec read, write, etc...)
flags est l'un des éléments O_RDONLY, O_WRONLY ou O_RDWR qui
réclament respectivement l'ouverture du fichier en lecture seule, écriture
seule, ou lecture/écriture.
flags peut aussi être un OU binaire ( | ) avec un ou
plusieurs des éléments suivants :
O_CREAT
Créer le fichier s'il n'existe pas.
O_EXCL En conjonction avec O_CREAT, déclenchera une erreur si
le fichier existe, et open échouera. La solution consiste à créer un fichier
unique sur le même système de fichiers (par exemple avec le pid et le nom de
l'hôte), utiliser link(2) pour créer un lien sur un fichier de verrouillage
et d'utiliser stat(2) sur ce fichier unique pour vérifier si le nombre de
liens a augmenté jusqu'à 2. Ne pas utiliser la valeur de retour de link().
O_NOCTTY
Si pathname correspond à un périphérique de terminal --
voir tty(4) --, il ne deviendra pas le terminal contrôlant le processus même
si celui-ci n'est attaché à aucun autre terminal.
O_TRUNC
Si le fichier existe il sera tronqué.
O_APPEND
Le fichier est ouvert en mode "ajout". Initialement,
et avant chaque write, la tête de lecture/écriture est placée à la fin du
fichier comme avec lseek...
O_NONBLOCK or O_NDELAY
Le fichier est ouvert en mode "non-bloquant". Ni la
fonction open ni aucune autre opération ultérieure sur ce fichier ne
laissera le processus appelant en attente.
O_SYNC Le fichier est ouvert en écriture synchronisée. Chaque
appel à write sur le fichier bloquera le processus appelant jusqu'à ce que
les données aient été écrites physiquement sur le support matériel.(voir la
section RESTRICTIONS dans le man).
Certains de ces attributs optionnels peuvent être modifies par
la suite avec la fonction fcntl.
* La configuration de la liaison :
DESCRIPTION
Les fonctions termios établissent une interface générale sous
forme de terminal, permettant de contrôler les ports de communication
asynchrone.
Plusieurs fonctions décrites (man) utilisent un argument
termios_p qui est un pointeur sur une structure termios.
Cette structure contient les membres suivants :
tcflag_t c_iflag; /* modes d'entrée */
tcflag_t c_oflag; /* modes de sortie */
tcflag_t c_cflag; /* modes de contrôle */
tcflag_t c_lflag; /* modes locaux */
cc_t c_cc[NCCS]; /* caracteres de contrôle */
Les champs de la structure termios
Nous n'allons pas détailler ici l'ensemble des champs de cette structure car
ils sont trop nombreux. Seuls les champs utiles seront abordés.
c_iflag : les modes d'entrée
Ils définissent un traitement à appliquer sur les caractères en
provenance de la liaison série :
IGNBRK : les caractères BREAK sont ignorés.
IGNPAR : les caractères qui comportent une erreur de parité
sont ignorés.
ISTRIP : dans le cas d'une transmission sur 8 bits, le huitième
bit est systématiquement mis à zéro.
c_oflag : les modes de sortie
Ils définissent un traitement à appliquer sur les caractères envoyés
sur la liaison série. On y trouve notamment OLCUC qui transforme les
minuscules (non accentuées !) en majuscules.
c_cflag : Les modes de contrôle
Ce champ est important, car c'est ici que l'on définit le débit, la
parité utilisée, les bits de donnée et de stop, ...
CLOCAL : si ce flag n'est pas utilisé, une déconnexion (ie.
chute du signal DCD) entraîne la fermeture automatique du port série et les
prochains appels à read() renverront la valeur -1. (connexion locale, pas de
controle par le modem)
CRTSCTS : controle de flux materiel (uniquement utilise si le
cable a les lignes necessaires. Voir la section 7 du Serial-HOWTO).
CREAD : permet la reception des caracteres
IGNPAR : ignore les octets ayant une erreur de parite.
ICRNL : transforme CR en NL (sinon un CR de l'autre cote de la
ligne ne terminera pas l'entree). Sinon, utiliser l'entree sans traitement
(device en mode raw).
CS5 : chaque caractère est composé de 5 bits.
CS6 : chaque caractère est composé de 6 bits.
CS7 : chaque caractère est composé de 7 bits.
CS8 : chaque caractère est composé de 8 bits (c'est le cas le
plus fréquent).
CSTOPB : on utilise 2 bits de stop au lieu d'un seul par défaut
(sauf en 5 bits, où on utilise 1,5 bits).
HUPCL (Hang UP on CLose) : provoque la déconnexion (ie. chute
des signaux DTR et RTS) lors de la fermeture du port série par l'appel
système close().
PARENB : activation du mécanisme de parité paire.
PARODD : utilisation d'une parité impaire au lieu d'une parité
paire par défaut.
B50 : liaison à 50 bits/s.
B75 : liaison à 75 bits/s.
...
230400 : liaison à 230400 bits/s.
460800 : liaison à 460800 bits/s.
c_lflag : les modes locaux
Ce champ est d'une importance capitale : il définit le mode (canonique
ou non) et la gestion de l'écho.
ECHO : un écho des caractères reçus est effectué.
ICANON : passage en mode canonique, c'est-à-dire que les
caractèes reçus sont stockés dans un tampon et qu'ils ne sont disponibles
qu'à la réception d'un caractère eol (de code ASCII décimal 10). Les
caractères erase et kill permettent respectivement d'effacer le dernier
caractère et tous les caractères de la ligne courante. En mode non-canonique
(le mode par défaut), tous les caractères sont immédiatement disponibles à la
lecture.
Entree canonique
C'est le mode de fonctionnement normal pour les terminaux, mais peut
egalement etre utilise pour communiquer avec d'autres peripheriques.
Toutes les entrees sont traitees lignes par lignes, ce qui signifie qu'un
read ne renverra qu'une ligne complete. Une ligne est terminee par defaut
avec un caractere NL (ACII LF), une fin de fichier, ou un caractere de fin de
ligne. Un CR (le caractere de fin de ligne par defaut de DOS et Windows) ne
terminera pas une ligne, avec les parametres par defaut.
L'entree canonique peut egalement prendre en charge le caractere erase,
d'effacement de mot, et de reaffichage, la traduction de CR vers NL, etc...
Entree non canonique
L'entree non canonique va prendre en charge un nombre fixe de caractere par
lecture, et autorise l'utilisation d'un compteur de temps pour les
caracteres. Ce mode doit etre utilise si votre application lira toujours un
nombre fixe de caracteres, ou si le peripherique connecte envoit
les caracteres par paquet.
Entree asynchrone
Les deux modes ci-dessus peuvent etre utilises en mode synchrone ou
asynchrone. Le mode synchrone est le mode par defaut, pour lequel un appel a
read sera bloquant, jusqu'a ce que la lecture soit satisfaite.
En mode asynchrone, un appel a read retournera immediatement et lancera un
signal au programme appelant en fin de transfert. Ce signal peut etre recu
par un gestionnaire de signal.
Attente d'entree depuis de multiples sources
Cela ne constitue pas un mode d'entree different, mais peut s'averer etre
utile, si vous prenez en charge des peripheriques multiples. Dans mon
application, je traitais l'entree depuis une socket TCP/IP et depuis une
connexion serie sur un autre ordinateur quasiment en meme temps. L'exemple de
programme donne plus loin attendra des caracteres en entree depuis deux
sources. Si des donnees sur l'une des sources deviennent disponibles, elles
seront traitees, et le programme attendra de nouvelles donnees.
L'approche presentee plus loin semble plutot complexe, mais il est
important que vous vous rappeliez que Linux est un systeme multitache.
L'appel systeme select ne charge pas le processeur lorsqu'il attend des
donnees, alors que le fait de faire une boucle jusqu'a ce que des caracteres
deviennent disponibles ralentirait les autres processus.
c_cc : les caractères de contrôle
C'est un tableau de caractères. Des constantes sont définies pour
accéder à quelques éléments particuliers :
VERASE : en mode canonique, c'est le caractère erase, qui
provoque l'effacement du dernier caractère.
VKILL : en mode canonique, c'est le caractère kill, qui
provoque l'effacement de toute la ligne.
VEOF : en mode canonique, c'est le caractère de fin de fichier
lorsqu'il est utilisé seul sur une ligne. Le prochain appel à read() renverra
une valeur nulle.
VEOL : en mode canonique, c'est le caractère de fin de ligne.
C'est lui qui rend disponibles à la lecture tous les caractères précédents.
VMIN : en mode non-canonique, spécifie le nombre de caractéres
que doit contenir le tampon pour être accessible à la lecture. En général, on
fixe cette valeur à 1.
VTIME : en mode non-canonique, spécifie, en dixièmes de
seconde, le temps au bout duquel un caractère devient accessible, même si le
tampon ne contient pas c_cc[VMIN] caractères. Une valeur de 0 représente un
temps infini.
* Read et Select :
ssize_t read(int fd, void *buffer, size_t n);
Cette fonction lit n octets dans le fichier dont le descripteur est fd et les
place dans un buffer. En cas de réussite, elle renvoie le nombre d'octets
transferés, sinon elle retourne -1.
Multiplexage d'entrées-sorties
NOM
select, FD_CLR, FD_ISSET, FD_SET, FD_ZéRO - Multiplexage
d'entrées/sorties synchrones.
SYNOPSIS
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select(int n, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
FD_CLR(int fd, fd_set *set);
FD_ISSET(int fd, fd_set *set);
FD_SET(int fd, fd_set *set);
FD_ZéRO(fd_set *set);
DESCRIPTION
select attend des changements d'état sur plusieurs descripteurs
de fichiers.
Il y a trois ensembles indépendants de descripteurs qui sont
surveillés simultanement.
Ceux de l'ensemble readfds seront surveillés pour vérifier si
des caracteres deviennent disponibles en lecture.
Les descripteurs de l'ensemble writefds seront surveillés pour
vérifier si l'on peut écrire immédiatement sur eux.
Ceux de l'ensemble exceptfds seront surveillés pour l'occurence
de conditions exceptionnelles.Il en existe deux types : l'arrivée de données
hors-bande sur une socket, et la disponibilite d'informations d'état
concernant un pseudo-terminal en mode paquet.
On peut indiquer un pointeur NULL à la place d'un ensemble si
l'on ne veut pas en tenir compte.
En sortie, les ensembles sont modifiés pour indiquer les
descripteurs qui ont changé de statut.
Quatre macros sont disponibles pour la manipulation des
ensembles :
FD_ZéRO efface un ensemble (initialisation à zéro d'un
ensemble).
FD_SET et FD_CLR : ajoutent et suppriment un descripteur dans
un ensemble.
FD_ISSET verifie si un descripteur est contenu dans un
ensemble, principalement utile après le retour de select.
n est le numero du plus grand descripteur des 3 ensembles, plus
1. En fait, c'est le plus élevé numéro de descripteur d'E/S présent dans l'un
des 3 ensembles de descripteurs (readfds, writefds, exceptfds) timeout est
une limite supérieure au temps passé dans select avant son retour. Elle peut
être nulle, ce qui conduit select à retourner immédiatement.
Si le timeout est NULL (aucun), select peut bloquer indéfiniment.
VALEUR RENVOYÉE
En cas de réussite select renvoie le nombre de descripteurs
dans les ensembles, qui peut être nul si le délai de timeout a expiré avant
que quoi que ce soit d'intéressant ne se produise. select retourne -1 s'il
échoue, auquel cas errno contient le code d'erreur.
Si vous voulez plus de détails sur select faîtes man select.
* Write :
ssize_t write(int fd, const void *buffer, size_t n);
Cette fonction écrit n octets dans le fichier dont le descripteur est fd à
partir d'un buffer. Cette fonction retourne le nombre d'octets écrits ou -1
en cas d'erreur.
Liens internet:
http://charmed.chez.tiscali.fr/howtofr/Serial-Programming-HOWTO.gz
http://www.linuxmag-france.org/vrac/serie.html
http://echo-linux.alienor.fr/articles/ports-series/ports_series.html
http://users.skynet.be/pcamus/isil/rs232.pdf
http://perso.wanadoo.fr/bernard.le.fol/tp_manip_fichiers/node8.html
Vous souhaitez acquerir votre Pack ou des Services MandrakeSoft?
Rendez-vous sur "http://www.mandrakestore.com"
|