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!

 Inhalt:

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)
 

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:

 

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

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)

 

 

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, 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-
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;

 

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, 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"  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 und OR aus. Wir werden damit jetzt folgende drei Aufgaben lösen:

 

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

 

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; alles Taco.

 

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 niedrig wertigen 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

 

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.

 

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

 

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.

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!

 

7.1  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

 

 

 

 

7.2  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

 

8.  Die parallele (Centronics) Schnittstelle

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

 

 

 

 

8.2  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

 

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.

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)

zurueck zur WvSS