zurück

Die Parallele Schnittstelle

Worum geht es hier eigentlich?

Hier geht es darum, ohne großen Aufwand selbstgebaute Hardware über den PC zu Steuern. Dazu wird eine Parallele Schnittstelle verwendet. Diese wird angesprochen durch direkten Zugriff auf die Adressregister dieser. Da bei dieser Variante das Betriebssystem umgangen wird gestaltet sich der Zugriff unterschiedlich schwierig. Unter DOS ist das kein Problem, unter WINDOWS 9x sind nicht in jeder Programmiersprache Befehle dafür vorgesehen (macht aber nichts), indessen ist der Zugriff unter Verwendung spezieller dll's auch unter NT-Systemen möglich. Auch unter Linux lässt sich der direkte Zugriff Freischalten.

Die Anschlüsse:

Pin Signal Name Typ Beschreibung
01 STR Strobe Steuerregister LOW-Pegel überträgt Daten zum Drucker
02 D0 Datenbit 0 Datenbit Datenbit 0
03 D1 Datenbit 1 Datenbit Datenbit 1
04 D2 Datenbit 2 Datenbit Datenbit 2
05 D3 Datenbit 3 Datenbit Datenbit 3
06 D4 Datenbit 4 Datenbit Datenbit 4
07 D5 Datenbit 5 Datenbit Datenbit 5
08 D6 Datenbit 6 Datenbit Datenbit 6
09 D7 Datenbit 7 Datenbit Datenbit 7
10 ACK Acknowledge Statusregister LOW-Pegel zeigt an, Drucker hat Zeichen empfangen und ist bereit für das nächste
11 BSY belegt (busy) Statusregister HIGH-Pegel zeigt an, Drucker belegt, off-line oder Fehler
12 PAP Papier Statusregister HIGH-Pegel zeigt Papierende an
13 ONOF on-line/off-line Statusregister HIGH-Pegel zeigt, Drucker ist on-line
14 ALF Auto-Line-Feed Steuerregister LOW-Pegel zeigt, Drucker führt automatischen Zeilenvorschub aus
15 FEH Druckerfehler Statusregister LOW-Pegel zeigt, Papierende, Drucker off-line oder Druckerfehler
16 INI Druckerinitialisierung Steuerregister LOW-Pegel, Drucker wird Initialisiert
17 DSL Drucker-Select Steuerregister LOW-Pegel, Drucker ist ausgewählt
18 Masse Masse Masse Masse 0V
19 Masse Masse Masse Masse 0V
20 Masse Masse Masse Masse 0V
21 Masse Masse Masse Masse 0V
22 Masse Masse Masse Masse 0V
23 Masse Masse Masse Masse 0V
24 Masse Masse Masse Masse 0V
25 Masse Masse Masse Masse 0V

Die Beschaltung:

Die Parallele Schnittstelle ist Kompatibel zu TTL-Logik in Open-Collektor Ausführung. Das heisst, die Anschlüsse liegen über einen Wiederstand an +5V und werden je nach Datenrichtung entweder vom PC oder durch das externe Gerät bei LOW-Pegel auf 0V gezogen. Hier ein Schema des Ausgangstreibers im PC.

Niemals einen Anschluss der Schnittstelle ohne Vorwiederstand mit +5V verbinden, da ein LOW-Pegel als Ausgangssignal dann zum Kurzschluss führt und die Schnittstelle zerstört. Bei der Verwendung von Schaltkreisen zur Dateneingabe in den PC darauf achten, dass es sich um Open-Collektor-Schaltkreise handelt.

Die Programmierung:

Falls Windows verwendet wird darf die Schnittstelle nicht von anderen Geräten benutzt werden. Da neuere Druckertreiber immer wieder mal prüfen ob der Drucker eingeschaltet ist und welcher Status ... muss der Druckertreiber deinstalliert oder auf eine andere Schnittstelle verlegt werden (LPT2, File ...).

