Das eBook Angewandte Mikroelektronik wurde von Hans Lohninger zur Unterstützung verschiedener Lehrveranstaltungen geschrieben. Weitere Informationen finden sie hier.


Z80-DART

Die folgenden Experimente beruhen auf einer interruptgesteuerten Ein- und Ausgabe von Zeichen auf der seriellen Schnittstelle. Dies hat den Vorteil, dass die Programme zur Bedienung der seriellen Schnittstelle sehr einfach aufgebaut sind, da die Verwaltung des Schnittstellenbausteins (DART) wegfällt. Aus der Sicht der Anwenderprogramme reduziert sich also der Aufwand zum Senden und Empfangen von Zeichen auf der seriellen Leitung auf den Aufruf von je einem Unterprogramm (RDV24A und WRV24A für den Kanal A des DART bzw. RDV24B und WRV24B für Kanal B). Der Aufwand in den Interruptroutinen ist dafür etwas höher. Die folgende Beschreibung soll kurz zeigen, wie die interruptgesteuerte Ein- und Ausgabe funktioniert.

Empfangen von Zeichen

Die zentrale Datenstruktur zum interruptgesteuerten Empfang von Zeichen ist ein Eingangspuffer, der als FIFO organisiert ist. Für jede serielle Schnittstelle existiert ein solcher Puffer (VARDBF, VBRDBF). Wird ein Signal auf der seriellen Schnittstelle empfangen, so sendet der DART einen Interrupt an die CPU. Die Interruptroutine (GETICA für DART-A bzw. GETICB für DART-B) liest nun das Zeichen aus dem Empfangsregister des entsprechenden DART-Kanals und schreibt dieses in den Eingangspuffer. Ein Anwenderprogramm kann nun asynchron zu den Interrupts die Zeichen aus dem Empfangspuffer mit Hilfe der Prozedur RDV24A (bzw. RDV24B) lesen.

Im Folgenden sind die interruptgesteuerte Empfangsroutine (GETICA) und die Leseroutine (RDV24A) für den Kanal A des DART abgedruckt. Für den Kanal B existieren ähnliche Routinen (siehe Source-Listing im Anhang).

;===================================================
;------ INTERRUPT: receiver DART-A full ------------
;===================================================
;
            .GLOBAL GETICA
GETICA:     PUSH    AF
            PUSH    HL
            PUSH    DE
            PUSH    BC
            IN      A,(DARTAD)  ;Zeichen einlesen
;
$5:         LD      HL,CNTRLA
            DEC     (HL)        ;Control-Bearbeitung
            INC     (HL)        ;  ein ?
            JR      Z,$2
;
            IFA.NE. 'S'-40H,$3  ;^S ?
            LD      HL,STPOTA
            LD      (HL),TRUE   ;Ausgang stoppen
            JR      $1
;
$3:         IFA.NE. 'Q'-40H,$6  ;^Q ?
            LD      HL,STPOTA
            LD      (HL),FALSE  ;Ausgang starten
            CALL    TRMDTA
            JR      $1
;
$6:         IFA.EQ. 'C'-40H,$4  ;^C ?
;
$2:         LD      HL,VARDBF   ;Zeichen in FIFO
            CALL    WRFIFO
            LD      HL,VARDBF   ;RTS gesetzt ?
            CALL    TSTFIF
            CP      0FAH        ;mehr als 250 Zeichen
            JR      C,$1        ;  im Puffer ?
            LD      A,5
            OUT     (DARTAC),A
            LD      A,(DAREG5)
            RES     1,A
            LD      (DAREG5),A
            OUT     (DARTAC),A  ;RTS rücksetzen
$1:         POP     BC
            POP     DE
            POP     HL
            POP     AF
            EI
            RETI
;
$4:         LD      HL,WARM     ;Warmstart
            PUSH    HL
            LD      HL,STPOTA   ;Ausgang ein
            LD      (HL),FALSE
            EI
            RETI
;
;===================================================
;----- read character from DART A ------------------
;===================================================
;
;ENTRY:     -
;EXIT:      CF = 1, falls kein Zeichen vorhanden
;           CF = 0, falls Zeichen gültig
;           Zeichen in Akkumulator
;
            .GLOBAL RDV24A
RDV24A:     PUSH    HL
            PUSH    BC
            LD      HL,VARDBF   ;RTS gesetzt
            CALL    TSTFIF
            CP      100         ;weniger als 100
            JR      NC,$1       ;  Zeichen im Puffer ?
            LD      A,5
            OUT     (DARTAC),A
            LD      A,(DAREG5)
            SET     1,A
            LD      (DAREG5),A
            OUT     (DARTAC),A  ;RTS rücksetzen
$1:         LD      HL,VARDBF
            CALL    RDFIFO
            POP     BC
            POP     HL
            RET

