Home

Bauanleitungen

Links

Gästebuch

News

Projekte

Impressum

Ein Interface am Parallelport

Dies ist jetzt alles schön und gut, aber woher bekomme ich jetzt die entsprechenden Signale her?

Eine Möglichkeit, Steuersignale aus dem Computer herauszubekommen, ist der Parallelport. Man kann den Parallelport mit verschiedenen Betriebsarten initialisieren, wir wollen uns aus Kompatibilitätsgründen auf den SPP (Standard-Parallel-Port) beschränken. Nun haben wir allerdings das Problem, daß der Standard-Parallelport eigentlich nur für die Ausgabe von Signalen gedacht ist. Wir können ihn aber mit einigen Tricks dazu bewegen, auch Daten einzulesen.

Schauen wir uns mal die verfügbaren Signale des Parallelports an:

Anschluß  Funktion
1 Ausgang, "Strobe" Bit 0 im Control-Register  (*)
2-9 Ausgang, Datenbit 0-7 Data-Register
10 Eingang, "Ack",  Bit 6 im Status-Register
11 Eingang, "Busy" Bit 7 im Status-Register (*)
12 Eingang, "Paper-Out" Bit 5 im Status-Register
13 Eingang,"Select" Bit 4 im Status-Register
14 Ausgang, "Auto-Linefeed" Bit 1 im Control-Register  (*)
15 Eingang, "Error" Bit 3 im Status-Register
16 Ausgang, "Reset" Bit 2 im Control-Register
17 Ausgang, "Select Printer" Bit 3 im Control-Register   (*)
18-25 Masse

(*) Diese Ein-/Ausgänge sind invertiert, d.h. eine 0 wird als 1 angezeigt und umgekehrt.

Wir haben also insgesamt 12 Ausgänge und 5 Eingänge zur Verfügung. 

Im folgenden Schaltplan wird gezeigt, wie mit 2 ICs des Typs L293D 4 Motoren gesteuert werden können. Außerdem wird mit Hilfe eines ICs des Typs 74LS244 auch das Einlesen von 8 Eingängen möglich. Die Ansteuerung dieses "minimal"-Interfaces geschieht über einfache QBasic-Befehle. Das Einlesen der 8 Eingänge geschieht in zwei Etappen: Der Parallelport stellt nur 5 Eingänge zur Verfügung, die normalerweise zur Statuserkennung von Druckern verwendet werden. Hier kommen wir zu einem weiteren Fachbegriff, den wir später auch noch benötigen werden: Das "Multiplexen". Dies bedeutet, daß Ein- oder Ausgänge mehrfach genutzt werden können. Ein Beispiel: Der PCI-Bus des PC ist auch ein gemultiplexter Bus, denn die PC-Steckkarten nutzen alle die gleichen Busleitungen, die einzelnen Karten werden dann durch spezielle Signale aktiv oder inaktiv geschaltet. 4 der verfügbaren Eingänge werden in diesem Fall doppelt genutzt: Einmal für die Eingänge 1-4, und nochmals für die Eingänge 5-8. Für die Software bedeutet dies, daß jeweils zwei Einlese-Vorgänge gemacht werden müssen.

Jetzt ist alles, was man für ein Interface benötigt, komplett. Das Bauteil mit der Bezeichnung 78L05 ist übrigens für die 5 Volt-Spannungsversorgung zuständig. Da die Motoren mit 9 Volt arbeiten, der Computer und die restlichen ICs üblicherweise mit 5 Volt (teilweise auch weniger), müßte man eigentlich mit 2 Netzteilen arbeiten. Das Bauteil 7805 ist ein Spannungsregler, der unabhängig von der Eingangsspannung eine 5 Volt-Spannung ausgibt (solange die Eingangsspannung 6 V überschreitet). Somit ist man nur noch auf eine Spannungsversorgung angewiesen. Insgesamt kostet dieses Interface so ca. 15 DM, falls man es auf einer Lochraster-Platine aufbaut.

Für eine vergrößerte Ansicht den Schaltplan anklicken.

Um den Schaltplan herunterzuladen, rechte Maustaste klicken und im Kontextmenü "Ziel speichern unter" auswählen (MS Internet-Explorer). Wie es beim Netscape funktioniert, weiß ich leider nicht - vielleicht kanns mir ja mal jemand zumailen.

Ich habe den Schaltplan übrigens geändert - Stand 20.01.2002

parallel-8b.jpg (209932 Byte)

Natürlich bin auch ich nicht vor dem Fehlerteufel sicher.... und es hat sich auch einer eingeschlichen. Damit das Interface funktioniert, muß die Masse (GND) des Druckerports (Pin 18-25) mit der Leitung GND der restlichen Schaltung verbunden werden. 

Hier gibts die Stückliste.