Der Einfachheit halber verwende ich QuickBasic zur demonstration. QuickBasic ist bestandteil von MS-Dos, bei Win98 befindet es sich auf der CD "\\tools\oldmsdos\qbasic.exe".
- der Befehl "out" dient zum schreiben in ein Adressregister
- der Befehl "inp" dient zum lesen aus einem Adressregister
- "&" vor einer Zahl kennzeichnet diese als Hexadezimalzahl
Zum Probieren eingnet sich das Direktfenster von QuickBasic ganz gut.

Die Hardwareadressen:

Die Adressen der parallelen Schnittstellen können 3BC, 378, 278 oder 2BC (hexadecimal) sein. Die Adressen werden bei Steckkarten meist über Jumper eingestellt. Ist die Schnittstelle auf dem Board dann befindet sich die Einstellung meist im BIOS und wird beim Rechnerstart angezeigt.
Unter Windows stehts auch im Gerätemanger.
Normalerweise hat die LPT1 die Adresse 378h (h für Hex), welche ich hier verwenden werde.

Das Datenregister: Adresse = 378h, Offset = 00h, macht 378h. (Bidirektional)

Bit: 7 6 5 4 3 2 1 0
Signal: D7 D6 D5 D4 D3 D2 D1 D0
Pin: 9 8 7 6 5 4 3 2


Das Statusregister: Adresse = 378h, Offset = 01h, macht 379h. (Nur Eingabe)

Bit: 7 6 5 4 3 2 1 0
Signal: BSY ACK PAP ONOF FEH x x x
Pin: 11 10 12 13 15 - - -


Das Steuerregister: Adresse = 378h, Offset = 02h, macht 37Ah. (Bidirektional)

Bit: 7 6 5 4 3 2 1 0
Signal: x x SE/EM IRQ DSL INI ALF STR
Pin: - - - - 17 16 14 1


Die Datenbits:

Die Datenbits können zum einlesen und zum ausgeben verwendet werden. Es können aber immer nur alle Datenbits gleichzeitig zum einlesen oder zum ausgeben verwendet werden.

Datenbits ausgeben:

out &h378,&h1 (Datenbit 0 wird eingeschalten, alle anderen aus (&h1 = 0000 0001))
out &h378,&h2 (Datenbit 1 wird eingeschalten, alle anderen aus (&h2 = 0000 0010))
out &h378,&hff (alle Datenbits werden eingeschalten (&hff = 1111 1111))
out &h378,&h0 (alle Datenbits werden ausgeschalten (&hff = 0000 0000))

Datenbits einlesen:

Da Ursprünglich die Parallele Schnittstelle nur Daten zum Drucker sendete und lediglich ein paar Zustände wie Drucker bereit, fertig... zurück bekahm ist die Standart-Schnittstelle nicht zum einlesen von Daten geeignet. Dies Betrift aber nur noch ältere Schnittstellen. Eigentlich sollten jetzt alle Parallelen Schnittstellen Bidirektional sein und können je nach Modus bis zu 2MByte/s an Daten übertragen.

Um Daten einzulesen muß die Schnittstelle auf Einlesen umgeschalten werden. Dazu wird Bit "5" (Signal "SE/EM") im Adressregister "2" auf "1" gesetzt, ohne die anderen Bits zu ändern. Und das sieht so aus:
out &h37A,( inp(&h37A) or &h20)
"inp(&h37A)" fragt den Inhalt der Adresse 37Ah (378h + 02h) ab.
Durch die ODER Verknüpfung ergiebt sich Bit "5" = "1" (xxxx xxxx OR 0010 0000 = xx1x xxxx).
Mit "out &h37A" wird das Ergebnis an die Adresse37Ah (378h + 02h) geschrieben.

Mit der Umschaltung auf Einlesen schaltet die Schnittstelle alle Datenbits auf HIGH. Ansonsten würden die eigenen Ausgaben eingelesen. Jetzt können die Datenbits abgefragt werden.
print inp(&h378) zeigt den Inhalt des Datenregisters auf dem Bildschirm an. Ist die Schnittstelle nicht belegt muß "255" (dezimal 255 = binär 1111 1111) angezeigt werden. Oder
a = inp(&h378) speichert den Inhalt des Datenregisters in der Variablen "a".

