Programmation du port parallèle
icone embarque
Signature :
GNU/Linux Magazine
Sommaire de l'article :

Retrouvez cet article dans : Linux Magazine Hors série 23

Un port est présent sur la quasi-totalité des PC, et ce, quel que soit son âge. Le port parallèle, initialement créé pour connecter une imprimante, est aussi une des interfaces les plus faciles d’accès. Ceci, autant d’un point de vue matériel que logiciel. Le port parallèle n’est pas une nouveauté. Déjà présent en 1981 sur l’IBM PC, celui-ci était prévu pour piloter les toutes nouvelles imprimantes matricielles et compenser la lenteur du port série de l’époque. Comme son nom l’indique, le port parallèle permet la transmission de 8 bits de données en une seule fois de manière parallèle sur huit lignes spécifiques. En 1991, avec la montée en puissance des ordinateurs et des configurations, le port parallèle IBM commença à montrer ses limites. Une alliance nommée NPA (Network Printing Alliance) se forma, composée de grands fabricants comme Lexmark, IBM, Texas Instruments, etc. Ce groupe travailla à la définition d’un cahier des charges permettant un contrôle parfait des imprimantes et des travaux d’impression. Il s’avéra rapidement qu’un port parallèle bidirectionnel devenait indispensable. La NPA proposa les résultats de ses travaux à l’IEEE (Institute of Electrical and Electronic Engineer). En 1994, ce dernier publia le standard 1284 " Standard Signaling Method for a Bi-directional Parallel Peripheral Interface for Personal Computers ".

Le port

Un port parallèle IEEE 1284 se compose de 17 lignes (broches) de signaux et de 8 lignes connectées à la masse pour former les 25 broches d’un connecteur DB25 femelle à l’arrière d’un PC. A chaque ligne correspond un bit dans un registre donné. Le premier registre est accessible à l’adresse d’entrée/sortie propre à chaque port parallèle. Un certain nombre d’adresses sont standardisées comme 0x378 pour le premier port, mais des cartes additionnelles peuvent utiliser des adresses totalement différentes. Le premier registre est celui contrôlant les lignes de donnée, le deuxième, 8 bits plus loin concerne les lignes d’état et enfin, le troisième, les lignes de contrôle. Il faut clairement distinguer les signaux des registres. C’est une source de confusion importante lorsqu’on travaille avec ce port. Certains signaux sont actifs au niveau haut, ils sont vrais lorsque le signal est au +5 V. D’autres sont actifs au niveau bas, vrais lorsqu’ils sont à la masse. De la même manière, les bits des registres peuvent être à 1 logique en présence de +5 V et d’autres à 1 logique si la ligne est à la masse.

/img-articles/lmhs/23/art-5/fig-1.jpg

Fig. 1 -  Brochage de l’interface parallèle d’un PC (DB25 femelle)

Pour faire la distinction entre des signaux de l’un ou l’autre type, on utilise une barre placée au-dessus du non du signal ou un slash (barre de fraction). Ainsi, /ERROR est un signal actif au niveau bas et BUSY est actif au niveau haut. De manière identique, les registres peuvent être actifs au niveau haut comme S5 (registre d’état, bit 5) ou actif au niveau bas comme /S7 (si le bit est à 1, c’est que la ligne est à la masse). Là où cela devient épineux, c’est dans le fait que cette notion d’activation au niveau haut ou bas est relative à un état (vrai/faux) par rapport à une tension (+5 V/masse). Ainsi, si nous choisissons la ligne 15, le signal est /ERROR. Cela signifie qu’en présence de +5V il n’y a PAS d’erreur. Le bit correspondant (S3) dans le registre d’état (STATUS) est actif au niveau haut, un 1 signifie +5 V sur la broche 15. Cependant si ce bit est à 1, c’est qu’il n’y a PAS d’erreur. On n’écrit pas /S3 car le registre n’est pas actif au niveau bas, 1=+5 V. Le bit n’est pas actif par rapport à la véracité (l’état) du signal, mais par rapport l’état de la ligne (tension). Ajoutons une couche pour être sûr que tout cela soit assimilé. La ligne BUSY (11) est active au niveau haut. S’il y a présence de +5 V c’est que le périphérique est occupé. Le bit /S7 du registre d’état est actif au niveau bas, il sera à 1 si la ligne est à la masse. Il faut procéder par étape. En lecture, il faut lire le bit, en conclure l’état de la ligne (+5 V ou masse) puis en déduire la signification du signal. En écriture, il faut décider du signal, déduire l’état à appliquer à la ligne et choisir la valeur du bit dans le registre. Notre travail ici est simplifié puisque nous ne cherchons pas à développer un périphérique de type imprimante. La signification des signaux n’importe pas vraiment, nous voulons simplement utiliser les entrées et les sorties.