Nach dem Einlesen des Zeichens vom DART wird überprüft, ob eine Bearbeitung von Steuerzeichen erwünscht ist. Wenn dies nicht der Fall ist, wird das Zeichen in den Empfangspuffer geschrieben und die Interruptroutine beendet. Bei gewünschter Bearbeitung von Steuerzeichen (Variable CNTRLA = TRUE) wird geprüft, ob das empfangene Zeichen ^Q, ^S oder ^C ist. Darauf werden entsprechende Aktionen gesetzt. ^S und ^Q dienen zur Steuerung des Datenflusses auf dem Transmitter der Schnittstelle, ^C dient als Steuerzeichen für einen Warmstart.

Achtung! Die Steuerzeichen ^S und ^Q sind nicht für Software-Handshake vorgesehen, sie sind lediglich zur Bequemlichkeit des Benutzers implementiert, um lange Ausgaben stoppen zu können. Zur Steuerung des Datenstroms ist Hardware-Handshaking vorgesehen (Leitungen RTS und CTS). Dazu wird die Leitung RTS aktiviert, wenn mehr als 250 Zeichen im Empfangspuffer sind. RTS wird deaktiviert, wenn weniger als 100 Zeichen im Puffer sind. Durch dieses Verfahren wird der ankommende Datenfluss erst gestoppt, wenn der Empfangspuffer überzulaufen droht. Nachdem der Sender gestoppt worden ist, darf er erst wieder senden, wenn nur mehr 100 Zeichen im Puffer sind. Der Puffer wird durch die Routine RDV24A geleert.

Senden von Zeichen

Das Senden von Zeichen auf der seriellen Schnittstelle erfolgt ebenfalls über ein FIFO, das asynchron mit Zeichen gefüllt wird (WRV24A) und aus dem die Zeichen per Interrupt abgeholt werden (PUTICA). Das folgende abgedruckte Programm zeigt die beiden für die Verwaltung des Senders der Schnittstelle DART-A erforderlichen Programme (WRV24A und PUTICA).

;===================================================
;------ INTERRUPT: Zeichen auf DART-A senden -------
;===================================================
;
PUTICA:     CALL    TRMDTA      ;ein Zeichen senden
            EI
            RETI
;
            .GLOBAL TRMDTA
TRMDTA:     PUSH    AF
            PUSH    HL
            IFTRUE  STPOTA,$1   ;^S ?
            LD      HL,VAWRBF
            CALL    RDFIFO
            JR      C,$2
            OUT     (DARTAD),A  ;Zeichen ausgeben
$1:         POP     HL
            POP     AF
            RET
;
$2:         LOAD    USOTLA,TRUE
            LD      A,1         ;Interrupt abschalten
            OUT     (DARTAC),A
            LD      A,(DTAWR1)
            RES     1,A
            LD      (DTAWR1),A
            OUT     (DARTAC),A
            JR      $1
;
            .DATA
DTAWR1: DEFB        0           ;Interrupt DART A
            .CODE
;
;===================================================
;---- Ausgabe eines Zeichens auf DART-A ------------
;===================================================
;
;ENTRY: Zeichen in AKKU
;EXIT:      Zeichen in den Spooler-Puffer geschrieben
;
            .GLOBAL WRV24A
WRV24A:     PUSH    AF
            PUSH    HL
            PUSH    DE
$1:         LD      HL,VAWRBF   ;Spooler voll ?
            DI
            CALL    WRFIFO      ;Zeichen schreiben
            EI
            JR      C,$1        ;FIFO voll, warten
            DI
            IFFALSE USOTLA,$2       ;Spooler leer ?
            LOAD    USOTLA,FALSE            ;Spooler empty flag
            LD      A,1         ;  rücksetzen
            OUT     (DARTAC),A
            LD      A,(DTAWR1)
            SET     1,A
            LD      (DTAWR1),A
            OUT     (DARTAC),A
            CALL    TRMDTA      ;erstes Zeichen senden
$2:         EI
            POP     DE
            POP     HL
            POP     AF
            RET

Die Routine WRV24A übernimmt das zu sendende Zeichen und speichert es in einem FIFO (Variable VAWRBF) ab. Aus diesem Puffer werden die Zeichen von der interruptgesteuerten Routine PUTICA abgeholt und über den DART ausgegeben. Da der Sender des DART einen Interrupt erzeugt, nachdem ein Zeichen gesendet wurde, kann das erste Zeichen nicht über einen Interrupt gesendet werden. Die interruptgesteuerte Datenübertragung muss also erst durch ein erstes Zeichen gestartet werden. Dies geschieht in der Routine WRV24A, in dem ein Flag (Variable USOTLA) überprüft wird, das anzeigt, ob der Sender des DART aktiv ist. Falls dieser inaktiv ist, wird ein erstes Zeichen an den Sender ausgegeben und damit die weitere interruptgesteuerte Ausgabe gestartet.


Last Update: 2008-05-31