Die Kondensatoren (Wert 100nF/16V) an den Eingängen sind übrigens zur Entprellung. Jeder mechanische Schalter oder Kontakt "prellt" beim Umschalten, d.h. beim Auftreffen der Kontaktzungen aufeinander öffnet und schließt der Kontakt mehrmals, bis er zur Ruhe kommt. So würde das Interface unter Umständen bei einem Umschaltvorgang des Kontakts mehrere Impulse zählen. Der Kondensator verhindert dies. Die Widerstände haben alle den gleichen Wert (4,7K 1/4W) und dienen als Spannungsteiler, damit die 9V die Eingänge des 74244 nicht zerstören.

Auch an den Motor-Ausgängen sind Kondensatoren (220nF/16V) und Widerstände (1 Ohm 1/4W) vorgesehen. In dieser Beschaltung als sog. "R-C-Glied" dienen sie als Entstörung des Motors.

 

Bleibt nur noch: Wie steuert man den Parallelport an?

Der Parallelport wird mit drei Registern angesteuert. Ein Register kann man sich ähnlich wie eine Speicherstelle vorstellen, nur daß die Daten, die man hineinschreibt, eine Auswirkung auf die Anschlüsse des Parallelports haben. Um die Register beschreiben bzw. lesen zu können, muß man die Adresse des Registers kennen. Ohne jetzt zu weit ins Detail gehen zu wollen, man kann die Adresse(n) des (der) Parallelports vom Betriebssystem erfahren, indem man bestimmte, definierte Speicherstellen abfragt (Unter DOS, auch im DOS-Fenster von Windows). Wie das Ganze unter Windows funktioniert, ist mir nicht bekannt, ich bin für jeden Hinweis in dieser Richtung dankbar. Eine weitere Möglichkeit besteht darin, im Gerätemanager der Systemsteuerung nachzuschauen.

Üblicherweise hat der Parallelport die Adresse $0278 oder $0378 (Hexadezimal) .

Im Betriebssystem bekommt man die Information unter folgenden Adressen:

LPT 1  $0000:0408

LPT 2  $0000:040A

LPT 3  $0000:040C

Nehmen wir einfach mal an, der Parallelport hätte die Adresse  $0378, das wäre in Dezimal 888. Dann haben die drei Register die folgenden Adressen:

Data-Register: 888 (888+0, nur Schreiben)

Status-Register 889  (888+1, nur Lesen)

Control-Register 890 (888+2, nur Schreiben)

In Qbasic werden diese Adressen mit den Befehlen OUT (schreiben) und INP (lesen) angesteuert. Der Einfachheit halber definiert man die Variable port mit dem Wert des Ports.

Um also auf die Motoren zugreifen zu können, muß man mit OUT port,X den Parallelport ansteuern. Wir können mit jedem Befehl 1 Byte übertragen, das aus 8 Bit besteht. Jedes Bit entspricht einem Ausgang, somit können wir jeden der 8 Ausgänge einzeln ein- und ausschalten. 

Wie schalte ich nun einzelne Bits (Ausgänge) an und aus? Hierzu müssen wir einen kleinen Ausflug in ein anderes Zahlensystem, das Binärsystem machen. Das Binärsystem kennt nur 0 (aus) und 1 (an). Damit unterscheidet es sich von dem uns geläufigen 10er (oder Dezimal-) System. Hier kann jede Stelle Werte zwischen 0 und 9 annehmen. Um eine Zahl im Binärsystem darzustellen, muß man sie umrechnen.

Sehen wir uns hierzu mal die Zahl 157 (Dezimal) an.  Man kann sie auch 

100 x 1 + 5 x 10 + 7 x 1

schreiben. Jede Stelle (Einer, Zehner, Hunderter) hat also einen gewissen Stellenwert (wie das Wort schon sagt).

Ebenso ist es bei Binärzahlen: Die Zahl %1011 (um die Zahlensysteme zu unterscheiden, sind vorangestellte oder angehängte Zeichen üblich. Die Schreibweise 1011b ist auch möglich)

1 x 1000 + 0 x 100 + 1 x 10 + 1 x 1

Um jetzt diese Zahl umrechnen zu können, braucht man den entsprechenden Wert jeder Stelle im Dezimalsystem. Um nicht zu sehr ins Detail gehen zu müssen, machen wir es mit einer einfachen Tabelle (den genauen mathematischen Zusammenhang kann man in jedem Mathematik- oder Informatikbuch nachlesen).

Stelle Wert (Dezimal)
0 2^0 = 1
1 2^1 = 2
2 2^2 = 4
3 2^3 = 8
4 2^4 = 16
5 2^5 = 32
6 2^6 = 64
7 2^7 = 128

Somit wäre unsere obige Beispielzahl %1011 

1 x 8 + 0 x 4 + 1 x 2 + 1 x 1= 11