Um die Schnittstelle wieder auf Ausgabe zu schalten muß Bit "5" (Signal "SE/EM") im Adressregister "2" auf "0" gesetzt werden. Das geht so:
out &h37A,( inp(&h37A) and &hDF)
Diesmal wird der Inhalt des Steuerregisters mit "DFh" UND Verknüpft, denn (xxxx xxxx AND 1101 1111 = xx0x xxxx). Damit steht an den Datenleitungen wieder die letzte Ausgabe an.

Sollte es nicht möglich sein Daten Einzulesen, (Schnittstelle ist Bidirektional) dann sollte mal versucht werden, für die Schnittstelle einen Modus einzustellen der nicht "ECP" heißt. (Normal, Bidirektional, SPP, SPP/EPP, EPP aber nicht ECP oder ECP/EPP) Ich habe da mal bei einer älteren Schnittstelle Probleme gehabt und damit beseitigt. Normalerweise ist es aber für die Datenbits egal.

Die Statusregister:

Die Statusregister kann man nur zum einlesen verwenden. Dabei ist es egal, ob die Datenbits gerade zur Eingabe oder zur Ausgabe dienen.

Statusbits einlesen:

print inp(&h379) zeigt den Inhalt des Statusregisters auf dem Bildschirm an. Dabei ist zu beachten, dass das Statusregister zwar aus 8Bits besteht, davon aber nur 5Bits Statusbits sind. Ausserdem giebt es Statusbits, welche zum Hardwareanschluss negiert sind. Das heisst, wenn der Eingang auf High-Pegel ist zeigen diese Statusbits "0" statt "1" an.
a = inp(&h379) speichert den Inhalt des Statusregisters in der Variablen "a".

Auflösen der Statusbits:

FEH Pin:15

Das Statusbit "FEH" liefert TRUE zurück wenn der Eingang auf High-Pegel liegt und FALSE wenn der Eingang auf Low-Pegel liegt.
Unter QuickBasic ist dabei zu beachten:
TRUE = WAR = -1 und nicht wie in anderen Programmiersprachen = 1.
FALSE = Falsch = 0
print (&h8 = (&h8 and inp(&h379)))
Zuerst wird mit inp(&h379) das Statusregister abgefragt. Danach werden mit dem "and" Vergleich alle Bits ausser Bit 5 ausgeblendet. Mit &h8 = wird dann noch auf TRUE oder FALSE geprüft.

OFON Pin:13

Das Statusbit "OFON" liefert TRUE zurück wenn der Eingang auf High-Pegel liegt und FALSE wenn der Eingang auf Low-Pegel liegt.
print (&h10 = (&h10 and inp(&h379)))

PAP Pin:12

Das Statusbit "PAP" liefert TRUE zurück wenn der Eingang auf High-Pegel liegt und FALSE wenn der Eingang auf Low-Pegel liegt.
print (&h20 = (&h20 and inp(&h379)))

ACK Pin:10

Das Statusbit "ACK" liefert TRUE zurück wenn der Eingang auf High-Pegel liegt und FALSE wenn der Eingang auf Low-Pegel liegt.
print (&h40 = (&h40 and inp(&h379)))

BSY Pin:11

Das Statusbit "BSY" ist Negiert und liefert FALSE zurück wenn der Eingang auf High-Pegel liegt und TRUE wenn der Eingang auf Low-Pegel liegt. Deshalb wird das Eingelesene Signal einfach noch mit "NOT" umgekehrt.
print NOT(&h80 = (&h80 and inp(&h379)))

Beispiel alle Statusbits auflösen und Anzeigen:

a = inp(&h379)
FEH = (&h8 = (&h8 and inp(&h379)))
OFON = (&h8 = (&h8 and inp(&h379)))
PAP = (&h8 = (&h8 and inp(&h379)))
ACK = (&h8 = (&h8 and inp(&h379)))
BSY = NOT(&h8 = (&h8 and inp(&h379)))
print FEH ; OFON ; PAP ; ACK ; BSY

Die Steuerregister:

