Programmierung der seriellen und parallelen Schnittstelle unter DOS | |
|
Frank Steinberg - https://www.FrankSteinberg.de - Version 24.06.2003. |
Habe ich was Falsches geschrieben? Bitte Mail an mich.
Download aller Beispieldateien dieser Seite und mehr ... (msr.zip)
Wir erfahren, wie man die serielle RS 232 Schnittstelle und die parallele (Centronics) Schnittstelle so programmiert, dass man Signale in Form von Spannungen (bei kleinen Strömen) ausgeben und Signale einlesen kann.
Nicht behandeln werden wir:
Wie der Titel schon sagt, geht's um die Programmierung unter DOS. Unter Windows oder Linux bleibt der PC derselbe. Deshalb bleiben die Verfahren gleich. Ich habe aber zu wenig Durchblick, was das Betriebssystem und die Programmiersprachen zulassen. Über einige kleine Versuche bin ich bisher nicht hinausgekommen. Das bisschen, was ich dazu sagen kann, steht in win32bit.htm.
Jetzt kommt erst mal 'ne Übersicht, welche Anweisungen und Funktionen man so braucht, um in die Port-Register zu schreiben aus ihnen zu lesen. Das Ganze für die solche Programmiersprachen, die man kostenlos aus dem Internet bekommt. Ich weiß, dass das in vielen Büchern zu Programmiersprachen ausgelassen wird, das gilt insbesondere für Anfängerbücher.
So wird aus einem I/O - Port gelesen | |||
Programmiersprache |
Anweisung |
Beispiel |
Bemerkung |
Assembler |
|
|
|
Turbo C |
|
|
liest ein Byte |
Pacific C |
|
|
|
Turbo Pascal |
|
|
liest ein Byte |
Basic |
|
|
|
So wird in einen I/O - Port geschrieben | |||
Programmiersprache |
Anweisung |
Beispiel |
Bemerkung |
Assembler |
|
|
|
Turbo C |
|
|
schreibt ein Byte |
Pacific C |
|
|
|
Turbo Pascal |
|
|
schreibt ein Byte |
Basic |
|
|
|
Um die Schnittstellen anzusprechen, schreibt/liest man Bytes in einem besonderen 64 kB großen Speicherbereich, den I/O Registern. Die Befehle dafür sind unter 2. vorgestellt. Die Basisadressen spucken fast alle Diagnoseprogramme aus (z.B. msd.exe im Lieferumfang von Ms-DOS 6.xx) . Außerdem werden sie bei den meisten PCs beim Booten angezeigt.
Die Basisadressen der seriellen Schnittstellen liegen bei allen mir zur Verfügung stehenden PCs bei 3F8hex für COM1 und 2F8hex für COM2. Beim Parallelport wird es schon schwieriger. Meist liegt LPT1 bei 378hex, seltener bei 3BChex, LPT2 meist bei 278hex. Darauf verlassen sollten wir uns aber nicht.
Wie kommen wir nun elegant an die richtigen I/O-Adressen ran? Wir können im unteren Bereich des Hauptspeichers (dem Bios-Datenbereich) die Basisadressen aller im jeweiligen Computer vorhandenen seriellen/parallelen Schnittstellen auslesen. In Basic steht dafür die Funktion PEEK
zur Verfügung. In den Hauptspeicher geschrieben wird übrigens mit POKE
. Bei PEEK
kann man nicht viel falsch machen, man verändert ja nichts. POKE
ist dagegen mit Bedacht anzuwenden! Bei PEEK/POKE
bitte immer vorher das Speichersegment mit DEF SEG = ...
bestimmen! Für unsere Zwecke ist immer DEF SEG = 0
angesagt.
Interessante Adressen im Hauptspeicher (Bios-Datenbereich) | ||||
Segment- |
Offset-Adresse |
Umfang |
Inhalt |
Bemerkung |
0 |
400 - 401 hex |
2 Byte |
I/O-Register Basisadresse von COM 1 |
= 0 wenn nicht vorhanden |
0 |
402 - 403 hex |
2 Byte |
I/O-Register Basisadresse von COM 2 |
= 0 wenn nicht vorhanden |
0 |
404 - 405 hex |
2 Byte |
I/O-Register Basisadresse von COM 3 |
= 0 wenn nicht vorhanden |
0 |
406 - 407 hex |
2 Byte |
I/O-Register Basisadresse von COM 4 |
= 0 wenn nicht vorhanden |
0 |
408 - 409 hex |
2 Byte |
I/O-Register Basisadresse von LPT 1 |
= 0 wenn nicht vorhanden |
0 |
40A - 40B hex |
2 Byte |
I/O-Register Basisadresse von LPT 2 |
= 0 wenn nicht vorhanden |
0 |
40C - 40D hex |
2 Byte |
I/O-Register Basisadresse von LPT 3 |
= 0 wenn nicht vorhanden |
0 |
40E - 40F hex |
2 Byte |
I/O-Register Basisadresse von LPT 4 |
= 0 wenn nicht vorhanden |
0 |
46C - 46F hex |
4 Byte |
Systemtimer - Zähler |
Wird alle 18,2 Sek inkrementiert, |
Die Basisadresse von LPT 1 können wir dann folgendermaßen ermitteln:
DEF SEG
= 0
BasAdr% = PEEK
(&H408) +
PEEK
(&H409) * 256
Ein Beispiel, bei dem COM 1-4 und LPT 1-3 abgefragt werden, zeigt portadr.bas.
Mit Power Basic steht zusätzlich zu PEEK
noch PEEKI
(liest ein Word = 2 Byte), PEEKL
(liest 4 Byte) und PEEK$
(liest eine Byte-Sequenz) zur Verfügung. Zusätzlich gibt es die Entsprechungen für POKE:
DEF SEG
= 0
BasAdr% = PEEKI
(&H408)
In Turbo Pascal geht das Lesen des Hauptspeichers mit
ByteWert :=
mem
[
SegmentAdresse:OffsetAdresse
];
Wenn wir ein 16-Bit Bytepaar ("Word"), brauchen, geht es das sehr komfortabel mit
WordWert :=
memw
[
SegmentAdresse:OffsetAdresse
];
Die Basisdresse von LPT1 könnte man also wie folgt auslesen: BasAdr := memw[$0:$408];
Entsprechend schreiben wir in den Hauptspeicher mit
mem
[
SegmentAdresse:OffsetAdresse
] := ByteWert;
.
bzw
memw
[
SegmentAdresse:OffsetAdresse
] = WordWert;
Um eine Spannung auf einem Pin einer Schnittstelle zu erzeugen oder den Staus eines Pins zu lesen, müssen wir einzelne Bits setzen, löschen oder lesen. Leider gibt es für keine Programmiersprache Anweisungen, wie "setze Bit 3 des Bytes auf 1". Was tun? Bevor wir das angehen, erstmal eine Exkursion, wie so ein Byte aufgebaut ist. Wir alle wissen: Ein Byte hat 8 Bits. Damit kann man 256 verschieden Zahlen darstellen (0 - 255). Dazu hat jedes Bit entsprechend seiner Stellung im Byte einen bestimmten Wert. Die Stellung im Byte wird von 0 bis 7 gezählt.
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Wert |
27 |
26 |
25 |
24 |
23 |
22 |
21 |
20 |
128 |
64 |
32 |
16 |
8 |
4 |
2 |
1 |
Aha: Wir geben also in Basic ein: OUT &H378, 4
und schon ist Bit 2 gesetzt und wir haben + 5V an Pin 4 von LPT1 (wir wissen das, weil wir schon mal heimlich im nächsten Abschnitt gelesen haben). Gebe ich OUT &H378, 5
ein, sind Bit 0 und 2 gesetzt, ich habe +5V an Pin 2 und 4.
Stimmt (mal unterstellt, die Basisadresse von LPT1 ist 378hex)! Wir haben aber alle anderen Bits zwangsweise auf 0 gesetzt. Oft müssen wir aber einzelne Bits ändern, OHNE die anderen zu behelligen. Da gibt es einige Möglichkeiten, wie man sowas macht. Am einfachsten geht das mit (bitweisen) AND - oder OR - Verknüpfungen.
Jeder der programmiert, kennt solche Konstruktionen:
IF Zahl% > 0
AND
Zahl% < 7 THEN PRINT "Die Zahl ist eine gültige Zensur"
oder
IF Zahl% < 1
OR
Zahl% > 6 THEN PRINT "Die Zahl ist keine gültige Zensur"
.
Verblüffend für viele ist aber:
PRINT 12
AND
10
als Ergebnis wird 8 angezeigt oder
PRINT 12
OR
10
als Ergebnis wird 14 angezeigt.
Wie das? Die Zahlen werden bitweise verglichen! Bei AND geht ein Bit im Ergebnis nur auf 1, wenn beide Vergleichsbits auf 1 stehen. Bei der OR - Verknüpfung geht das Ergebnisbit auf 1, wenn eines der beiden Vergleichsbits auf 1 steht. Lasst uns überprüfen, ob Basic richtig arbeitet ;-) :
Bit » |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Summe (Byte) |
Wert |
128 |
64 |
32 |
16 |
8 |
4 |
2 |
1 |
255 |
Zahl 1 |
0 |
0 |
0 |
0 |
1 |
1 |
0 |
0 |
12 |
Zahl 2 |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
0 |
10 |
Ergebnis der AND Verknüpfung |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
8 |
Bit » |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Summe (Byte) |
Wert |
128 |
64 |
32 |
16 |
8 |
4 |
2 |
1 |
255 |
Zahl 1 |
0 |
0 |
0 |
0 |
1 |
1 |
0 |
0 |
12 |
Zahl 2 |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
0 |
10 |
Ergebnis der OR Verknüpfung |
0 |
0 |
0 |
0 |
1 |
1 |
1 |
0 |
14 |
Als weitere Operanden für bitweise Verknüpfungen gibt es in Basic noch EQV, IMP, NOT und XOR. Für uns reichen AND, OR und XOR aus. Wir werden damit jetzt folgende vier Aufgaben lösen:
Einzelne Bits setzen wir, indem wir das erste Byte (das wir z.B. aus einem Port-Register auslesen) mit einem Vergleichsbyte per OR verknüpfen, bei dem die zu setzenden Bits auf 1 stehen, der Rest auf 0. Nehmen wir an, wir wollen die Bits 1, 2 und 3 auf 1 setzen, dann ist der Basic-Code:
ByteGelesen% = INP(Adresse%)
oder ganz kurz:
ByteNeu% = ByteGelesen% OR 14
OUT Adresse%, ByteNeu%
OUT Adresse%, INP(Adresse%) OR 14
Zur Überprüfung bemühen wir nochmal unsere Tabelle:
Bit » |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Summe (Byte) |
Wert |
128 |
64 |
32 |
16 |
8 |
4 |
2 |
1 |
255 |
vom Port gelesen |
0 |
1 |
0 |
1 |
0 |
1 |
0 |
1 |
85 (beliebig) |
unser Vergleichsbyte |
0 |
0 |
0 |
0 |
1 |
1 |
1 |
0 |
14 |
Ergebnis der OR Verknüpfung |
0 |
1 |
0 |
1 |
1 |
1 |
1 |
1 |
95 |
Wir sehen: Die Bits 1 und 3 waren zuvor auf 0 und sind jetzt gesetzt. Bit 2 war zuvor schon gesetzt, was auch so geblieben ist. Wäre es auf 0 gewesen, wäre es auch gesetzt worden. Der Rest ist im ursprünglichen Zustand geblieben. Wunderbar!
Einzelne Bits löschen wir, indem wir das erste Byte (das wir wieder aus einem Port-Register ausgelesen haben) mit einem Vergleichsbyte per AND verknüpfen. Bei dem Vergleichsbyte müssen die zu löschenden Bits auf 0 stehen, der Rest auf 1. Wir nehmen diesmal die Bits 0, 1 und 2. In Basic schreiben wir:
ByteGelesen% = INP(Adresse%)
oder ganz kurz:
ByteNeu% = ByteGelesen% AND 248
OUT Adresse%, ByteNeu%
OUT Adresse%, INP(Adresse%) AND 248
Die Tabelle kennen wir nun schon:
Bit » |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Summe (Byte) |
Wert |
128 |
64 |
32 |
16 |
8 |
4 |
2 |
1 |
255 |
vom Port gelesen |
0 |
1 |
0 |
1 |
0 |
1 |
0 |
1 |
85 (beliebig) |
unser Vergleichsbyte |
1 |
1 |
1 |
1 |
1 |
0 |
0 |
0 |
248 |
Ergebnis der AND Verknüpfung |
0 |
1 |
0 |
1 |
0 |
0 |
0 |
0 |
80 |
Bit 0 und 3 waren vorher gesetzt, nun sind sie auf 0; so sollte es sein. Bit 1 war vorher schon auf 0 und bleibt es (wäre aber gelöscht worden). Der Rest steht wie gelesen; genau wie geplant.
Einzelnen Bits geben wir den entgegengesetzten Wert, indem wir das Vergleichsbyte wie folgt aufbauen: Die Bits, die wir ändern wollen, setzen wir auf 1. Die Bits, die gleich bleiben sollen auf 0. Unser Ursprungsbyte (aus einem Port-Register ausgelesen), wird mit diesem Vergleichsbyte per XOR verknüpft. Im Beispiel alternieren wir die vier niedrigwertigen Bits, die anderen sollen gleich bleiben. In Basic schreiben wir:
ByteGelesen% = INP(Adresse%)
oder ganz kurz:
ByteNeu% = ByteGelesen% XOR 15
OUT Adresse%, ByteNeu%
OUT Adresse%, INP(Adresse%) XOR 15
Wieder die Tabelle:
Bit » |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Summe (Byte) |
Wert |
128 |
64 |
32 |
16 |
8 |
4 |
2 |
1 |
255 |
vom Port gelesen |
0 |
1 |
0 |
1 |
0 |
1 |
0 |
1 |
85 (beliebig) |
unser Vergleichsbyte |
0 |
0 |
0 |
0 |
1 |
1 |
1 |
1 |
15 |
Ergebnis der XOR Verknüpfung |
0 |
1 |
0 |
1 |
1 |
0 |
1 |
0 |
90 |
XOR nennt man auch Exclusiv-ODER. Die Bedingung wird nur wahr (Bit auf 1), wenn die verglichenen Bits verschieden sind. Zu unserem Beispiel: Bit 0 bis 3 haben ihren Wert gewechselt, Bit 4 - 7 sind gleich geblieben. So sollte es sein
AD-Wandler teilen uns die Ergebnisse ihrer Wandlungen in Form von Spannungen mit, die auf Anforderung gesetzt werden oder eben nicht. Die Spannungen werden an einen Pin gesendet, der mit einem Port-Eingang verbunden ist. Da müssen wir "reinhorchen" und einzelne Bits auswerten. Wir können die folgenden Abläufe auch z.B. dazu verwenden, einen Schalter mit einem Schnittstelleneingang zu verbinden und dessen Stellung auswerten. Das permanente Abfragen von solchen Zuständen nennt man übrigens "polling".
Zum Einsatz kommt wieder die AND-Verknüpfung. Im Vergleichsbyte setzen wir nur das gesuchte Bit auf 1, der Rest ist 0. Im Ergebnisbyte ist entweder allein das gesucht Bit gesetzt oder keins. Wenn wir Bit 6 abfragen, hat das Ergebnisbyte entweder den Wert 64 (wenn Bit 6 = 1) oder 0 (wenn Bit 6 = 0). Lets's talk Basic:
ByteGelesen% = INP(Adresse%)
oder kürzer:
VergleichsByte% = 64
IF ByteGelesen% AND VergleichsByte% = VergleichsByte% THEN
PRINT "Bit 6 = 1"
ELSE
PRINT "Bit 6 = 0"
END IF
IF INP(Adresse%) AND 64 = 0 THEN PRINT "Bit6=0" ELSE PRINT "Bit6=1"
Zum letzten mal unsere Tabelle:
Bit » |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Summe (Byte) |
Wert |
128 |
64 |
32 |
16 |
8 |
4 |
2 |
1 |
255 |
vom Port gelesen |
0 |
1 |
0 |
1 |
0 |
1 |
0 |
1 |
85 (beliebig) |
unser Vergleichsbyte |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
64 |
Ergebnis der AND Verknüpfung |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
64 |
Wir sehen sofort: Wäre Bit 6 nicht gesetzt gewesen, wären alle Bits im Ergebnis auf 0 gesetzt. Der Wert des Bytes wäre dann logischerweise auch 0.
Bevor es hier losgeht eine Warnung: Die maximale Spannung, die aus einer Schnittstelle rauskommt, beträgt 15V. Uns selber werden wir damit nicht kaputtkriegen, unsere Schnittstelle aber schon. Grundsätzlich gilt: Die serielle Schnitstelle ist besser abgesichert als die parallele. Beim Parallelport vor allem die Datenleitungen (Pin 2-9) nicht ohne Vorwiderstand mit Masse oder einer Spannung verbinden.
Ich empfehle, eine billige (ISA-) Schnittstellenkarte für alle Versuche zu kaufen (inzwischen allerdings schwer zu bekommen) oder den alten 286'er zu benutzen. In jedem Fall erst überlegen, dann fummeln! Die Pin-Nummern stehen direkt auf den Steckern. Wer keine Adleraugen hat, findet die Steckerbelegungen unter 5.4 und 5.7.
Alles was ihr tut, geschieht auf eigene Gefahr!
6. Wie ermitteln wir die Registeradressen? |
Die Adressen der Register werden in der folgenden Tabelle nicht in absoluten Werten angegeben, sondern in Abständen von der Basisadresse, dem Offset. Wie wir die Basisadresse bestimmen , haben wir ja unter 3. gelernt. Nehmen wir an, COM1 hat 3F8hex, COM2 hat 2F8hex und LPT 1 378hex. Das Modemstatusregister der seriellen Schnittstelle hat einen Offset von 6, das Statusregister der parallelen Schnittstelle hat Offset 1. Der Auslesen muss in Basic wie folgt aussehen:
MStatusRegByte% = INP (&H3F8 + 6)
oder MStatusRegByte% = INP (&H3FE)
für COM1
MStatusRegByte% = INP (&H2F8 + 6)
oder MStatusRegByte% = INP (&H2FE)
für COM2
PPStatusRegByte% = INP (&H378 + 1)
oder PPStatusRegByte% = INP (&H379)
für LPT1
Das Modemsteuerregister hat einen Offset von 4, das Datenregister der Parallelports Offset 0. So schreiben wir mit Basic in die Register:
OUT &H3F8+4, MSteuerByte%
oder OUT &H3FC, MSteuerByte%
für COM1
OUT &H2F8+4, MSteuerByte%
oder OUT &H2FC, MSteuerByte%
für COM2
OUT &H378, PPDatenRegByte%
für LPT1
Wir können alle Adressen natürlich auch in Variablen/Konstanten ablegen: X% = INP(AdrMStRCOM2%)
.
Die serielle Schnittstelle ist erfreulich einheitlich ausgelegt. Von den insgesamt 10 für die serielle Schnittstelle vorhandenen 8-Bit Registern sind die meisten für den asynchronen Datenverkehr zuständig. Für die Steuerleitungen (Ausgänge) brauchen wir nur das Modemsteuerregister (Offset 4), für die Statusleitungen (Eingänge) das Modemstatusregister (Offset 6). Es stehen insgesamt 4 Eingänge und 2 Ausgänge zur Verfügung. Der eigentlich für das asynchrone Senden vorgesehene Datenausgang (TxD), kann über das Bit 6 des Datenformatregisters (Offset 3) wie ein Steuerausgang verwendet werden. Damit erhöht sich die Anzahl der Ausgänge auf 3.
7.1 Die elektrischen Eigenschaften der seriellelen Schnittstelle |
Spannungen und Pegel:
Ein High-Pegel wird durch eine Spannung von ca. +3 V bis +15 V dargestellt, ein Low-Pegel durch ca. -3 V bis -15 V. Die Eingänge interpretieren einen spannungslosen Zustand als Low-Pegel (Bit ist auf 0). Ein PC-Netzteil stellt +12 V und -12 V zur Verfügung. Größer ist der Pegel deshalb an den Ausgängen meist nicht. Die kleinsten Werte, die ich gemessen habe, lagen bei +9 V / -9 V! Aber immer dran denken: Die Spannung an den Ausgängen ist nie Null; immer ca. -12 V oder + 12 V!
Ströme:
Eine serielle Schnittstelle kann ca. 20 mA pro Ausgang zur Verfügung stellen. Das reicht zur Versorgung vieler elektronischer Schaltungen (z.B. AD-Wandler) aus. Eine Leuchtdiode kann mit einem Vorwiderstand von 470 Ohm - 1 KOhm direkt angeschlossen werden.
Bit |
Wert |
Bezeichnung |
Pin |
Pegel, wenn Bit auf ... |
Beschreibung | ||
9 Pol |
25 Pol |
0 |
1 | ||||
Datenformat-Register (ein Ausgang) |
Basisadresse + 3 (Offset 3) | ||||||
0 |
1 |
Datenbits |
- |
- |
- |
- |
|
1 |
2 |
Datenbits |
- |
- |
- |
- |
|
2 |
4 |
Stopbits |
- |
- |
- |
- |
|
3 |
8 |
Parität |
- |
- |
- |
- |
|
4 |
16 |
Parität |
- |
- |
- |
- |
|
5 |
32 |
Parität |
- |
- |
- |
- |
|
6 |
64 |
Break TxD (Transmit Data) |
3 |
2 |
-12 V |
+12 V |
setzt TxD wie einen Steuerausg. |
7 |
128 |
Divisor-Latch Access |
- |
- |
- |
- |
|
Modem-Steuer-Register (zwei Ausgänge) |
Basisadresse + 4 (Offset 4) | ||||||
0 |
1 |
DTR (Data Terminal Ready) |
4 |
20 |
-12 V |
+12 V |
|
1 |
2 |
RTS (Ready To Send) |
7 |
4 |
-12 V |
+12 V |
|
2 |
4 |
nicht verwendet |
- |
- |
- |
- |
|
3 |
8 |
Master-Interrupt |
- |
- |
- |
- |
|
4 |
16 |
Loop |
- |
- |
- |
- |
|
5 |
32 |
nicht verwendet |
- |
- |
- |
- |
|
6 |
64 |
nicht verwendet |
- |
- |
- |
- |
|
7 |
128 |
nicht verwendet |
- |
- |
- |
- |
|
Modem-Status-Register (vier Eingänge) |
Basisadresse + 6 (Offset 6) | ||||||
0 |
1 |
DCTS |
- |
- |
gleich |
verändert |
Änderung CTS seit letztem Lesen |
1 |
2 |
DDSR |
- |
- |
gleich |
verändert |
Änderung DSR seit letztem Lesen |
2 |
4 |
DRI |
- |
- |
gleich |
verändert |
Änderung RI seit letztem Lesen |
3 |
8 |
DDCD |
- |
- |
gleich |
verändert |
Änderung DCD seit letztem Lesen |
4 |
16 |
CTS (Clear To Send) |
8 |
5 |
-12 V |
+12 V |
bei 0V Bit auf 0 |
5 |
32 |
DSR (Data Set Ready) |
6 |
6 |
-12 V |
+12 V |
bei 0V Bit auf 0 |
6 |
64 |
RI (Ring Indicator) |
9 |
22 |
-12 V |
+12 V |
bei 0V Bit auf 0 |
7 |
128 |
DCD (Data Carrier Detect) |
1 |
8 |
-12 V |
+12 V |
bei 0V Bit auf 0 |
Masse (GND) |
5 |
7 |
|
|
|
9 Pol Sub-D |
25 Pol Sub-D |
9 Pol Sub-D |
25 Pol Sub-D |
Stecker am Computer: |
Kupplung am Endgerät: | ||
1 5 |
1 13 |
5 1 |
13 1 |
Während wir uns bei der seriellen Schnittstelle auf Standards verlassen können, gibt es bei der prallelen Schnittstelle große Unterschiede in der Auslegung:
Die Eigenschaften des Parallelport können wir mit dem Parallelport-Debugger (Download) austesten. Mit dem Programm können wir alle Ausgänge schalten, die Eingänge beobachten und Statusbits setzen. Über einen Widerstand (ca. 1 kOhm) können wir die Ein- und Ausgänge nach Masse oder mit einer 5V-Spannungsquelle verbinden und die Reaktion beobachten.
8.1 Die elektrischen Eigenschaften der parallelen Schnittstelle |
Spannungen und Pegel:
Ein High-Pegel wird durch eine Spannung von ca. 2 - 5 V dargestellt, ein Low-Pegel durch ca. 0 - 0,8 V. Ich habe bei meinen Computern die Spannungen gemessen, die tatsächlich bei einem High-Pegel an den Ausgängen anliegen: Je nach gemessenem Parallelport lagen die Werte bei 3,3 - 5,1 V!
Die 5 Eingänge des Parallelport-Statusregisters (Offset 1) sind meist intern auf HIGH gesetzt. Schalterstellungen können wir einfach einlesen, indem wir einen Eingang mit Masse verbinden. Bei neueren Computern ist das bei allen 5 Eingängen der Fall, bei den älteren manchmal nur bei "Acknowledge" (Bit 6).
Ströme:
Ein Warnhinweis vorweg: Die Datenausgänge (Pins 2 - 9) bitte NICHT direkt mit Masse verbinden, die Schnittstelle kann dadurch beschädigt werden. Damit sind wir auch schon bei den Unterschieden zwischen Daten- und Steuerausgängen: Die Steuerausgänge sind hochohmig und können deshalb keine hohen Ströme liefern. Selbst für Geringstverbraucher reichen die entnehmbaren Ströme (ca. 0,5 mA) nicht aus. Die Datenausgänge können dagegen ca. 2 mA liefern, bevor die Spannung auf Werte unter 2,5 V zusammenbricht. Die Datenausgänge können damit eine Low-Current-LED zum Leuchten bringen (Vorwiderstand ca. 2,2 kOhm), bei den Steuerausgängen ist selbst das Illusion. Was können die Steuerausgänge überhaupt? Na, steuern; z.B. die Eingänge von A/D Wandlern oder sonstigen Digitalschaltungen.
Zu allen Werten beim Parallelport gilt: Die Unterschiede sind groß; die Werte können im individuellen Fall nach oben und unten abweichen.
8.1.1 Ausgänge bidirektional als Eingang nutzen |
Garantien gibt es beim Parallelport keine; aber: Wollen wir die Ausgänge als Eingänge nutzen und will der Port nicht so, wie wir wollen, können wir folgendes versuchen:
Und wie testen wir das alles? Genau: Mit dem Parallelport-Debugger (der mit dem dem kostenlosen Download).
8.2 Register und Pins der parallelen (Centronics) Schnittstelle im SPP-Modus | |||||||
Bit |
Wert |
Bezeichnung |
Pin |
Pegel, wenn Bit auf ... |
Beschreibung | ||
25 Pol |
Centronics |
0 |
1 | ||||
SPP Parallelport-Daten-Register (8 Ausgänge) |
Basisadresse + 0 (Offset 0) | ||||||
0 |
1 |
Daten 1 |
2 |
2 |
0 V |
+5 V |
|
1 |
2 |
Daten 2 |
3 |
3 |
0 V |
+5 V |
|
2 |
4 |
Daten 3 |
4 |
4 |
0 V |
+5 V |
|
3 |
8 |
Daten 4 |
5 |
5 |
0 V |
+5 V |
|
4 |
16 |
Daten 5 |
6 |
6 |
0 V |
+5 V |
|
5 |
32 |
Daten 6 |
7 |
7 |
0 V |
+5 V |
|
6 |
64 |
Daten 7 |
8 |
8 |
0 V |
+5 V |
|
7 |
128 |
Daten 8 |
9 |
9 |
0 V |
+5 V |
|
SPP Parallelport-Status-Register (5 Eingänge) |
Basisadresse + 1 (Offset 1) | ||||||
0 |
1 |
nicht verwendet |
- |
- |
- |
- |
|
1 |
2 |
nicht verwendet |
- |
- |
- |
- |
|
2 |
4 |
nicht verwendet |
- |
- |
- |
- |
|
3 |
8 |
Error |
15 |
32 |
0 V |
+5 V |
|
4 |
16 |
Select |
13 |
13 |
0 V |
+5 V |
|
5 |
32 |
Paper Empty |
12 |
12 |
0 V |
+5 V |
|
6 |
64 |
Acknowledge |
10 |
10 |
0 V |
+5 V |
|
7 |
128 |
Busy |
11 |
11 |
+5 V |
0 V |
|
SPP Parallelport-Steuer-Register (4 Ausgänge) |
Basisadresse + 2 (Offset 2) | ||||||
0 |
1 |
Strobe |
1 |
1 |
+5 V |
0 V |
|
1 |
2 |
Auto Feed |
14 |
14 |
+5 V |
0 V |
|
2 |
4 |
Init (Reset) |
16 |
31 |
0 V |
+5 V |
|
3 |
8 |
Select Input |
17 |
36 |
+5 V |
0 V |
|
4 |
16 |
Interrupt enable |
- |
- |
- |
- |
|
5 |
32 |
bidirektional |
- |
- |
- |
- |
nicht bei allen Schnittstellen wirksam |
6 |
64 |
nicht verwendet |
- |
- |
- |
- |
|
7 |
128 |
nicht verwendet |
- |
- |
- |
- |
|
Masse (GND) |
18-25 |
19-30 |
|
|
|
25 Pol Sub-D |
36 Pol Centronics |
Kupplung am Computer: |
Kupplung am Drucker: |
13 1 |
18 1 |
Stecker am Druckerkabel: |
Stecker am Druckerkabel: |
1 13 |
1 18 |
Sehr hilfreich für Versuche sind Verlängerungskabel für die Schnittstellenausgänge. Die Ausgänge der Schnittstellen liegen für unsere Zwecke ja etwas ungünstig. Dazu einige Stecker/Kabel/Widerstände, LEDs und einen Lötkolben und schon kann es losgehen. Wer nicht gleich löten will, kann sofort mit zwei Experimenten loslegen:
9.1 Einlesen einer Schalterstellung am Parallelport
Als "Schalter" biegen wir zwei Büroklammern auf. Eine stecken wir in den Pin 10 und eine in in den Pin 25. Dann starten wir lpt1_in.bas. Wenn sich die beiden Büroklammern berühren, müsste ein BEEP ertönen und die Anzeige auf "... Bit 6 = 0" wechseln. Sicherer ist es, statt der Büroklammern einen Widerstand von ca. 1kOhm zu benutzen. Damit bleibt die Schnittstelle auch heil, wenn wir versehentlich einen Datenausgang (Pin 2-9) erwischen.
9.2 LEDs an COM1 blinken lassen
Ein externes Analogmodem hat meist mehr oder weniger Status-LEDs. Die zeigen den Zustand genau der Statusleitungen an, deren Ansteuerung wir gelernt haben. Was und ob da was blinkt, hängt von den vorhandenen LEDs ab und wie die Leitungen miteinander verbunden sind. Alternativ können wir LEDs auch direkt anschließen. Wir brauchen mindestens einen Widerstand (so um 1 kOhm) und eine bis drei LEDs. Als Steuerprog nehmen wir comblink.bas.
Zum Schluss noch einige Quellcode-Beispiele, die sowieso noch auf meiner Homepage vor sich hinrosten:
relais2.bas einfaches Steuerprogramm für eine Relaiskarte am Parallelport
max192.bas Maxim 192 und 186 AD-Wandler über die serielle Schnittstelle auslesen
ltc1290.bas LTC1290 AD-Wandler von Linear-Technologies über die serielle Schnittstelle auslesen
ltc1290.txt ... und ein Infotext dazu.
Download aller Beispieldateien dieser Seite und mehr ... (msr.zip)
Das war's! Was Ihr daraus macht, bleibt Eurer Fantasie überlassen. Wer die passende und preiswerte Hardware sucht, kann z.B. meine Einfach-Relaisplatine für ca. 5 Euro selberbauen.
|
© Frank Steinberg |