Wollen wir also die Ausgänge 8, 5 und 3 einschalten (man beachte, daß die Stellen von 0 - 7 gezählt werden, die Ausgänge aber von 1 - 8) , müssen also die Bits 7, 4 und 2 ="1" werden.

1 x 128 + 1 x 16 + 1 x 4 = 148

Wenn man also den Befehl OUT port,148 ausführen läßt, dann werden die entsprechenden Ausgänge eingeschaltet.

Was bedeutet ein- und ausgeschaltet? In unserem Beispiel heißt dies, daß der entsprechende Ausgang entweder auf 9Volt oder 0 Volt (Masse oder auch Minuspol der Spannungsversorgung) liegt. Um eine Lampe leuchten zu lassen, wenn ein Ausgang eingeschaltet ist, muß man einen der Anschlüsse an den gewünschten Ausgang legen, den anderen Anschluß der Lampe an Masse. Wird der Ausgang auf 9 Volt geschaltet, leuchtet die Lampe, wird er ausgeschaltet erlischt sie, da beide Anschlüsse der Lampe nun auf Masse liegen. Man kann anstelle der Lampe auch einen Motor anschließen, allerdings kann man ihn in dieser Weise nur ein- und auschalten, aber nicht links und rechts laufen lassen.

Um einen Motor in beide Richtungen betreiben zu können, muß man ihn umpolen können. Man kann dies überprüfen, indem man den Motor an eine Spannungsquelle anschließt. Er wird immer die gleiche Drehrichtung haben. Nur wenn man am Motor die Stecker tauscht (oder an der Spannungsquelle) dreht er in die andere Richtung. Diesen Effekt  können wir bei unserem Interface auch erzeugen, indem man den Motor an zwei Ausgänge anschließt (wie dies auf dem Schaltplan schon angedeutet ist).

Nehmen wir an, wir haben einen Motor auf Ausgang 1 und 2 angeschlossen. Sind beide Ausgänge ausgeschaltet, hat der Motor auf beiden Seiten Masse und dreht sich nicht, denn es kann kein Strom fließen. Schalten wir nun Ausgang 1 ein, dreht sich der Motor (mal angenommen) links herum, denn Ausgang 1 ist auf 9 Volt (Plus)  und Ausgang 2 auf Masse (Minus) - der gleiche Zustand, als ob ich den Motor in ein Netzteil stecke (oder in die Batterie-Box). Was passiert nun, wenn ich Ausgang 1 an lasse und zusätzlich Ausgang 2 einschalte? Wer meint, der Motor würde sich nun drehen, liegt leider falsch. Wir haben nun an beiden Ausgängen 9 Volt, es gibt keinen Stromfluß. Keine Angst, dies ist ein völlig ungefährlicher Zustand. Nur wenn ich gleichzeitig den Ausgang 1 wieder ausschalte, dreht sich der Motor nun anders herum.

Programmiertechnisch sieht das so aus:

OUT port,0 Motor 1 aus
OUT port,1 Motor 1 rechts
OUT port,2 Motor 1 links
OUT port,3 Motor 1 aus

 Wenn wir uns nun die Binärzahlen ins Gedächtnis zurückrufen:

0 00
1 01
2 10
3 11

Man sieht also: Immer wenn die zwei zum Motor führenden Ausgänge unterschiedliche Zustände haben, läuft der Motor.

Für die anderen Motoren sieht es entsprechend aus. Beispiel: Motor 1 soll sich links, Motor 3+4 rechtsherum drehen. Als Binärzahl geschrieben, müssen die Ausgänge folgendermaßen geschaltet werden:

M4 M3 M2 M1

01  01  00  10

 

oder:

%01010010 = 64+16+2 = 82

Mit OUT port,82 hätte man also exakt diesen Zustand der Ausgänge.

Wie schon weiter oben erwähnt, werden wir die Eingänge in zwei Schritten einlesen müssen, da der Standard-Parallel-Port uns keine 8 Eingänge zur Verfügung stellt. Hier kommt das IC4 (74HC244) ins Spiel. Dieses IC besteht aus zwei Bus-Treibern zu je 4 Bit, oder anders: Zwei Verstärker mit je 4 Kanälen. Auf dem Schaltplan sieht man, daß jeweils zwei Ausgänge dieses ICs auf einen Eingang des Parallelport führen. Normalerweise bedeutet das Verbinden zweier Ausgänge automatisch Gefahr, denn es kann durchaus sein, daß die Ausgänge unterschiedliche Spannungspegel haben (wollen). Wenn man nun High- und Low- Pegel (also 5 und 0 Volt) zusammenschließt, bekommt man einen Kurzschluß und zerstört evtl. ein Bauteil. Wie also verhindert man dies? Das Geheimnis liegt in den Eingängen "G1" und "G2". Der "Kringel" an den Zuleitungen zu diesen Eingängen bedeutet übrigens, daß diese Eingänge "LOW-aktiv" sind, mit anderen Worten: Sie sind aktiviert, wenn Low-Pegel (0 Volt = Minus) anliegt. Jeder der Eingänge G1 und G2 ist für eine Gruppe von 4 Leitungen zuständig. Wird an G1 Low-Pegel angelegt, sind die Leitungen A1->Y1 ... A4->Y4 aktiv, bei G2 sind es die Leitungen A5->Y5... A8->Y8.

