^

Programmierung der seriellen und parallelen Schnittstelle unter DOS

 

Frank Steinberg - http://www.FrankSteinberg.de - Version 24.06.2003.

Ich hab's verstanden, es kann also nicht so schwer sein. Ihr werdet's auch verstehen!

 Inhalt:

  1. Worum geht's hier, worum nicht?
  2. Welche Programmiersprache?
  3. Wie ermitteln wir die Basisadressen der Schnittstellen?
  4. Wie ist das 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 Elektrische Eigenschaften
    7.2 Tabelle der Register und Pins
    7.3 Steckerbelegung
  8. Die parallele (Centronics) Schnittstelle
    8.1 Elektrische Eigenschaften
    8.1.1 Ausgänge bidirektional als Eingänge nutzen
    8.2 Tabelle der Register und Pins
    8.3 Steckerbelegung
  9. Erste Versuche.

Habe ich was Falsches geschrieben? Bitte Mail an mich.

Download aller Beispieldateien dieser Seite und mehr ... (msr.zip)
 

1.  Worum geht's hier worum nicht?

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:

Zurück zum Inhalt
 

2.  Welche Programmiersprache?

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

IN Ziel, Adresse

IN AX, 2FEh

 

Turbo C

Wert = inportb (Adresse)
Wert = inport (Adresse)

DrStatus = inportb(0x379);
 

liest ein Byte
liest ein Bytepaar (Word)

Pacific C

Wert = inp (Adresse, Wert)

MStatus = inp(0x3FE)

 

Turbo Pascal

Wert := port [Adresse]
Wert := portw [Adresse]

DrStatus := port[$378+1];
 

liest ein Byte
liest ein Bytepaar (Word)

Basic

Wert = INP (Adresse)

MStatus% = INP(BasAdr%+6)

 

  

 So wird in einen I/O - Port geschrieben

Programmiersprache

 Anweisung

 Beispiel

 Bemerkung

Assembler

OUT Adresse, Quelle

OUT 378h, AX

 

Turbo C

outportb (Adresse, Wert)
outportw (Adresse, Wert)

outportb (0x378, 12);
outportw (SteuReg, 0xFFFF);

schreibt ein Byte
schreibt ein Bytepaar (Word)

Pacific C

outp (Adresse, Wert)

outp (0x2FB, MSteuReg)

 

Turbo Pascal

port [Adresse] := Wert
portw [Adresse] := Wert

port [$378] := 12;
portw [SteuReg] := $FFFF;

schreibt ein Byte
schreibt ein Bytepaar (Word)

Basic

OUT (Adresse, Wert)

OUT (&H378, 12)

 

Zurück zum Inhalt
 

3.  Wie ermitteln wir die Basisadressen der Schnittstellen?

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-
Adresse

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,
geht um 0:00 Uhr auf 0

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;

Zurück zum Inhalt
 

4.  Wie ist das mit den Bits und Bytes?

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:

Zurück zum Inhalt
 

4.1  Setzen einzelner Bits

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%)
ByteNeu% = ByteGelesen% OR 14
OUT Adresse%, ByteNeu%
oder ganz kurz:
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!

Zurück zum Inhalt
 

4.2  Löschen einzelner Bits

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%)
ByteNeu% = ByteGelesen% AND 248
OUT Adresse%, ByteNeu%
oder ganz kurz:
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.

Zurück zum Inhalt
 

4.3  Alternieren einzelner Bits

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%)
ByteNeu% = ByteGelesen% XOR 15
OUT Adresse%, ByteNeu%
oder ganz kurz:
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

Zurück zum Inhalt
 

4.4  Lesen einzelner Bits

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%)
VergleichsByte% = 64
IF ByteGelesen% AND VergleichsByte% = VergleichsByte% THEN
  PRINT "Bit 6 = 1"
 ELSE
  PRINT "Bit 6 = 0"
END IF
oder kürzer:
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.

Zurück zum Inhalt
 

5.  Ran an die Hardware!

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!

Zurück zum Inhalt
 

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%).

Zurück zum Inhalt
 

7.  Die serielle (RS 232) Schnittstelle

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.

Zurück zum Inhalt
 

7.3  Register und Pins der seriellen (RS 232) Schnittstelle

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

 

 

 

Zurück zum Inhalt
 

7.4  Steckerbelegung der seriellen Schnittstelle

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
+-------------+
 \ . . . . . /
  \ . . . . /
   +-------+
    
6     9

  1                          13
+-------------------------------+
 \ . . . . . . . . . . . . . . /
  \ . . . . . . . . . . . . . /
   +-------------------------+
   
14                       25

  5        1
+-------------+
 \ o o o o o /
  \ o o o o /
   +-------+
    
9     6

  13                         1
+-------------------------------+
 \ o o o o o o o o o o o o o o /
  \ o o o o o o o o o o o o o /
   +-------------------------+
   
25                       14

Zurück zum Inhalt
 

8.  Die parallele (Centronics) Schnittstelle

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.

Zurück zum Inhalt
 

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.

Zurück zum Inhalt
 

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:

  1. Manche Schnittstellen können an den Ausgängen nur lesen, wenn sie auf HIGH (+5V) gesetzt sind. Also erstmal die Bits im Daten- und Steuerregister entsprechend setzen.
  2. Bit 5 im Steuerregister setzen. Bei manchen Schnittstellen wird hier auf bidirektional umgestellt.
  3. Auch wenn die 8 Datenausgänge nicht bidirektional sind, können evtl. die 4 Steuer-Ausgänge (Steuer-Register; siehe Tabelle 8.2) als Eingang gelesen werden.
  4. Hat das auch nicht funktioniert, können wir versuchen, im Bios-Setup in den ECP- oder EPP-Modus umzuschalten. Da sollten die Datenleitungen in jedem Fall bidirektional sein. Mit beiden Modi habe ich aber keine Erfahrungen.

Und wie testen wir das alles? Genau: Mit dem Parallelport-Debugger (der mit dem dem kostenlosen Download).

Zurück zum Inhalt
 

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

 

 

 

Zurück zum Inhalt
 

8.3  Steckerbelegung der parallelen Schnittstelle

25 Pol Sub-D

36 Pol Centronics

Kupplung am Computer:

Kupplung am Drucker:

  13                         1
+-------------------------------+
 \ o o o o o o o o o o o o o o /
  \ o o o o o o o o o o o o o /
   +-------------------------+
   
25                       14

    18                                 1
+-------------------------------------------+
 \   I I I I I I I I I I I I I I I I I I   /
  \                                       /
   \ I I I I I I I I I I I I I I I I I I /
    +-----------------------------------+
    
36                                 19

Stecker am Druckerkabel:

Stecker am Druckerkabel:

  1                          13
+-------------------------------+
 \ . . . . . . . . . . . . . . /
  \ . . . . . . . . . . . . . /
   +-------------------------+
   
14                       25

     1                                 18
+-------------------------------------------+
 \                                         /
  \  I I I I I I I I I I I I I I I I I I  /
   \                                     /
    +-----------------------------------+
    
19                                 36

  Zurück zum Inhalt

 

9.  Erste Versuche

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.

Zurück zum Inhalt


Zur Startseite

 

Haftungsausschluss    Impressum

© Frank Steinberg