/img-articles/lmhs/23/art-5/tt1.jpg

Les signaux sont divisés en trois groupes.

DATA

Il s’agit là des 8 lignes de données du port parallèle en bleu sur la figure 1. Normalement en sorties, ces lignes peuvent également être lues si le port est en mode bidirectionnel (voir section "Modes du port parallèle"). Dans tous les cas, il est possible de lire à l’adresse d’entrée/sortie du port (0x378 par défaut pour le premier). C’est la pertinence des informations qu’il faut prendre en considération. Avec un port non bidirectionnel, vous lirez la dernière valeur envoyée. Dans le cas contraire, les données lues peuvent être envoyées par le périphérique.

STATUS

Accessibles à l’adresse du port plus 1, ces lignes sont en lecture seule et permettent d’obtenir des informations de la part du périphérique :
  • /ACK (bit 6 – broche 10) : le périphérique met cette ligne à l’état bas brièvement (environ 5 µs) pour indiquer à l’ordinateur qu’il a bien reçu le caractère transmis précédemment. C’est un signal d’accusé de réception.
  • BUSY (bit 7 – broche 11) : actif au niveau haut cette ligne indique un état spécifique du périphérique, celui-ci ne peut plus recevoir de données et les traiter. L’ordinateur doit attendre que le périphérique soit à nouveau disponible.
  • PE (bit 5 – broche 12) : " paper error ", " paper out " ou " paper empty " selon les documentations. Cette ligne indique que l’imprimante n’a plus de papier.
  • ON LINE ou SELECT (bit 4 – broche 13) : cette ligne indique à l’ordinateur que le périphérique est en ligne (" on line ")
  • /ERROR (bit 3 – broche 15) : indique à l’ordinateur que le périphérique est en erreur. Ce signal est actif au niveau bas et le registre au niveau haut. En clair, si à la lecture vous avez un 1 logique, c’est qu’il n’y a PAS d’erreur.

CONTROL

En vert sur le schéma en figure 1, les lignes de contrôle sont au nombre de 4 et permettent le pilotage de l’interface et la négociation avec l’imprimante. Il s’agit de sorties :
  • /STROBE : ce signal indique à l’imprimante que des données sont présentées sur les lignes de données et qu’elle doit les prendre en compte. Ce signal, comme les suivants, est actif au niveau bas (donc préfixé d’un slash). Ceci signifie que lorsqu’on veut signaler à l’imprimante la présence de données, on passe brièvement (moins de 0.5 µS) le signal à la masse avant de revenir au +5 V.
  • /AUTOFEED : ce signal demande à l’imprimante de faire automatiquement un saut de ligne. A l’époque des imprimantes matricielles, certaines configurations d’imprimante ne faisaient pas de " retour, à la ligne " (CR/LF), mais un simple retour de la tête d’impression en début de ligne (CR). Il fallait donc logiciellement avancer le papier d’une ligne (LF) de manière automatique si les données ne contenaient qu’un retour chariot.
  • /SELECT IN : ce signal permet une sélection d’imprimante. Tout comme avec certains composants que nous verrons plus loin dans ce hors-série, cette ligne active au niveau bas permet de signaler au périphérique qu’il est sélectionné et que les ordres émis le concernent.
  • /INIT : via ce signal, l’ordinateur peut demander une réinitialisation de l’imprimante. Là encore le signal est actif au niveau bas, ce qui signifie qu’il faut mettre la ligne à la masse pour réinitialiser l’imprimante.