Den Zustand der Eingänge am Parallel-Port kann man über das Status-Register abfragen, mit dem schon angesprochenen INP() Befehl:

X=INP(port + 1)

Mit diesem Befehl bekommt man in X ein Byte. Wir haben aber nur 4 Bit, die gelesen werden können, also haben wir auch ein wenig "Müll" mitgelesen, den wir loswerden müssen. Die für uns interessanten Bits sind die Bits 4,5,6 und 7 , also die oberen 4 Bits, in den unteren 4 Bits sind Daten, die wir nicht verwenden können. Man spricht bei einer vierer - Gruppe Bits auch von "Nibble", dabei ist Bit 0-3 das untere Nibble und Bit 4-7 das obere. Wir müssen also das obere Nibble isolieren. Dies geschieht mit dem AND - Befehl:

X = INP(port+1) AND 240

Die Zahl 240 ins Binärsystem umgerechnet ergibt %11110000,  man sieht also: Das obere Nibble ist %1111, das untere %0000. Durch den AND - Befehl werden zwei Zahlen (in unserem Fall das Ergebnis von INP(889) und die Zahl %11110000) binär miteinander verknüpft. Dabei bleibt im Ergebnis genau dann eine 1 stehen, wenn in beiden Operanden eine 1 vorhanden war. Beispiel:

%11110000 AND %10010110 = %10010000

Bei beiden Lesevorgängen bekommen wir das Ergebnis im oberen Nibble. Es ist aber sicherlich einfacher, einen der beiden Lesevorgänge in das untere Nibble zu verschieben, somit hätten wir zur weiteren Verarbeitung wieder ein vollständiges Byte. Um eine Binärzahl nach rechts zu verschieben (um das obere Nibble ins untere zu bekommen) muß man sie pro Stelle durch zwei teilen, vier Stellen in unserem Fall entspricht also einem Teiler von 16.

Dies war jetzt aber viel komplizierte Theorie - kommen wir zur Praxis. Ein QBASIC-Listing zur Abfrage der Eingänge sieht dann folgendermaßen aus:

OUT port + 2, 1                            'Das untere Nibble am 74HC244  anwählen

e1 = INP(port  + 1) AND 240        'Vom Port das obere Nibble lesen

e1 = e1  XOR 128                        'Das Busy-Bit invertieren (Bit 7)

e1 = e1 / 16                                 'und 4x verschieben ins untere Nibble

 

OUT port + 2, 2                            'Das obere Nibble am 74HC244 anwählen

e2 = INP(port  + 1) AND 240        'Vom Port das obere Nibble lesen

e2 = e2 XOR 128                        'Das Busy-Bit invertieren (Bit 7)

 

eingang = e1 + e2                        'Das Gesamt-Ergebnis ( 1 Byte ) wird in Variable "eingang" geschrieben

Der Befehl XOR, den wir bislang nicht besprochen haben, verknüpft (ähnlich dem AND) zwei Zahlen binär. Nur wenn die entsprechenden Bits identisch sind, ergibt sich eine 0, sind sie unterschiedlich, ergibt sich eine 1.

Beispiel 1:

%11110000  XOR %11001100  = %00111100

Beispiel 2:

%11111111 XOR %11001100 = %00110011

Wie man in Beispiel 2 sieht, wird eine Zahl binär invertiert (d.h. 0 wird 1 und 1 wird 0), wenn man sie mit XOR %11111111 (oder auch XOR 255) verknüpft. Wie schon in der Tabelle am Anfang der Seite gezeigt, gibt es Eingänge und Ausgänge am Drucker-Port, die Invertiert sind, d.h. dort wird bereits von der Hardware eine Invertierung vorgenommen. Um dies wieder auszugleichen, muß das Bit 7 ("Busy"-Leitung) invertiert werden, um den tatsächlichen Zustand zu erhalten. Dies geschieht mit dem Befehl .... XOR 128.

Soviel zum "kleinen" Interface. Aber man kann mit relativ wenig Aufwand noch mehr bekommen: 16 Ein- und 16 Ausgänge (bzw. 8 Motoren). Hier gehts weiter...

 

Home

Bauanleitungen

Links

Gästebuch

News

Projekte

Impressum