
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.

| 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 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.
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 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 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.
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))
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 kann man nur zum einlesen verwenden. Dabei ist es egal, ob die Datenbits gerade zur Eingabe oder zur Ausgabe dienen.
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".
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.
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)))
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)))
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)))
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)))
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 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)
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)
Einschalten out &h37a, ( inp(&h37a) and (&hf0 + &h8
+ &h4 +&h1)) + &h0
Ausschalten out &h37a, ( inp(&h37a) and (&hf0 + &h8 +
&h4 +&h1)) + &h2
Einschalten out &h37a, ( inp(&h37a) and (&hf0 + &h8
+ &h2 +&h1)) + &h4
Ausschalten out &h37a, ( inp(&h37a) and (&hf0 + &h8 +
&h2 +&h1)) + &h0
Einschalten out &h37a, ( inp(&h37a) and (&hf0 + &h4
+ &h2 +&h1)) + &h0
Ausschalten out &h37a, ( inp(&h37a) and (&hf0 + &h4 +
&h2 +&h1)) + &h8
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
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.
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.
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.
![]()
Stand: 31. Juli 2003.
![]()