Modes du port parallèle

Pour l’heure, nous n’avons parlé que d’un seul mode du port parallèle : SPP pour Standard Parallel Port. Dans ce mode également appelé " Printer Mode ", les lignes de données du port ne peuvent être utilisées qu’en mode unidirectionnel. Le mode SPP peut également, selon l’interface, être utilisé de manière bidirectionnelle.  On utilise le bit 5 du registre des lignes CONTROL pour inverser le mode de fonctionnement des huit lignes de données. En plaçant ce bit à 1, on peut lire les lignes DATA comme valeurs d’entrées et non plus comme dernières valeurs envoyées (latchs). Si le port n’est pas en mesure de travailler de manière bidirectionnelle, l’écriture du bit 5 n’aura aucun effet. SPP/EPP1.7/EPP1.9, parfois noté simplement EPP dans l’écran de configuration du BIOS est le mode le plus intéressant pour une machine moderne. EPP, Enhanced Parallel Port, est le résultat d’un rapprochement des sociétés Intel et Xircom & Zenith Data Systems.  Le mode EPP présente l’intérêt de pouvoir continuer à travailler comme avec le mode SPP. Les registres SPP sont utilisables comme expliqué plus haut (base, base+1 et base+2) en tenant compte du fait que le bit 5 du registre CONTROLE permet d’inverser le sens écriture/lecture pour les lignes de données. Deux adresses supplémentaires, base+3 et base+4, donnent respectivement accès aux registres des ports d’adresses EPP et de données EPP. Un port parallèle en EPP peut donc être librement utilisé selon les besoins.  La différence entre les versions 1.7 et 1.9 du mode EPP réside principalement dans l’absence du bit de timeout. Dans tous les cas, on préfèrera le standard le plus récent possible à moins d’avoir une bonne raison de choisir 1.7 (compatibilité avec un périphérique). Enfin, nous avons le mode ECP pour Extended Capabilities Port développé par Hewlett Packard et Microsoft. Ce mode est également compatible SPP et utilise des registres de configuration supplémentaires comme EPP : Base+0x400 pour les données en FIFO en mode FIFO ou configuration. A en mode configuration, Base+0x401 pour le registre de configuration B en mode configuration et Base+0x402 pour le registre ECR (Extended Control Register) dans tous les modes. Le mode ECP présente quelques caractéristiques majeures dont l’utilisation d’un canal DMA et un tampon FIFO pour les données. Cependant, ces éléments ne sont intéressants qu’en cas de débit important (périphérique bloc sur port parallèle) et sont largement compensés par une certaine difficulté d’utilisation. On notera que la grande majorité des BIOS permettent de configurer le port parallèle intégré à la carte mère en mode multiple. Ainsi, vous pouvez choisir ECP/EPP1.9 pour cumuler tous les avantages : port bidirectionnel SPP, registres du mode EPP base+3 et base+4, registre et mode de configuration ECP/ECR.

Support Linux

