Voici quelques indications sur la façon de de commander par programme un port parallèle.
Attention : ce qui suit ne s’applique qu’à la commande des ports natifs, et non au ports réalisés à travers des convertisseurs USB-parallèle.
Ça ne s’applique aussi qu’au mode SPP, et avec les limitations exposées sur la page précédente: pas de relecture des registres A0 et A2, pas d’utilisation des interruptions.
Sommaire
Langage et système d’exploitation
Le langage utilisé doit permettre de manipuler des octets et d’accéder aux adresses d’entrée/sortie : instructions IN et OUT en assembleur, INP et OUT en BASIC, fonction et instruction PORT en Pascal, etc.
Le système d’exploitation doit autoriser cet accès direct, ou bien il faut se procurer le composant logiciel capable de faire le travail: pilote, DLL pour Windows 9x, etc.
Les exemples suivants sont donnés en QuickBASIC sous DOS, et en VisualBASIC sous Windows 95, mais bien évidemment on peut faire la même chose en assembleur, en Pascal ou en C, sous Linux, BeOS ou autre, en utilisant les outils de programmation adaptés.
Détermination de l’adresse du port parallèle
Rappelons qu’un port parallèle de PC utilise trois adresses consécutives A0, A1, A2 de l’espace d’entrée-sortie.
L’adresse de base A0 peut prendre 3 valeurs différentes, suivant le nombre de ports installés, le type de carte supportant le port, les réglages du BIOS et des cavaliers, etc.
Heureusement il existe une méthode simple pour connaître ces adresses: le BIOS ayant fait le travail pour nous, il suffit d’aller lire ces adresses en mémoire, sur 2 octets, à partir de l’adresse hexa 40:0008h.
Exemple en BASIC, pour un PC n’ayant qu’un seul port parallèle: |
DEFINT A-Z ‘toutes les variables sont entières … DEF SEG=&h40 ‘chargement du pointeur de segment A0=PEEK(8)+256*PEEK(9) ‘lecture de la valeur entière sur 2 octets DEF SEG ‘restauration du pointeur de segment A1=A0+1: A2=A1+1 ‘calcul des adresses des 2 autres registres … |
Lorsqu’il y a plusieurs ports parallèles, les adresses sont à la suite à partir de 40:0008h (LPT1, puis LPT2, puis LPT3).
Un exemple de détermination du nombre et de l’adresse des ports, ainsi que du choix d’un port, est donné dans les programme « moniteur de port parallèle », au bas de cette page.
Bits et octets
On ne peut lire et écrire dans les registres que des octets entiers, alors qu’on cherche le plus souvent à manipuler des bits. Il faut donc convertir les valeurs binaires en valeurs décimales ou hexadécimales. Les exemples ci-après sont en décimal.
Commande du registre A0 :
(D7) |
(D6) |
(D5) |
(D4) |
(D3) |
(D2) |
(D1) |
(D0) |
|
0 0 0 0 |
0 0 0 0 |
0 0 0 0 |
0 0 0 0 |
0 0 0 0 |
0 0 0 0 |
0 1 1 1 |
1 0 1 0 |
1 2 3 4 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
255 |
Exemple en BASIC: |
DEFINT A-Z ‘idem … ‘On souhaite mettre D1 et D4 à 1, et les autres fils à 0. ValeurA0=34 ’34 décimal = 00100010 binaire (D1 et D4 à 1) OUT A0, ValeurA0 ‘écriture dans le registre A0 … |
Commande du registre A2 :
Comme précédemment, on peut utiliser la correspondance binaire-décimal classique, limitée aux 16 premières valeurs :
(n.u.) |
(n.u.) |
(n.u.) |
(n.u.) |
(C3-) |
(C2+) |
(C1-) |
(C0-) |
|
0 0 0 0 |
0 0 0 0 |
0 0 0 0 |
0 0 0 0 |
0 0 0 0 |
0 0 0 0 |
0 1 1 1 |
1 0 1 0 |
1 2 3 4 |
0 |
0 |
0 |
0 |
1 |
1 |
1 |
1 |
15 |
Par contre, contrairement à A0, on va avoir besoin de commander les fils indépendamment les uns des autres.
Ceci peut-être fait en suivant deux règles simples :
- mémorisation de l’état du port dans une variable globale
- modification d’un bit dans la variable et ré-écriture de celle-ci dans le registre lors de la commande.
Exemple en BASIC (en BASIC, les opérateurs logiques s’appliquent directement aux variables numériques): |
DEFINT A-Z ‘Toutes les variables sont entières … ‘suite à une commande précédente, l’état du port est mémorisé dans la variable ValeurA2 … … ‘On veut mettre le fil C2+ à l’état 1: Bit=2 ‘rang du bit en commençant à 0 ValeurA2=ValeurA2 OR 2^Bit ‘mise à 1 du bit C2 OUT A2,ValeurA2 ‘écriture de l’octet dans le registre A2 … … ‘On veut mettre le fil C2+ à l’état 0: Bit=2 ‘idem… ValeurA2=ValeurA2 AND NOT 2^Bit ‘mise à 0 du bit C2 OUT A2,ValeurA2 ‘écriture de l’octet dans le registre A2 … … ‘On veut mettre le fil C0- à l’état 0: Bit=0 ‘idem… ValeurA2=ValeurA2 OR 2^Bit ‘mise à 1 du bit, car cette ligne est inversée OUT A2,ValeurA2 ‘écriture de l’octet dans le registre A2 … |
Lecture du registre A1 :
Lorsqu’on a détecté un changement d’état, il faut calculer quel fil(s) a(ont) changé d’état, d’où la nécessité de conserver l’ancien état de chaque bit dans une autre variable (ça n’est pas indispensable, mais c’est plus simple).
(I7-) |
(I6+) |
(I5+) |
(I4+) |
(I3+) |
(n.u.) |
(n.u.) |
(n.u.) |
|
0 0 0 0 |
0 0 0 0 |
0 0 0 0 |
0 0 0 0 |
0 0 0 0 |
0 0 0 0 |
0 1 1 1 |
1 0 1 0 |
1 2 3 4 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
255 |
Exemple en BASIC: |
DEFINT A-Z ‘idem … ‘l’état du registre est dans la variable ValeurA1 ‘l’état de chaque bit est dans le tableau Bit() … Boucle: ‘boucle de scrutation permanente ValeurLue=INP(A1) ‘il est nécessaire de mémoriser la valeur lue IF ValeurLue<> ValeurA1 THEN GOSUB TraitementA1 ‘ici, autres évènements à traiter cycliquement, ‘y compris les conditions de sortie de boucle GOTO Boucle … TraitementA1: ‘traitement du changement d’état du registre FOR I=3 to 7 ‘seuls ces bits nous intéressent IF (ValeurA1 AND 2^I) <> (2^I)*Bit(I)) THEN ‘ce bit a changé d’état IF (ValeurA1 AND 2^I)=0 THEN Bit(I)=0 ELSE Bit(I)=1 GOSUB TraitementBit END IF NEXT ValeurA1=ValeurLue ‘mémorise que le changement d’état a été traité RETURN … TraitementBit: ‘traitement du changement d’état… ‘du bit I qui vient de prendre la valeur Bit(I) ‘traitement souhaité… RETURN … |
Note : ceci n’est qu’un exemple, et il y a de nombreuses autres façons de réaliser ce genre de fonction. Il est notamment souhaitable d’accélérer le programme en évitant les calculs répétés d’expression du style 2^I.
Un moniteur de port parallèle
Voici un petit moniteur écrit en QuickBASIC, qui permet de d’écrire bit à bit sur les ports A0 et A2, et de lire et d’afficher les données présentes sur A1.
Un exemple en VisualBASIC
VisualBASIC étant dépourvu d’instructions d’entrée/sortie physique, il faut faire appel à une DLL fournissant ces fonctions.
On trouve sur Internet un certain nombre de telles DLL, en tant que shareware ou freeware. Parmi ces dernières, nous avons choisi InpOut32, sur l’excellent site de Jan Axelson, que nous vous conseillons absolument de visiter.
Une fois en possession de cette DLL, l’écriture d’un programme simple ne pose guère de problème. Noter toutefois l’usage qui est fait de l’instruction DoEvents pour réaliser une scrutation permanente.
Attention : ce moniteur ne fonctionne pas exactement comme le précédent :
- le contenu des registres de sortie A0 et A2 est préparé bit à bit en mémoire, avant d’être affiché sur le port sur commande de l’utilisateur (alors que dans MONPAR, le registre de sortie est mis à jour au fur et à mesure des modifications)
- le bit de bidirectionnalité (D5 de A2) est traité.
Commentaires : On peut se demander s’il est bien judicieux d’utiliser VisualBASIC pour le contrôle d’un réseau de train électrique ou autre application du même style.
En fait, c’est plus précisément l’utilisation du système d’exploitation Windows pour réaliser une gestion de processus multitâche temps réel, qui est tout à fait discutable, car Windows n’est pas fait pour cela, et son utilisation dans ce contexte pose plusieurs problèmes:
- Perte de performance. Il est vrai que les ordinateurs actuels sont surpuissants. Cependant, si l’on veut utiliser pour son train un vieux PC dédié à cet usage, on aura intérêt à se passer de Windows, soit que celui-ci ralentisse trop l’ordinateur, soit qu’il soit tout bonnement impossible de l’installer sur une machine antédiluvienne.
- Difficulté de réaliser certaines fonctions sans être un programmeur de haut niveau: temps réel pointu, gestion des interruptions, programmation synchrone, etc.
Windows présente par contre d’autres avantages, comme la gestion graphique de l’écran en haute résolution, ou la facilité d’utilisation de la souris.
Programmation sous W7, 9, 64 bits,etc
En attendant la réfection de cette page, vous pouvez nous contacter par mail.
0 commentaires