|
Programmierung der seriellen und parallelen Schnittstelle unter DOS |
|
Frank Steinberg - http://www.franksteinberg.de - Version 27.12.2001. |
Ich hab es verstanden, es kann also nicht so schwer sein. Ihr werdet es auch verstehen!
1. Worum geht es hier, worum nicht?
2. Welche Programmiersprache?
3. Wie ermitteln wir die Basisadressen der
Schnittstellen?
4. Wie ist da mit den BITS und BYTES?
4.1 Setzen einzelner BITS
4.2 Löschen einzelner BITS
4.3 Alternieren einzelner BITS
4.4 Lesen einzelner BITS
5. Ran an die Hardware!
6. Wie ermitteln wir die Registeradressen?
7. Die serielle (RS 232) Schnittstelle
7.1 Tabelle der Register und PINS
7.2 Steckerbelegung
8. Die parallele (Centronics) Schnittstelle
8.1 Tabelle der Register und PINS
8.2 Steckerbelegung
9. Erste Versuche
Habe ich was Falsches geschrieben? Bitte Mail an +fst+@nexgo.de.
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 (allerdings erfolgreiche) Versuche
unter Win 3.1 mit DLLs, die die Prozeduren zur Ansteuerung der Hardware
beinhalten, bin ich bisher nicht hinausgekommen; also Ende dieses Themas.
>> (Siehe: Werner-von-Siemens-Schule Schüler des Fachgymnasium Informationstechnik und der Technischen Assistenten für Informationstechnik veroeffentlichen wie es geht).
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, aber darauf kann man sich nicht verlassen.
Wie kommt man nun elegant an die richtigen I/O-Adressen ran? Man kann 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 mitByteWert
:=
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
mitmem
[
SegmentAdresse:OffsetAdresse
] := ByteWert;
.
bzwmemw
[
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, erst mal 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 so etwas macht. Am einfachsten geht das mit 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"
oderIF 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 oderPRINT 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 und OR aus. Wir werden damit jetzt folgende drei 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 noch 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 |
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; alles Taco.
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 niedrig wertigen 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 IFIF 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. 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
COM1MStatusRegByte% = INP (&H2F8 + 6)
oder
MStatusRegByte% = INP (&H2FE)
für
COM2PPStatusRegByte% = 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
COM1OUT &H2F8+4, MSteuerByte%
oder
OUT &H2FC, MSteuerByte%
für
COM2OUT &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.
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!
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 |
Bei der parallelen Schnittstelle kann das Datenregister (Offset 0)
bidirektional sein, d.h. auch Daten lesen können. Bitte beim Testen die Ausgänge
nicht direkt mit Masse verbinden, sondern über einen Widerstand von von ca. 330
Ohm.
Die 4 Ausgänge des Parallelport-Steuerregisters (Offset 2) sollen so
gut wie immer bidirektional sein. Das habe ich nicht überprüft.
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,5 - 5,1 V!
Die 5 Eingänge des Parallelport-Statusregisters (Offset 1) führen teilweise eine eigene Spannung (gemessen 0,85 - 5V). Bei meinem Pentium 100 ist das bei allen 5 Eingängen der Fall, bei den älteren Computern nur "Acknowledge" (Bit 6). Eingänge mit eigener Spannung kehren sofort in den Zustand zurück, der für einen High-Pegel vorgesehen ist, wenn das Signal abgeklemmt wird. Bit 6 geht auf 0, wenn der zugehörige Pin mit Masse verbunden wird. Wird der Masseschluss geöffnet, springt es auf 1 zurück. Bei den Eingängen ohne eigene Spannung bleibt der Zustand (quasi bistabil) bestehen. Erst wenn ein High-Pegel angelegt wird, geht das Bit auf 1. Welche Eingänge Spannung führen, kann man einfach mit einem Voltmeter messen.
8.1 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 |
Datenbit 0 |
2 |
2 |
0 V |
+5 V |
|
1 |
2 |
Datenbit 1 |
3 |
3 |
0 V |
+5 V |
|
2 |
4 |
Datenbit 2 |
4 |
4 |
0 V |
+5 V |
|
3 |
8 |
Datenbit 3 |
5 |
5 |
0 V |
+5 V |
|
4 |
16 |
Datenbit 4 |
6 |
6 |
0 V |
+5 V |
|
5 |
32 |
Datenbit 5 |
7 |
7 |
0 V |
+5 V |
|
6 |
64 |
Datenbit 6 |
8 |
8 |
0 V |
+5 V |
|
7 |
128 |
Datenbit 7 |
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 |
eigene Spannung (0,85 - 5 V) s.o. |
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 |
nicht verwendet |
- |
- |
- |
- |
|
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.
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)