Le noyau Linux prend en charge parfaitement les ports parallèles de tout type et dans tous les modes. Depuis la version 2.4 du noyau, le support de cette interface est devenu très hiérarchisé. Nous avons d’un coté le support spécifique à chaque plate-forme dont le plus utilisé est partport_pc. Au-dessus de ce pilote se place le support parport permettant d’unifier les méthodes d’accès au port sous la forme d’une API unique. Nous y reviendrons par la suite, mais la réorganisation du support parport du noyau 2.4 a également été l’occasion d’introduire ppdev. Tout comme le support lp (line printer) permet le dialogue avec une imprimante depuis l’espace utilisateur, ppdev permet le contrôle de chaque ligne du port. Notez la nette différente entre lp et ppdev. Le second offre un accès au port parallèle IEEE 1284 alors que le premier fournit une méthode pour imprimer. echo "coucou" > /dev/lp0 imprimera la chaîne de caractères sur le périphérique.  Rien d’équivalent n’est possible avec /dev/parport0 avec ppdev. Ceci pose problème, non pas avec les ports parallèles intégrés aux cartes mères ou vendus sous forme de cartes additionnelles PCI ou ISA, mais avec les adaptateurs USB. Ceux-ci sont supportés par le pilote usblp (noyau 2.6) ou printer (noyau 2.4). Ceux-ci ne fournissent pas une couche de bas niveau pour parport comme c’est le cas pour parport_pc, parport_cs ou parport_gsc, mais un support pour /dev/lp. De ce fait, l’utilisation de ppdev n’est pas possible car les adaptateurs USB concernés sont normalement dédiés aux connexions avec les imprimantes ou directement intégrés à celles-ci (imprimantes USB). La question de savoir s’il fallait ou non intégrer le support usblp comme un élément de parport a déjà fait l’objet de discussions sur la LKML et la réponse était toujours la même : les adaptateurs USB/imprimante sont pris en charge comme des canaux pour l’impression, non comme des convertisseurs USB/Parallèle (comme uss720) ou un nouveau port parallèle. Dans tous les cas, vous pourrez constater que le support de votre port parallèle est correctement pris en charge par le noyau en inspectant les journaux d’activité (/var/log/kern.log) :
parport: PnPBIOS parport detected.
parport0: PC-style at 0x378 (0x778), irq 7, dma 3
  [PCSPP,TRISTATE,COMPAT,EPP,ECP,DMA]
Le noyau 2.6 est quelque peu plus bavard que le 2.4, puisqu’il informe des différents modes supportés par l’interface, mais aussi des IRQ et DMA utilisés (selon le mode) et des adresses utiles. Vous retrouverez une partie de ces informations dans /proc dans les fichiers dma, interrupts et ioports.

Etat du port au démarrage de la machine

Aucune documentation officielle ni standard ne définit clairement l’état des lignes du port parallèle au démarrage d’un PC. Pire encore, durant le processus de démarrage entre l’initialisation par le BIOS, le chargement puis l’exécution du noyau et le lancement des différents services, les différentes lignes du port parallèle changent d’état. Pour cette raison, le périphérique doit réagir ou plutôt ne pas réagir en conséquence. Il était de coutume, fut un temps, de n’allumer l’imprimante qu’après le démarrage complet du système. On retrouve encore ce type de recommandation dans certaines documentations constructeur.  J’ai cependant constaté sur bon nombre de machines que la ligne /STROBE restait, de la mise sous tension à l’utilisation par un outil logiciel, à l’état haut (+5 V). Ceci paraît parfaitement logique étant donné la fonction du signal. Toutefois, il ne s’agit là que d’une constatation empirique.  Prenez garde, lors de la conception d’un nouveau montage connecté à ce port de ne pas le laisser agir/réagir avant une étape où vous avez entièrement le contrôle. Bien entendu, lorsqu’il s’agit du module LCD ou d’afficheurs lumineux, ceci n’est en rien critique. Il n’en va pas de même avec une carte à relais ou un triac pilotant des équipements importants (éclairage, moteur, etc.).

Programmation : les mauvaises solutions

L’accès et la programmation de l’interface parallèle sous Linux est un vaste domaine qui pourrait couvrir la totalité de ce magazine. Nous ne traiterons ici que les cas les plus courants. Il existe plusieurs manières de piloter les lignes du port parallèle. Nous allons les voir de la plus mauvaise à la plus convenable.

La méthode sauvage

Des lecteurs ayant déjà développé des applications sous MS/DOS sauront qu’il n’est pas difficile de piloter directement le port parallèle sans l’assistance du système. En mode SPP, les adresses du port sont connues. Habituellement 0x378 est l’adresse d’entrée/sortie de base du premier port parallèle (LPT1). Avec les anciennes versions du noyau Linux, accéder directement au port via cette adresse était la seule manière de le contrôler. Aujourd’hui, il s’agit tout simplement de la technique la plus " sale ". On utilisera les fonctions de bas niveau outb et inb pour écrire et lire directement dans les registres :
 #include<unistd.h>