Die Steuerregister sollten eigentlich Bidirektional sein, jedoch mußte ich feststellen, daß es neuere Schnittstellen giebt die ich nur zur Ausgabe über die Steuerregister bewegen konnte. Also die Ausgabe ist kein Problem. Bei der Eingabe ist damit zu rechnen, daß es nicht mit jeder Schnittstelle Funktioniert. Ganz wichtig bei der Ausgabe ist, daß nur die Steuerbits im Steuerregister geschrieben werden und die Bits 4 bis 7 im Steuerregister nicht geändert werden.

Info:
- Bit 4 (IRQ) legt fest ob beim Übergang von High nach Low Pegel an Pin10 der Schnittstelle ein Hardware-Interrupt Angefordert wird. (Bit4 = 1 aktiv / Bi4 = 0 deaktiviert)
- Bit 5 dient wie weiter oben beschrieben zur Umschaltung Ein- und Ausgabe der Datenbits.

Außerdem ist zu beachten, dass Pin1 (STR); Pin14 (ALF) und Pin17 (DSL) negiert ist. (genauso wie Statusbit BSY an Pin11)

Steuerbits ausgeben:

STR Pin:1

Einschalten out &h37a, ( inp(&h37a) and (&hf0 + &h8 + &h4 +&h2)) + &h0
Ausschalten out &h37a, ( inp(&h37a) and (&hf0 + &h8 + &h4 +&h2)) + &h1

zur Erklärung:
out &h37a, schreiben in das Steuerregister
(inp (&h37a) die alten werte aus dem Steuerregister auslesen
and (&hf0 + &h8 + &h4 +&h2)) die ausgelesenen Werte mit den werten Verknüpfen welche beibehalten werden sollen
+ &h0 und den neuen Wert des zu ändernden Bits zuweisen (dabei Negierung Beachten)

ALF Pin:14

Einschalten out &h37a, ( inp(&h37a) and (&hf0 + &h8 + &h4 +&h1)) + &h0
Ausschalten out &h37a, ( inp(&h37a) and (&hf0 + &h8 + &h4 +&h1)) + &h2

INI Pin:16

Einschalten out &h37a, ( inp(&h37a) and (&hf0 + &h8 + &h2 +&h1)) + &h4
Ausschalten out &h37a, ( inp(&h37a) and (&hf0 + &h8 + &h2 +&h1)) + &h0

DSL Pin:17

Einschalten out &h37a, ( inp(&h37a) and (&hf0 + &h4 + &h2 +&h1)) + &h0
Ausschalten out &h37a, ( inp(&h37a) and (&hf0 + &h4 + &h2 +&h1)) + &h8

Steuerbits einlesen:

Falls die Schnittstelle mitmacht dann so:
out h37a, ((inp(&h37a) and &hf0) + &h4) setzt alle Steuerbits auf High
x = (inp (&h37a) and &hf) Bits 0 bis 3 einlesen und in x speichern

Andere Programmiersprachen:

Weil aber heute niemand mehr in Q-Basic Programmiert und auch ich hier nur die Funktionsweise ohne irgendwelchen Aufwand wo man noch Fehler machen kann Demonstrieren wollte hier ein paar Tips zu anderen Programmiersprachen.

Visual Basic:

Hier gibt's bloß einen Link, weil's dort alles Wissenswerte dazu gibt. Parallelportansteuerung unter VB Außerdem sind hier dll's für die Realisierung unter NT-Systemen zu finden.

C:

In C giebts dafür die Befehle inportb und outportb welche sich in der #include-Datei <conio.h> befinden. Die Funktionsweise ist die gleiche wie in Q-Basic mit INP und OUT.
Achtung inportb und outportb (b für Byte) lesen und schreiben 8Bits, nicht verwechseln mit inport und outport, da werden 16 Bits gelesen und geschrieben. Leider sind die Befehle in neueren C-Compilern nicht mehr Integiriert wie zum Beispiel Visual-C++. Aber in Turbo-C oder Borland C++ ist das alles noch drin.

horizontal rule

Home | Index | Links | Rechts | Kontakt

 Stand: 31. Juli 2003.

horizontal rule