#include<stdio.h>
#include <asm/io.h>
#define BASEPORT 0x378
int main(int argc, char **argv)
{
	if(ioperm(BASEPORT,3,1)) {
		perror("ioperm");
		exit(1);
	}
	outb(11,BASEPORT);
	printf("lu : %X\n", inb(BASEPORT+1));
	return(0);
}
Je vous ai prévenu, c’est moche. On utilise la fonction ioperm pour positionner les autorisations d’entrée/sortie sur les ports à commencer par 0x378 et ce sur 3 octets. L’utilisation de cette fonction nécessite les privilèges super-utilisateur. Le binaire doit donc être exécuté par ce dernier ou être SUID root avec tous les risques que cela comporte. Cette méthode d’accès n’est présentée ici qu’à titre indicatif. Ne l’utilisez pas. Vous court-circuitez tous les mécanismes de protection et de gestion du noyau et risquez de perturber gravement le fonctionnement du système en cas d’erreur. Il existe des méthodes plus élégantes, plus pratiques et surtout plus " propres ".

/dev/port

Sous GNU/Linux, il existe une méthode alternative permettant d’accéder aux ports d’entrée/sortie. Il suffit, en effet, d’utiliser /dev/port. Ce pseudo fichier est un mappage mémoire des adresses d’E/S. Pour écrire dans le registre en 0x378, il suffit de positionner le pointeur dans le fichier à cette adresse et d’écrire ou lire l’octet. Les problèmes posés sont globalement les mêmes que précédemment à la différence que des permissions spécifiques sur /dev/port règleront le problème de l’identité de l’utilisateur exécutant le binaire. On notera que l’utilisation de ce pseudo fichier permet de développement avec un langage comme Python ou Perl :
#!/usr/bin/perl -w
use Fcntl;

$BASE=888;

sysopen(PORT, “/dev/port”, O_WRONLY)
  or die “Impossible d’ouvrir le fichier : $!\n”;
binmode(PORT);

sysseek(PORT, $BASE,0)
  or die “Probleme seek : $!\n”;

syswrite(PORT, chr(1) )
  or die “Probleme syswrite : $!\n”;

Close PORT
  or die “Probleme close : $!\n”;
Comme précédemment, ces exemples ne sont qu’indicatifs. Il existe une méthode bien moins dangereuse et applicable aussi bien à du code C que Perl.

ppdev : programmation propre du port

Voici la méthode " normale " pour une application devant accéder aux lignes du port parallèle. L’accès depuis l’espace utilisateur se fait selon deux techniques en fonction des besoins. Si votre application doit envoyer des données à une imprimante, cela se fera via le protocole " imprimante " et /dev/lp0. Pour chaque octet envoyé, les lignes de données sont initialisées, /STROBE signale la mise à disposition et l’imprimante accuse réception avec la ligne /ACK. Une application de ce type pourrait tenir en un simple echo coucou > /dev/lp0. Ceci n’est pas l’objet du présent article. Le pilote ppdev permet d’agir avec la même automatisation et sécurité avec davantage de finesse quant au contrôle de chaque ligne du port. Pour ce faire, on utilisera l’appel ioctl sur l’entrée correspondant au port dans /dev. La syntaxe d’ioctl utilise trois arguments : un descripteur de fichier, une commande et, éventuellement, un pointeur vers les données à utiliser. Avant toute opération sur le port via ppdev, nous devons ouvrir le pseudo-fichier correspondant en lecture/écriture selon une technique tout à fait classique :
#include <sys/ioctl.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/errno.h>
#include <linux/ppdev.h>
#include <linux/parport.h>
int errno, fd;
if ((fd = open("/dev/parport0", O_RDWR)) < 0) {
  fprintf(stderr,"Open Error : %s (%d)\n",
	strerror(errno),errno);
  exit(EXIT_FAILURE);
}
Dès le descripteur de fichier obtenu, il est nécessaire de demander l’accès au port. Celui-ci peut être refusé par le système car une autre application ou un module noyau en a obtenu l’accès exclusif. On a généralement le problème lorsque lp est chargé. Il conviendra alors de retirer le module. Notez que l’accès au port n’est pas nécessaire pour toutes les opérations. Certaines commandes ne concernent que l’accès à ppdev et non au port lui-même. Ces dernières n’ont pas besoin de réclamer l’accès.
 if (ioctl(fd, PPCLAIM) < 0) {
  fprintf(stderr,"PPCLAIM ioctl Error : %s (%d)\n",
	strerror(errno),errno);
  exit(EXIT_FAILURE);
}
Si cette commande réussit, on peut manipuler les lignes à loisir puis, au terme de la procédure, on rend la main et on referme de fichier :
 if (ioctl(fd, PPRELEASE) < 0) {
  fprintf(stderr,"PPRELEASE ioctl Error : %s (%d)\n",
	strerror(errno),errno);
  exit(EXIT_FAILURE);
}

if(close(fd) < 0) {
  fprintf(stderr,"Close Error : %s (%d)\n",
  	strerror(errno),errno);
  exit(EXIT_FAILURE);
}
La commande PPEXCL utilisée avant PPCLAIM demandera un accès exclusif au port. Tout autre accès sera refusé jusqu’au moment où nous utiliserons PPRELEASE. L’accès exclusif ne sera obtenu au moment de l’utilisation de PPCLAIM.

Écriture des données

Une fois l’accès au port obtenu, l’action la plus courante est d’écrire sur les lignes de données.  On utilise la commande PPWDATA avec, en argument, un pointeur vers les données à écrire :
unsigned char valout=0x01;

if (ioctl (fd, PPWDATA, &valout) < 0) {
  fprintf(stderr,"PPWDATA ioctl Error : %s (%d)\n",
  	strerror(errno),errno);
  exit(EXIT_FAILURE);
}
Le port parallèle n’est pas en mesure de fournir suffisamment de courant pour toutes les applications. Vous pouvez parfaitement connecter une LED sur chaque ligne de données via une résistance de 470 Ohms et contrôler leur allumage via ce type de code.  Cela n’ira pas plus loin. Les lignes du port parallèle sont conçues pour véhiculer des signaux et vous pourrez y connecter toutes sortes de circuits logiques.  Mais s’il vous faut piloter des composants nécessitant beaucoup de courant, l’utilisation de transistors en saturation ou d’optocoupleurs est indispensable.

Lecture des données

Cela a été dit plus haut, les lignes de données peuvent fonctionner de manière bidirectionnelle. Techniquement, c’est le bit 5 du registre des lignes CONTROL qui permet de passer les lignes de données en entrée.  Avec ppdev, il n’est pas permis de définir ce bit depuis votre code. Il faut utiliser la commande PPDATADIR. Celle-ci n’influencera que le comportement des commandes PPWDATA que nous venons de voir et de PPRDATA. Il faut absolument éviter que le périphérique contrôle les lignes alors que le port est en sortie. Il y a un risque majeur d’endommager le port et/ou le périphérique.  En effet, si les lignes de données sont en sortie et à 0 (à la masse) et que le périphérique en passe une à 1 (+5 V) un court-circuit se produit et une partie des circuits logiques du port parallèle peut être détruit. Attention: Tenir compte du fonctionnement interne du port parallèle est ici capital. Lorsque les lignes de données du port sont en entrée, le périphérique peut contrôler l’état des lignes.

/img-articles/lmhs/23/art-5/fig-2.jpg

Fig. 2 - Exemple théorique du fonctionnement interne du mode bidirectionnel des lignes de données du port parallèle. Le bit 5 du registre CONTROL désactive le latch et permet au périphérique de contrôler les lignes dont nous lisons l’état dans le buffer. Si le périphérique impose un +5 V sur une ligne alors que le latch est activé un risque de court-circuit existe.

Il est important de négocier avec votre périphérique ou votre montage le moment où celui-ci pourra émettre des données et donc contrôler les lignes. Vous pouvez utiliser les lignes CONTROL et STATUS qui sont unidirectionnelles pour cette négociation.  La quasi-totalité des ports parallèles disposent, en entrée sur les lignes de données, de résistances de pull-up (rappel au +5 V). Il s’agit de résistances qui ramènent la ligne au +5 V de manière à obtenir un 1 logique en l’absence de connexion.
 unsigned char valin;
int dirin=1;
int dirout=0;

if (ioctl (fd, PPDATADIR, &dirin)  < 0) {
  fprintf(stderr,"PPDATADIR ioctl Error : %s (%d)\n",
  	strerror(errno),errno);
  exit(EXIT_FAILURE);
}

if (ioctl (fd, PPRDATA, &valin) < 0) {
  fprintf(stderr,"PPRDATA ioctl Error : %s (%d)\n",
  	strerror(errno),errno);
  exit(EXIT_FAILURE);
}
Si on applique un signal haut (+5 V), rien ne change et si on met la ligne à la masse, on obtient un 0 logique. Dans tous les cas, l’état d’une ligne n’est donc jamais indéfini. Toutes les documentations consultées sont d’accord sur un point : aucun fabricant ne semble suivre une ligne directrice unique et il devient nécessaire de tester avant toute connexion et configuration.  Placez les lignes en entrée et lisez avec PPRDATA. Écrivez une valeur quelconque et relisez. La valeur lue ne doit pas être celle précédemment écrite si les lignes sont effectivement configurées en entrée. A ce moment, vous pouvez partir du principe que le PC ne contrôle plus les lignes et vous pouvez relier l’une d’elle à la masse avant de lire à nouveau avec PPRDATA. Là, vous devez voir changer le bit correspondant dans le registre. Si votre groupe de ligne ne dispose pas en interne de résistances de pull-up, vous pouvez les ajouter à l’extérieur (voir la partie concernant les lignes STATUS ci-après).

Lecture de l’état

Pour lire le registre d’état et donc l’état des lignes 10, 11, 12, 13 et 15, il suffit d’utiliser la commande PPRSTATUS : Plutôt que d’analyser les bits de l’octet nous-mêmes, nous pouvons utiliser les pseudo-constantes définies dans linux/parport.h : PARPORT_STATUS_ERROR, PARPORT_STATUS_SELECT, PARPORT_STATUS_PAPEROUT, PARPORT_STATUS_ACK et PARPORT_STATUS_BUSY.
unsigned char status;

if (ioctl (fd, PPRSTATUS, &status) < 0) {
	fprintf(stderr,"PPRSTATUS ioctl Error : %s (%d)\n",
		strerror(errno),errno);
	exit(EXIT_FAILURE);
} else {
	if (status & PARPORT_STATUS_ERROR) {
		printf(“Pas d’erreur (1)\n”);
	} else {
		printf(“Erreur (0)\n”);
	}
}
Normalement, tout comme avec les lignes de données, des résistances de pull-up internes au port permettent un rappel au +5 V. Cependant, comme il n’est pas garanti que ce fait soit établi sur toutes les machines, on utilisera un montage comme celui présenté en figure 3.

/img-articles/lmhs/23/art-5/fig-3.jpg

Fig .3

Les résistances de 4.7 K Ohms forcent l’état haut en l’absence de pression sur les boutons poussoirs. Lorsqu’on établit la connexion, on force la ligne à la masse et la résistance limite le courant selon la formule U=R.I, soit 5=4700*I, soit 5/4700=1mA... négligeable. Bien entendu, des résistances plus importantes (10 K Ohms) feront également l’affaire. Le schéma présenté est complètement théorique. Il présente des boutons poussoirs ayant ce qu’il est courant d’appeler " la maladie des rebonds ". A l’échelle du PC, le contact du bouton n’est pas franc, mais entrecoupé à cause de raisons mécaniques évidentes. Un autre article présente une solution à ce type de problème. D’autre part, la liaison avec un circuit logique (TTL/CMOS) ne pose pas de problème et les résistances de pull-up deviennent inutiles.

Écriture des lignes de contrôle

Si les huit lignes de sortie ne sont pas suffisantes pour votre application, vous pouvez également " piocher " dans les quatre lignes du groupe CONTROL. La commande PPWCONTROL permettra l’écriture dans le registre correspondant. Cependant, comme ces lignes sont souvent utilisées individuellement, l’API ppdev offre une commande plus intéressante : PPFCONTROL. Celle-ci permet d’éviter de lire le registre avec PPRCONTROL, faire le changement dans la valeur obtenue et réécrire le tout. PPFCONTROL le fait en un seul mouvement, il suffit de lui passer en argument un pointeur sur une structure de type ppdev_frob_struct :
struct ppdev_frob_struct {
  unsigned char mask;
  unsigned char val;
}
Si nous souhaitons changer l’état de la ligne STROBE, il nous suffit alors de faire ceci : Ici, nous passons la ligne STROBE à 1 logique (état bas sur la ligne). frob.mask et frob.val sont utilisés en interne via un OU logique et la valeur obtenue utilisée avec un ET logique sur l’ancienne valeur du registre. Les pseudo-constantes à notre disposition sont : PARPORT_CONTROL_STROBE, PARPORT_CONTROL_AUTOFD, PARPORT_CONTROL_INIT et PARPORT_CONTROL_SELECT.

Conclusion

Nous venons de voir le principe de fonctionnement de base du port parallèle et la méthode d’usage pour l’accès depuis un code utilisateur sous GNU/Linux. Il reste un certain nombre de choses à explorer parmi lesquelles le développement d’un code noyau pilotant un montage sur ce port et la gestion des interruptions dans un code utilisateur. Ces deux sujets seront traités par ailleurs dans le présent hors-série dans le cadre d’une mise en pratique. Si vous voulez en apprendre davantage sur le port parallèle, son fonctionnement et sa programmation, référez-vous aux liens ci-dessous. Liens

Retrouvez cet article dans : Linux Magazine Hors série 23

Brèves
Édito : Linux Pratique Essentiel N°24
Édito : Linux Pratique HS N°23
Édito : GNU/Linux Magazine 146
Édito : GNU/Linux Magazine HS N°58
Édito : Open Silicium N°5
Communication
Linux Pratique HS 23 – Communiqué de presse
Linux Pratique Essentiel N°24 – Communiqué de presse
Gnu/Linux Magazine sponsor et partenaire de PROLOGIN
Linux Essentiel partenaire des Rencontres du Libre de Lion sur Mer (Normandie)
GNU/Linux Magazine HS 58 – Communiqué de presse
prochainement moteur de recherches des articles
 
:
:
Jours heures minutes secondes
En kiosque
Le tout nouveau Linux Pratique Essentiel est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau Linux Pratique est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau GNU/Linux Magazine est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau GNU/Linux Magazine HS est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau Open Silicium est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau Linux Pratique est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau Misc est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Le tout nouveau GNU/Linux Magazine est disponible dès maintenant chez votre marchand de journaux et sur notre site...

Lire la suite...

Voir le(s) commentaire(s)

  1. 20/02/2011 :

    Bonjour. Cet article est génial : c’es juste ce que je cherche. Cependant j’ai une question à propos des adaptateurs usb/parallèle : sont-ils reconnu comme étant un port parallèle ou un port usb par le système linux?
    Merci à tous ceux qui me répondrons.

  2. 28/09/2008 :

    Bonjour,

    les ports parallèles sont de moins en moins présents sur nos PC (surtout sur les portables !). Précisons qu’il existe des convertisseurs USB-Parallèle qui permettent de résoudre le problème. Pour les plus curieux ces convertisseurs utilisent souvent un chipset Prolific PL 2305. http://www.prolific.com.tw/eng/Download-2.asp?ID=17
    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 »
    D’autres références de chipsets permettant la convertion USB/Parallele 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 « parallel ».

    Vous pouvez aussi acheter directement une carte d’acquisition à faible coût (à base de microcontroleur) pour laquelle des drivers Linux existent. Cela vous permettra outre d’avoir des entrées/sorties numériques, de disposer pour un coût modeste également d’entrées/sorties analogiques : citons par exemple Labjack U12 http://www.labjack.com/labjack_u12.php ou en totalement libre Arduino http://www.arduino.cc
    (la bande passante de tels dispositifs est loin d’être au top de la technologie mais pour du contrôle de procédés lents c’est souvent suffisant.

    Cordialement

Laissez une réponse

Vous devez avoir ouvert une session pour écrire un commentaire.