8 MCS BASIC-52


Der bekannte Mikrocontroller 8052AH-BASIC von Intel enthält einen kompletten 8-K-großen BASIC-Interpreter im internen ROM. Zum Betrieb werden in der Minimalkonfiguration ein RAM von 2K und ein Adreßlatch sowie Leitungstreiber und -empfänger für die serielle Schnittstelle benötigt. Der 8052AH-BASIC eignet sich damit zum Aufbau sehr kleiner und preiswerter Systeme. Die folgende Tabelle zeigt die Pinbelegung des Mikrocontrollers. Gegenüber dem 8052 unterscheiden sich einige Portanschlüsse durch zusätzliche Sonderfunktionen:

P1.0:  T2, Zählereingang für den zusätzlichen Timer 2 des 8052
P1.1:  T2EX, Eingang zur Torsteuerung von Timer 2
P1.3:  PWM-Ausgang für den PWM-Befehl des BASIC-52
P1.4:  /ALE-Disable, wird zur EPROM-Programmierung benötigt
P1.5:  /Programm-Impuls zur EPROM-Programmierung (PROG-Befehl)
P1.6:  /DMA-Acknowledge, für die DMA-Funktion des BASIC
P1.7:  Serieller Druckerausgang für PRINT#-Befehle

P3.0:  RXD, serieller Eingang vom PC
P3.1:  TXD, serieller Ausgang zum PC
P3.2:  /INT0 /DMA-Request, für BASIC-DMA-Funktion
P3.3:  /INT1, Interrupt-Eingang für ONEX1-Befehl
P3.4:  T0
P3.2:  T1
P3.1:  /WR
P3.0:  /RD

 

Die folgende Übersicht der wichtigsten Befehle und Funktionen des BASIC-52 zeigt, daß es sich um ein hochentwickeltes System handelt, dessen Sprachumfang kaum hinter weit größeren BASIC-Interpretern zurücksteht. Zahlreiche Sonderfuntionen sind speziell an die Umgebung des Mikrocontrollers angepaßt.

 

Kommandos:

RUN Ctrl-C CONT LIST LIST# LIST@ NEW

Operatoren:

+ - / * = > >= < <= <> .AND. .OR. .XOR. ABS() NOT() INT() SGN() SQR() RND LOG() EXP() SIN() COS() TAN() ATN()

Statements:

CALL DATA READ RESTORE DIM DO-WHILE DO-UNTIL END FOR-TO-STEP NEXT GOSUB ON-GOTO ON-GOSUB IF-THEN-ELSE INPUT LET ONERR PRINT REM STOP

Erweiterte Statements des BASIC-52:

BAUD Baudrate für List#, Print#
ONEX1 Unterprogrammaufruf nach Interrupt 1
ONTIME Timer-Interruptaufruf
RETI Ende eines Interrupt-Unterprogramms
PH0., PH1. Ausgabe einer Hexadezimalzahl ohne/mit Nullstellen
PH0.#, PH1.#,
PRINT#, LIST# Serielle Ausgabe über P1.7
PUSH, POP Daten zum, vom Argument-Stack
PWM Pulsweitenmodulation über Port 1.4
STRING Speicher für Textstrings reservieren
UO1, UO0 User-Output aktiv/inaktiv
IDLE Warten auf Interrupt

Spezialfunktions-Opreratoren und Systemvariablen:

CBY() DBY() XBY() GET IE IP PORT1 PCON RCAP2 T2CON TCON TMOD TIME TIMER0 TIMER1 TIMER2 PI XTAL MTOP LEN FREE

 

Der 8052AH-BASIC läßt sich problemlos im Enwicklungssystem ES51 nach Abb. 6.4 einsetzen. Jumper 1 muß dabei gesetzt sein, um das interne ROM des Controllers zu aktivieren. Abb. 8.1 zeigt das Gesamtsystem mit einem zusätzlichen LCD-Display und dem AD-Wandler MAX186. Port P1 bleibt hier für eigene Zwecke frei. Einige der Sonderfunktionen, wie z.B. das Brennen von BASIC-Programmen in ein EPROM oder die DMA-Funktion des BASIC sind in diesem System allerdings nicht nutzbar.

Abb. 8.1 Das BASIC-Board auf der Basis des ES51

Der Controller benötigt zu seinem Betrieb mindestens 2 Kilobyte Daten-RAM ab Adresse 0000. Die hier bereitgestellten 32 K werden ebenfalls erkannt und sind als Programm- und Datenspeicher im BASIC voll nutzbar. BASIC-Programme werden aus der Sicht des Controllers als Daten abgelegt, wie es bei jedem Interpretersystem üblich ist. Da das gesamte RAM in diesem System auch als Programmspeicher im eigentlichen Sinne ansprechbar ist, lassen sich Maschinen-Unterprogramme schreiben und vom BASIC ausaufrufen.

Zum Betrieb des BASIC-Interpreters wird ein Terminalprogramm benötigt, über das Kommandos und BASIC-Prorammzeilen eingegeben werden und Ausgaben empfangen werden können. Für erste Versuche genügt z.B. das folgende kleine Terminalprogramm in QBasic. Beim Öffnen der Schnittstelle muß beachtet werden, daß BASIC mit dem OPEN-Kommando die Handshakeleitungen RTS und DTR hochsetzt und damit einen RESET des Prozessors auslöst. Beide Leitungen werden daher in Zeile 30 zurückgesetzt.

 

10 REM Mini-Terminal für BASIC-52 (TERMINAL.BAS)
20 OPEN "COM2:9600,N,8,1,CS,DS" AS #1
30 OUT (&H2FC),8 :REM RTS und DTR zurücksetzen
40 A$=INKEY$
50 IF A$ <> "" THEN PRINT#1,A$;
60 IF LOC(1) > 0 THEN B$ = INPUT$(1,#1): PRINT B$;
70 GOTO 40

 

Nach dem Neustart oder einem Reset erwartet der 8052AH-BASIC ein Leerzeichen, um sich auf die Baudrate des Terminals einzustellen. Er sendet dann seine Einschaltmeldung:

*MCS-51(tm) BASIC V1.1*
READY
>

Das MCS BASIC-52 verwendet den zusätzlichen Timer 2 des 8052 als Baudratengenerator. Im Gegensatz zu den Timern 0 und 1 des 8051 erhält Timer 2 die ungeteilte Taktfrequenz des Quarzosillators, hier also 11,0592 MHz. Das ermöglicht größere Teilerfaktoren und damit eine größere Flexibilität der Quarzfrequenzen. Nach einem Reset stellt BASIC-52 die Baudrate des angeschlossenen Terminals fest, indem es eine Impulslängenbestimmung des ersten gesendeten Zeichens vornimmt. Dabei muß es sich um ein Leerzeichen (ASCII 20h) handeln. Zusammen mit dem Startbit enthält es als erstes einen Impuls mit einer Länge von sechs Bitlängen. Dieser erste Impuls wird ausgemessen und damit der erforderliche Teilerfaktor für den Timer 2 bestimmt. So können im Prinzip beliebige Quarzfrequenzen und Baudraten verwendet werden. Das System geht standardmäßig von einem Quarz mit 11,0592MHz aus. Andere Frequenzen sollten dem BASIC-52 über den XTAL-Operator mitgeteilt werden, damit die interne Uhr und die zusätzliche serielle Ausgaberoutine korrekt ablaufen können.

Der automatisch eingestellte Teilerfaktor für Timer 2 kann mit dem Operator RCAP2 erfragt werden. Bei einer Übertragungsgeschwindigkeit von 9600 Baud und einer Taktfrequenz von 11,0592MHz ergibt PRINT RCAP2 das Ergebnis 65500. Das entspricht 65536-65500=36. Es werden also jeweils 36 Taktzyklen bis zum Überlauf gezählt. Da der interne Zähler der seriellen Schnittstelle dieses Signal durch 32 teilt, ergibt sich eine Bitrate von genau 9600 Baud.

Nach dem Einschalten und der Einstellung der Baudrate meldet das BASIC-52 seine Bereitschaft. Nun können in gewohnter Weise BASIC-Zeilen eingegeben und durch RUN gestartet werden. Ein erstes kleines Testprogramm könnte z.B. den Ausgabeport P1 ansprechen:

 

10 REM Portausgaben (TEST1.BAS)
20 FOR N=0 TO 255
30 PORT1=255-N
40 FOR I=1 TO 200 : NEXT I
50 NEXT N
60 GOTO 20
 

Ein übliches Terminalprogramm sendet jedes Zeichen von der Tastatur direkt an den Mikrocontroller. Alle Zeichen werden dort zunächst in einem Eingabepuffer mit einer Länge von 79 Zeichen gesammelt und erst nach <RETURN> ausgewertet. Jeder Fehler macht es leider erforderlich, die gesamte Zeile neu einzugeben. Um die Arbeit mit BASIC-52 etwas zu erleichtern, wurde das kleine Editor- und Terminalprogramm BASEDIT entwickelt.

BASEDIT hat im Grundmodus zwei Textfenster (vgl. Abb. 8.2). Im oberen Fenster arbeitet ein einfacher Texteditor mit vielen Editierfunktionen. Ins untere Fenster werden alle vom Mikrocontroller gesendeten Zeichen geschrieben. Jedesmal, wenn im Editor ein <RETURN> getippt wird, wird die komplette Zeile an den Controller geschickt. Sein Echo erscheint dann im Terminalfenster. Der Benutzer kann jede Zeile vor der Übertragung beliebig editieren. Dies gilt auch für Zeilen, die bereits weiter oben im Text stehen, und die nachträglich noch einmal geändert werden sollen. Im Terminalfenster läßt sich jeweils beobachten, ob eine Zeile angenommen wurde oder eine Fehlermeldung auslöst.

Abb. 8.2 Editier- und Ausgabefenster in BASEDIT.EXE

Der Editor arbeitet immer im Einfügemodus. RETURN innerhalb einer Zeile führt aber nicht wie in der Textverarbeitung üblich zu einem Teilen der Zeile, sondern der Cursor springt nur an den Anfang der nächsten Zeile. Der Cursor kann beliebig mit den Pfeiltasten, mit PgUp und PgDn sowie Home und End verschoben werden. Insgesamt können 512 Zeilen bearbeitet werden.

Spezielle Funktionen des Programms lassen sich über die Funktionstasten F1 bis F8 aufrufen:

F1 Hilfefunktion: Es erscheint ein Fenster mit einer Kurzübersicht der BASIC-Befehle.
F2 Save: Das Programm im Editor wird unter einem wählbaren Dateinamen gespeichert.
F3 Load: Ein Programm wird von der Diskette sowohl in den Editor als auch in den Controller geladen.
F4 List: Der Programmtext wird aus dem Controller in den Editor übertragen.
F5 Insert: Eine leere Zeile wird in den Text eingefügt.
F6 Zoom: Es wird ein bildschirmfüllendes Terminalfenster geöffnet, in dem alle Ausgaben des Controllers erscheinen. Eingaben werden direkt weitergeleitet.
F7 RUN: Das Programm wird mit "RUN" gestartet.
F8 STOP: Das Programm wird mir CTRL-C unterbrochen.

Natürlich können neben Programmzeilen auch Direktkommandos wie NEW, LIST, RUN usw. eingeben werden. Zum Testen können auch direkte Abfragen erfolgen wie z.B. PRINT PORT1. Ein Besonderheit des Gesamtsystems ist es, daß geladene Programme schon im Controller vorhandene Programme nur insoweit überschreiben, wie sie gleiche Zeilennummern ersetzen. Man kann daher eine Sammlung von Unterprogrammen anlegen, die bei Bedarf hinzugeladen werden. Um ganz neu anzufangen, muß vor dem Laden eines Programms NEW eingegeben werden.

 

 

 

8.1 BASIC52 im Direktmodus

Der 8052AH-BASIC läßt sich nicht nur als programmierbarer Mikrocontroller, sondern auch als "passives" Interface einsetzen. Dabei verwendet man den Direktmodus des Controllers. Eine Aufforderung wie z.B. PRINT PORT1 auf der Kommandozeilenebene führt zu einer direkten Antwort, wobei hier der Portzustand von Port P1 gelesen und zurückgegeben wird. Zahlreiche Aktionen lassen sich daher von einem PC-Programm aus durchführen, das Kommandos absetzt und die Antwort des Controllers auswertet. Dieses Verfahren ist zwar nicht besonders schnell, hat jedoch einige Vorteile: Der Anwender kann ein Mikrocontroller-Interface nutzen, ohne selbst einen Mikrocontroller oder ein EPROM programmieren zu müssen. Das folgende kleine PASCAL-Programm demonstriert den Datenaustausch zwischen PC und BASIC-52. Jedes Kommando wird zeichenweise gesendet, wobei jedesmal das Echo des BASIC-52 abgewartet wird. Am Ende der Zeile sendet das BASIC CR und LF. Bei Kommandos ohne Werterückgabe wie z.B. PORT1=255 meldet sich das BASIC-52 mit dem Zeichen > zurück. In den anderen Fällen sendet das BASIC die Anwort als Textstring, gefolgt von CR, LF und dem Bereitschaftzeichen >.

Program Basic_Direktmodus;       {BASDIREK.PAS}
Uses DOS,CRT,COM2_96;

var  n : Word;

procedure leeren;
var dummy,n : Byte;
begin
  for n:= 1 to 3 do begin
    delay(2);
    dummy := Port[BA];
  end;
end;

procedure Ausgabe (Zeile: String);
 var n: Integer;
     b: Byte;
begin
  leeren;
  for n:= 1 to length (Zeile) do begin
     sende (ord (Zeile [n]));
     b := Empfang;
  end;
  sende (13);
  repeat b:= Empfang until b= ord('>');
end;

function Abfrage (Zeile: String): Real;
 var n: Integer;
     b: Byte;
     Antwort : String;
     Ergebnis: Real;
begin
  leeren;
  for n:= 1 to length (Zeile) do begin
     sende (ord (Zeile [n]));
     b := Empfang;
  end;
  sende (13);
  for n:= 1 to 4 do b:=Empfang;
  Antwort := '';
  repeat
   b:= Empfang; {write (chr(b));}
   if (b>32) then Antwort := Antwort + chr(b);
  until b in [13,32];
  repeat b:= Empfang until b= ord('>');
  val (Antwort,Ergebnis,n);
  Abfrage := Ergebnis;
end;


begin
  init;
  Ausgabe ('PORT1 = 15');
  writeln (Abfrage ('PRINT PORT1'):3:0);
  Ausgabe ('PORT1= 255');
  Ausgabe ('PWM 20000,20000,100');
  repeat until KeyPressed;
end.


Das Hauptprogramm verwendet den Port P1 des Interfaces zum Schreiben und Lesen. Das PWM-Kommando wirkt auf das Bit 2 des Ports und dient zum Erzeugen einer genau definierten Folge von Rechteckimpulsen. Die angegebenen Parameter bedeuten: 20 000 Taktzyklen Highzustand, 20 000 Taktzyklen Lowzustand und 100 Impulse. Das PWM-Kommando läßt sich z.B. zur Tonerzeugung nutzen.

Das BASIC-52 verfügt über Funktionen zum Beschreiben und Lesen des Speichers. DBY zielt auf das interne RAM, XBY auf das externe RAM und CBY auf den internen Programmspeicher des Controllers. Damit ist es sehr einfach, eine Kopie des BASIC-52 auszulesen, um sie z.B. in ein EPROM zu brennen. Mit einem 80C32 läßt sich dann ein CMOS-System mit BASIC-52 aufbauen. Das Programm BASREAD.PAS nutzt den Direktmodus, um das Betriebssystem auszulesen und in die Datei BASIC52.BIN zu schreiben.

Program Basic_Ausleseprogramm;         {BASREAD.PAS}
Uses DOS,CRT,COM2_96;

var  n : Word;
     Parameter: String;
     b : Byte;
     f : file of Byte;

procedure leeren;
var dummy,n : Byte;
begin
  for n:= 1 to 3 do begin
    delay(2);
    dummy := Port[BA];
  end;
end;


function Abfrage (Zeile: String): Real;
 var n: Integer;
     b: Byte;
     Antwort : String;
     Ergebnis: Real;
begin
  leeren;
  for n:= 1 to length (Zeile) do begin
     sende (ord (Zeile [n]));
     b := Empfang;
  end;
  sende (13);
  for n:= 1 to 4 do b:=Empfang;
  Antwort := '';
  repeat
   b:= Empfang; {write (chr(b));}
   if (b>32) then Antwort := Antwort + chr(b);
  until b in [13,32];
  repeat b:= Empfang until b= ord('>');
  val (Antwort,Ergebnis,n);
  Abfrage := Ergebnis;
end;

begin
  init;
  sende (32);   {Basic initialisieren}
  delay (1000);
  leeren;
  assign (f,'BASIC52.BIN');
  rewrite (f);
  for n:= 0 to 8191 do begin
    str (n,Parameter);
    b:=lo(trunc(Abfrage ('PRINT CBY('+Parameter+')')));
    write (b,' ');
    write (f,b);
  end;
  close (f);
end.

 

 

8.2 Ansteuerung der LCD-Anzeige

Die Datenausgabe des BASIC-52 erfolgt normalerweise über das angeschlossene Terminal. Für eigenständige Anwendungen ohne ein Terminal ist manchmal eine Anzeige erforderlich. Oft verwendet man gemultiplexte LED-Anzeigen. Bequemer ist jedoch der Einsatz intelligenter LCD-Anzeigen mit eigenem Display-Controller. Sie enthalten bereits einen Zeichengenerator und können ohne großen Aufwand zur Ausgabe von ASCII-Zeichen veranlaßt werden.

Fast alle intelligenten LCD-Displays folgen heute einem gemeinsamen Standard. Hier wird ein Standardtyp mit 2*16 Zeichen eingesetzt. Das Display verfügt über folgende Anschlüsse:

Pin 14...Pin 7: Datenbus
Pin 6: E, Enable-Signal, aktiv high
Pin 5: R/W, 0 = Schreiben, 1 = Lesen
Pin 4: RS, 1= Daten, 0 = Kommandos
Pin 3: V0, Kontrasteinstellung 0...2V
Pin 2: VDD, +5V
Pin 1: VSS, 0V

Die Datenübertragung folgt dem Bus-Protokoll eines 6800-Prozessors: Zunächst muß durch die R/W-Leitung die Datenrichtung festgelegt werden, dann erfolgt der eigentliche Zugriff durch einen positiven Enable-Impuls. An einem 8051-Prozessor muß daher eine Verknüpfung des /RD- und des /WR-Signals erfolgen. Die Datenrichtungs-Umschaltung kann durch eine Adreßleitung erfolgen. Eine weitere Adreßleitung ist erforderlich, um die interne Registerselektion des Displaycontrollers über die Leitung RS vorzunehmen. Hier wird zwischen Daten und Kommandos unterschieden.

Abb. 8.3 Detailschaltbild zum Anschluß des LCD-Displays

Der Anschluß des Displays an das Systemboard ES51 erfolgt nach Abb. 8.3 durch eine sehr einfache Ansteuerung ohne Adreßdecoder. Die Display-Adressen erscheinen ab Adresse 8000h und werden mehrfach gespiegelt. Schreibzugriffe sind nur bei A1=0 erlaubt, weil mit A1=1 das Display seine Daten auf den Bus legt. Da /WR und /RD UND-verknüpft werden, würde ein Schreibbefehl auf einer Leseadresse zu einem Buskonflikt führen. Für die Ansteuerung ergeben sich nun folgende Adressen:

8000: Kommando schreiben
8001: Daten schreiben
8002: Kommando lesen
8003: Daten lesen

Das Display kennt eine Vielzahl von Kommandos, die jeweils mit RS=0 übergeben werden. Dabei wird zwischen Typen von Kommandos unterschieden, die jeweils eine charakteristische Anzahl von Nullbits in den höherwertigen Stellen besitzen.

                  7   6   5   4   3   2   1   0
+-----------------------------------------------+
Display löschen ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 1 ¦
+-----+-----+-----+-----+-----+-----+-----+-----¦
Cursor home     ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 1 ¦ x ¦
+-----+-----+-----+-----+-----+-----+-----+-----¦
verschieben     ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 1 ¦ID ¦ S ¦
+-----------------------------------------------+
(ID=1/0: rechts/links, S=1/0: ohne/mit Text)
+-----------------------------------------------+
Display, Cursor ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 1 ¦ D ¦ C ¦ B ¦
+-----------------------------------------------+
(D,C,B=1/0: Display, Cursor, Blinken An/Aus)
+-----------------------------------------------+
verschieben     ¦ 0 ¦ 0 ¦ 0 ¦ 1 ¦SC ¦RL ¦ x ¦ x ¦
+-----------------------------------------------+
(SC=1/0: Text/Cursor nach RL=1/0: rechts/links)
+-----------------------------------------------+
Initialisierung ¦ 0 ¦ 0 ¦ 1 ¦DL ¦ N ¦ x ¦ x ¦ x ¦
+-----------------------------------------------+
(DL=1/0: 8/4-Bit-Bus, N=1/0: beide/eine Zeile)
+-----------------------------------------------+
Zeichengenerator¦ 0 ¦ 1 ¦  Zeichen  ¦  Spalte   ¦
+-----+-----------------------------------------¦
Adresse         ¦ 1 ¦     Speicheradresse       ¦
+-----------------------------------------------+

Das Kommandoregister des Displays kann auch zurückgelesen werden. Es liefert dann sein Busy-Flag BF und die aktuelle Cursor-Position. Vor jedem Schreibzugriff auf das Display muß unbedingt BF überprüft werden. Nur wenn BF low ist, darf ein Kommando oder ein Datenbyte in das Display geschrieben werden, andernfalls kann es zu einer Zerstörung des Display-Controllers kommen.

+-----------------------------------------------+
Bereitschaft?   ¦BF ¦    Speicheradresse        ¦
+-----------------------------------------------+

 

Nach dem Einschalten müssen einige Initialisierungsbytes in das Kommandoregister geschrieben werden. Hier ein Beispiel:

Initialisierung mit 8-Bit-Datenbus und zwei Zeilen: 0011 1000 = 38h = 56

Display einschalten, Cursor ausschalten: 0000 1100 = 0Ch = 12

Display löschen: 0000 0001 = 01h = 1

Das Display enthält einen internen Datenzeiger, der den einzelnen Zeichenpositionen zugeordnet ist. Bei einem 2*16-stelligen Display gilt:

Zeile 1: Adresse 00h bis 0Fh
Zeile 2: Adresse 40h bis 4Fh

Der Cursor rückt mit jedem geschriebenen Zeichen automatisch vor, kann aber durch Setzen einer Adresse gezielt auf eine gewünschte Position gestellt werden.

Das folgende kleine BASIC-Programm stellt ein erstes Beispiel für eine einfache Ansteuerung dar. Das Programm verzichtet auf eine Überprüfung des Busy-Flags. Dies ist unproblematisch, solange die

Ansteuerung aus einem reinen BASIC-Programm relativ langsam erfolgt.

1      REM Zeichenausgabe auf dem LCD-Display   (LCD.BAS)
10     STRING 240,16
20     $(0)="Hallo Leute     "
30     GOSUB 1000
40     GOSUB 1300
50     GOSUB 1400
60     END 
1000   REM LCD-Reset
1010   XBY(8000H)=56
1020   XBY(8000H)=12
1030   XBY(8000H)=1
1040   RETURN 
1100   REM Cursor-Position 0
1110   XBY(8000H)=128
1120   RETURN 
1200   REM Zeichenausgabe
1210   XBY(8001H)=A
1220   RETURN 
1300   REM Obere Zeile
1310   XBY(8000H)=128
1320   FOR I=1 TO 16 : XBY(8001H)=ASC($(0),I) :  NEXT 
1330   RETURN 
1400   REM Untere Zeile
1410   XBY(8000H)=192
1420   FOR I=1 TO 16 : XBY(8001H)=ASC($(0),I) :  NEXT 
1430   RETURN 

 

Die direkte Ausgabe einzelner Zeichen im BASIC ist wenig komfortabel. Das BASIC-52 sieht jedoch eine Erweiterung in Form eines eigenen Treibers vor, mit dem PRINT-Befehle umgeleitet werden können. Der Anwender muß dazu eine Ausgaberoutine bereitstellen, die Zeichen aus dem Register R5 (Bank 0) liest und an die Ausgabe, hier das LCD-Display leitet. Durch das Kommando UO 1 läßt sich die Ausgabe auf den eigenen Treiber umlenken. Bei der Abarbeitung eines PRINT-Befehls wird vom System für jedes Zeichen einmal die Adresse 4030h angesprungen, wo ein Sprungbefehl auf das Ausgabeprogramm stehen muß.

Eine andere Möglichkeit, den eigenen Treiber zu benutzen, bietet der PRINT@-Befehl. Hier wird die Adresse 403Ch angesprungen, wo ebenfalls ein Sprungbefehl auf die Ausgaberoutine stehen sollte. Der eigene Treiber wird allerdings nur dann wirksam, wenn Bit 39 des Internen RAMs (Bit 7 in Adresse 24h) gesetzt wurde. Dies kann z.B. in der ohnehin erforderlichen Initialisierungsroutine für das Display erfolgen.

Das im folgenden vorgestellte Programm BAS52_IO.ASM enthält einen LCD-Treiber sowie einen Treiber für den AD-Wandler MAX186 und die weiter unten beschriebenen Befehlserweiterungen. BASIC52 stellt bereits zahlreiche Hilfen zu seiner externen Erweiterung bereit. Maschinen-Unterprogramme müssen folgende Regeln einhalten: Alle Register außer den acht Registern der Bank 3 (18h ...1Fh) und der Akku sowie der Datapointer müssen unverändert bleiben. Der Benutzer darf Bank 3 komplett für eigene Zwecke belegen.

Der LCD-Treiber sichert den Akku und den Datapointer auf dem Stack, um sie vor dem Rücksprung wieder zu restaurieren. Register 4 der Bank 3 führt die jeweilige Cursorposition. Bei einem CR wird der Cursor an den Anfang der aktuellen Zeile zurückgesetzt. Bei zweizeiligen Displays kann der Anwender den Cursor auf den Anfang der zweiten Zeile (Position 64) stellen. Für jeden Datenzugriff auf das Display wird über die Busy-Routine die Bereitschaft geprüft. Vor der ersten Verwendung des Treibers muß das Display durch Aufruf der Initialisierungsroutine (CALL 4050h) vorbereitet werden. BASIC-52 erlaubt kurze Aufrufe mit CALL 00, CALL 01, CALL 03 usw. bis CALL 127, die zu den Adressen 4100h, 4102h, 4104h usw. bis 41FEh geleitet werden. Entsprechende Sprungvektoren an diesen Adressen ermöglichen den vereinfachten Aufruf der LCD-Initialisierung (CALL 00), der Cursor-Routine und zusätzlich der weiter unten beschriebenen AD-Wandler-Routine für den MAX186. Der Cursor muß über einen zusätzlichen Parameter gesetzt werden:

CALL 427FH 0 oder kurz CALL 01 0

Die Cursor-Routine wertet einen hinter der CALL-Adresse stehenden Ausdruck aus, der auch eine Berechnung wie z.B. CALL 01 (64+4*N) enthalten kann. Weiteres zur Datenübergabe zwischen BASIC-52 und eigenen Maschinenprogrammen ist in Kap. 11 zu finden.

 

     ;8052-AH-Basic-Erweiterung: LCD-Treiber   (BAS52_IO.ASM)
4030                      .org  4030H
4030 02 42 00             ljmp  LCD        ;Vektor für UO 1
403C                      .org  403CH
403C 02 42 00             ljmp  LCD        ;Vektor für PRINT@
4100                      .org  4100H
4100 41 50                ajmp  LCDInit    ;Vektor für CALL 0
4102 41 7F                ajmp  CURSOR     ;für CALL 1
4104 61 00                ajmp  AD         ;für CALL 2

4200                      .org  4200H
4200 C0 83       LCD      push  DPH
4202 C0 82                push  DPL
4204 C0 E0                push  ACC
4206
4206 51 2E                acall Busy
4208 E5 1C                mov   A,28       ;Cusorposition
420A 44 80                orl   A,#128
420C 90 80 00             mov   DPTR,#8000H
420F F0                   movx  @DPTR,A    ;Cursor setzen
4210 51 2E                acall Busy
4212 E5 05                mov   A,05       ;Zeichen holen
4214 B4 0D 02             cjne  A,#0DH,J1  ;= CR?
4217 80 1D                sjmp  CR
4219 B4 0A 02    J1       cjne  A,#0AH,J2  ;= LF?
421C 80 09                sjmp  End
421E 90 80 01    J2       mov   DPTR,#8001H
4221 F0                   movx  @DPTR,A    ;Zeichen ausgeben
4222 E5 1C                mov   A,28       ;Bank3, R4, Cursorpos.
4224 04                   inc   A
4225 F5 1C                mov   28,A       ;Cursor erhöhen
4227 D0 E0       End      pop   ACC
4229 D0 82                pop   DPL
422B D0 83                pop   DPH
422D 22                   ret
422E
422E 90 80 02    Busy     mov   DPTR,#8002H
4231 E0                   movx  A,@DPTR
4232 20 E7 F9             jb    ACC.7,Busy
4235 22                   ret
4236
4236 51 2E       CR       acall Busy
4238 74 20                mov   a,#32
423A 90 80 01             mov   DPTR,#8001h
423D F0                   movx  @DPTR,a
423E E5 1C                mov   A,28
4240 04                   inc   A
4241 F5 1C                mov   28,a
4243 54 3F                anl   A,#63
4245 B4 28 EE             cjne  A,#40,CR
4248 E5 1C       J3       mov   a,28
424A 54 C0                anl   a,#192
424C F5 1C                mov   28,a
424E 80 D7                sjmp  End
4250
4250
4250 C0 83       LCDInit  push  DPH
4252 C0 82                push  DPL
4254 C0 E0                push  ACC
4256
4256 51 2E                acall Busy
4258 90 80 00             mov   DPTR,#8000H
425B 74 38                mov   A,#38H
425D F0                   movx  @DPTR,A
425E 51 2E                acall Busy
4260 90 80 00             mov   DPTR,#8000H
4263 74 06                mov   A,#06H
4265 F0                   movx  @DPTR,A
4266 51 2E                acall Busy
4268 90 80 00             mov   DPTR,#8000H
426B 74 0C                mov   A,#0CH
426D F0                   movx  @DPTR,A
426E 51 2E                acall Busy
4270 90 80 00             mov   DPTR,#8000H
4273 74 01                mov   A,#01H
4275 F0                   movx  @DPTR,A
4276 D2 27                setb  027H       ;PRINT@ freigeben
4278
4278 D0 E0                pop   ACC
427A D0 82                pop   DPL
427C D0 83                pop   DPH
427E 22                   ret
427F
427F C0 E0       CURSOR   push  ACC      ;Akku sichern
4281 74 39                Mov   A,#57
4283 12 00 30             lcall 030h     ;Ausdruck auswerten
4286 74 01                Mov   A,#1
4288 12 00 30             lcall 030h     ;als Integer in R3:R1
428B E9                   mov   A,R1     ;Startparameter holen
428C F5 1C                mov   28,A
428E D0 E0                pop   ACC      ;Akku wiederherstellen
4290 22                   ret

 

 

Der Displaytreiber kann z.B. ab der Adresse 4030h im EPROM stehen, wenn das EPROM über Jumper 2 aktiviert wurde. Ist Jumper 1 (EA) gesetzt, dann greift der Mikrocontroller in den unteren 8K automatisch auf das interne Interpreter-ROM zu, während Zugriffe auf höhere Adressen das externe EPROM verwenden. Zumindest in der Entwicklungsphase kann es aber sinnvoll sein, alle Maschinenroutinen im RAM zu testen. Dies ist bei offenem Jumper 1 möglich, da das gesamte RAM des Entwicklungssystems auch als Programmspeicher dient. Der BASIC-RAM-Bereich muß allerdings z.B. durch MTOP=8191 verkleinert werden, um Konflikte mit der systemeigenen Speicherverwaltung zu vermeiden. Das BASIC-Programm LCD2.BAS stellt den LCD-Treiber im RAM bereit:

3999   REM LCD-Treiber         (LCD2.BAS)
4000   MTOP=8191
4029   REM LCD-Vektoren
4030   DATA 002H,042H,000H,000H,000H,000H,000H,000H
4038   DATA 000H,000H,000H,000H,002H,042H,000H,000H
4039   FOR N=0 TO 15 :  READ D : XBY(04030H+N)=D :  NEXT N
4099   REM CALL-Vektoren
4100   DATA 041H,050H,041H,07FH,061H,000H,000H,000H
4101   FOR N=0 TO 7 :  READ D : XBY(04100H+N)=D :  NEXT N
4199   REM LCD
4200   DATA 0C0H,083H,0C0H,082H,0C0H,0E0H,051H,02EH
4208   DATA 0E5H,01CH,044H,080H,090H,080H,000H,0F0H
4210   DATA 051H,02EH,0E5H,005H,0B4H,00DH,002H,080H
4218   DATA 01DH,0B4H,00AH,002H,080H,009H,090H,080H
4220   DATA 001H,0F0H,0E5H,01CH,004H,0F5H,01CH,0D0H
4228   DATA 0E0H,0D0H,082H,0D0H,083H,022H,090H,080H
4230   DATA 002H,0E0H,020H,0E7H,0F9H,022H,051H,02EH
4238   DATA 074H,020H,090H,080H,001H,0F0H,0E5H,01CH
4240   DATA 004H,0F5H,01CH,054H,03FH,0B4H,028H,0EEH
4248   DATA 0E5H,01CH,054H,0C0H,0F5H,01CH,080H,0D7H
4250   DATA 0C0H,083H,0C0H,082H,0C0H,0E0H,051H,02EH
4258   DATA 090H,080H,000H,074H,038H,0F0H,051H,02EH
4260   DATA 090H,080H,000H,074H,006H,0F0H,051H,02EH
4268   DATA 090H,080H,000H,074H,00CH,0F0H,051H,02EH
4270   DATA 090H,080H,000H,074H,001H,0F0H,0D2H,027H
4278   DATA 0D0H,0E0H,0D0H,082H,0D0H,083H,022H,0C0H
4280   DATA 0E0H,074H,039H,012H,000H,030H,074H,001H
4288   DATA 012H,000H,030H,0E9H,0F5H,01CH,0D0H,0E0H
4290   DATA 022H
4291   FOR N=0 TO 144 :  READ D : XBY(04200H+N)=D :  NEXT N
4292   CALL 00H

 

Die Anwendung des LCD-Treibers ist relativ einfach. Im Normalfall wird die Ausgabe mit UO 1 umgeleitet. Dann wirken alle PRINT-Befehle auf das Display. Zusätzlich kann mit CALL 01 die Cursorposition verändert werden. Das Beispielprogramm LCDDEMO.BAS stellt den Zustand von Port P1 am Display dar. Zusätzlich wird ein Text ausgegeben. Mit jedem Zeilenende durch den PRINT-Befehl gelangt der Cursor wieder an den Anfang der aktuellen Zeile.

 

100    REM Anwendung des LCD-Treibers   (LCDDEMO.BAS)
110    UO 1 :  REM User Output freigeben
120    CALL 01H 0 :  REM Cursor auf Zeile 1
130    PRINT " PORT P1 = "
140    CALL 01H 64 :  REM Cursor auf Zeile 2
150    PRINT PORT1
160    GOTO 150
200    REM Hier LCD2.BAS hinzuladen

8.3 Verwendung des AD-Wandlers

Auf dem Entwicklungssystem ES51 kann der 12-Bit-Wandler MAX186 eingesetzt werden. Die Ansteuerung wurde bereits in Kap. 7.4 genau erläutert. Eine Verwendung in BASIC-Programmen eröffnet zahlreiche Möglichkeiten für spezielle Meßprogramme. Der Wandler wird hier vollständig von Leitungen des Ports P3 angesteuert, so daß der Port P1 frei bleibt. Port P3 ist aber durch keinen BASIC-Befehl ansprechbar, weil alle Leitungen auch Spezialfunktionen haben. Der Wandler kann also nur durch eine Maschinenroutine eingebunden werden, was ja wegen der seriellen Datenübertragung auch aus zeitlichen Gründen sinnvoll ist.

Das Programm BAS52_IO.ASM enthält eine geeignete Routine zur Ansteuerung des MAX186. Sie verarbeitet ein Steuerwort, das ihr vom aufrufenden BASIC-Programm übergeben wird, und liefert einen 12-Bit-Integerwert zurück. Das BASIC-52 bietet zahlreiche Hilfen der Einbindung eigener Routinen. So läßt sich z.B. ein Wert an die Routine übergeben, der im BASIC-Programm sogar in Form eines komplexen Ausdrucks stehen kann. Die Auswertung des Ausdrucks wird vom BASIC52 übernommen, wenn der Anwender geeignete Systemroutinen aufruft. Alle internen Funktionen des Systems werden mit CALL 030h aufgerufen, nachdem der Akku mit einem Steuerkommando geladen wurde. Hier werden die folgenden Funktionen benutzt:

57: Ausdruck auswerten
01: In Integer wandeln und in R3,R1 ablegen
157: Integer aus R2,R0 auf den Argument-Stack legen

Im BASIC wird die AD-Routine dann z.B. so aufgerufen:

10 CALL 4300H (206+16* Kanal) : REM AD-Wandler aufrufen
20 POP A : REM Wert abholen
30 PRINT A : REM Meßwert ausgeben

Das Maschinenprogramm ist voll relocatibel, weil durchgehend relative Sprungbefehle verwendet werden. Aus Gründen der günstigen Speichernutzung wird es hier hinter die LCD-Programme ab Adresse 4300h geschrieben. Das Programm entspricht dem MC51-Programm in Kap. 7.4.

      ;Ansteuerung des MAX186             (BAS52IO.ASM)
 4300 C0 E0       AD       push  ACC      ;Akku sichern
 4302 74 39                Mov   A,#57
 4304 12 00 30             lcall 030h     ;Ausdruck auswerten
 4307 74 01                Mov   A,#1
 4309 12 00 30             lcall 030h     ;als Integer in R3:R1
 430C E9                   mov   A,R1     ;Startparameter holen
 430D
 430D C2 B5                clr   0B5h     ;Steuerbyte zum Wandler
 430F 75 18 08             mov   18h,#08  ;Zähler: R1, Bank3
 4312 20 E7 04    S1       jb    ACC.7,S2
 4315 C2 B4                clr   0B4h     ;Di=0
 4317 80 02                sjmp  S3
 4319 D2 B4       S2       setb  0B4h     ;Di=1
 431B D2 B5       S3       setb  0B5h     ;Clk=1
 431D C2 B5                clr   0B5h     ;Clk=0
 431F 23                   rl    A        ;nächstes Bit
 4320 D5 18 EF             djnz  18h,S1
 4323
 4323 75 18 0A             mov   18h,#10  ;Warteschleife
 4326 D5 18 FD    S4       djnz  18h,S4
 4329
 4329 74 00                mov   A,#0     ;Highbyte auslesen
 432B 75 18 04             mov   18h,#4   ;4 mal
 432E D2 B5       S5       setb  0B5h     ;Clk-Impuls
 4330 C2 B5                clr   0B5h
 4332 23                   rl    A
 4333 30 B2 01             jnb   0B2h,S6  ;Do lesen
 4336 04                   inc   A
 4337 D5 18 F4    S6       djnz  18h,S5
 433A FA                   mov   R2,A     ;Highbyte in R2
 433B
 433B 74 00                mov   A,#0     ;Lowbyte lsen
 433D 75 18 08             mov   18h,#8   ;8 mal
 4340 D2 B5       S7       setb  0B5h     ;Clk-Impuls
 4342 C2 B5                clr   0B5h
 4344 23                   rl    A
 4345 30 B2 01             jnb   0B2h,S8  ;Do lesen
 4348 04                   inc   A
 4349 D5 18 F4    S8       djnz  18h,S7
 434C F8                   mov   R0,A     ;Lowbyte in R0
 434D
 434D 74 9A                mov   A,#154
 434F 12 00 30             lcall 030h     ;auf den Ergebnisstack
 4352 D0 E0                pop   ACC      ;Akku wiederherstellen
 4354 22                   ret

Der Treiber wird z.B. über das BASIC-Ladeprogramm AD.BAS in das RAM des Systems eingetragen.

 

 

4299   REM AD-Wandler MAX186               (AD.BAS)
4300   DATA 0F5H,019H,074H,039H,012H,000H,030H,074H
4308   DATA 001H,012H,000H,030H,0E9H,0C2H,0B5H,075H
4310   DATA 018H,008H,020H,0E7H,004H,0C2H,0B4H,080H
4318   DATA 002H,0D2H,0B4H,0D2H,0B5H,0C2H,0B5H,023H
4320   DATA 0D5H,018H,0EFH,075H,018H,00AH,0D5H,018H
4328   DATA 0FDH,074H,000H,075H,018H,004H,0D2H,0B5H
4330   DATA 0C2H,0B5H,023H,030H,0B2H,001H,004H,0D5H
4338   DATA 018H,0F4H,0FAH,074H,000H,075H,018H,008H
4340   DATA 0D2H,0B5H,0C2H,0B5H,023H,030H,0B2H,001H
4348   DATA 004H,0D5H,018H,0F4H,0F8H,074H,09AH,012H
4350   DATA 000H,030H,0E5H,019H,022H,000H,000H,000H
4351   FOR N=0 TO 87 :  READ  D: XBY(04300H+N)= D:  NEXT N

 

Zusammen mit der schon vorgestellten Erweiterung für das LCD-Display ergeben sich nun die folgenden CALL-Adressen:

LCD-Initialisierung: CALL 427FH oder CALL 00H
LCD-Cursor: CALL 427FH oder CALL 01H
AD-Wandler: CALL 4300H oder CALL 02H

Das folgende kleine Programm ADLCD.BAS verwendet die Erweiterung zum Aufbau eines Vierkanal-Voltmeters. Diesmal wird die Ausgabe nicht mit UO umgeleitet, sondern die Ergebnisse gelangen mit PRINT @ zum LCD-Display.

100    REM Vierkanal-Voltmeter        (ADLCD.BAS)
110    CALL 00H:   REM  LCD-Init
120    FOR N=0 TO 3
130    CALL 02H (128+64+16*N+14) :  REM AD, Kanal 1,3,5,7
140    POP D
150    IF N<2 THEN  CALL 01H (8*N):  REM Cursor
160    IF N>1 THEN  CALL 01H (64+8*(N-2)):  REM Cursor
170    PRINT @ D,"mV",
180    NEXT N
190    FOR I=1 TO 500 :  NEXT I
200    GOTO 120

 

 

8.4 BASIC-Befehlserweiterungen

Das BASIC-52 ist für komfortable Befehlserweiterungen vorbereitet. Der Benutzer kann also eigene BASIC-Schlüsselwörter festlegen und mit eigenen Maschinenprogrammen verbinden. Im Prinzip wird dabei ein Aufruf wie z.B. CALL 4300H 254 durch eine bessere Schreibweise wie z.B. AD 254 ersetzt. Die Erweiterungen umfassen Kommandos und Statements, denen Parameter übergeben werden können. Nicht möglich sind leider Funktionen, bei denen ein Wert zurückgeliefert wird. Als Hilfsmittel ist aber die Möglichkeit vorgesehen, mit einem Maschienprogramm eine Realzahl auf den sog. Argument-Stack zu legen, von wo sie mit dem BASIC-Befehl POP abgeholt werden kann.

Zum Erzeugen eigener Befehle sind die folgenden Schritte nötig: Der Benutzer muß das Byte 5Ah an die Adresse 2002h des Programmspeichers legen, um dem System die Erweiterung mitzuteilen. Zusätzlich muß an der Adresse 2048h ein Unterprogramm stehen, das Bit 45 des internen RAM setzt. An den Adressen 2070h und 2078h sind kurze Unterprogramme bereitzustellen, die den Datapointer jeweils auf den Anfang der Tabellen für Sprungvektoren und für Schlüsselworte stellen. Die Vektortabelle besteht aus einer Aneinanderreihung von Adressen. Die Tabelle der neuen Schlüsselworte enthält jeweils ein neues BASIC-Token (10h, 11h usw. bis 1Fh), das Schlüsselwort im ASCII-Text und ein Trennzeichen 00. Das letzte Wort der Liste wird von FFh gefolgt.

      ;BASIC-Befehlserweiterung        (BAS52_IO.ASM)
 2002                      .org  2002H
 2002 5A                   .byte 5AH       ;Erweiterung vorhanden
 2003
 2048                      .org  2048H
 2048 D2 2D                setb  45        ;Erweiterung aktiv
 204A 22                   ret
 204B
 2070                      .org  2070H
 2070 90 20 7C             MOV   DPTR,#VECTOR_TABLE    ;Vektortabelle
 2073 22                   ret
 2074
 2078                      .org 2078H
 2078 90 20 82             MOV  DPTR,#USER_TABLE       ;Schlüsselworte
 207B 22                   ret
 207C
 207C                          .msfirst          ;Highbyte - Lowbyte
 207C 42 50       VECTOR_TABLE .word LCDInit
 207E 42 7F                    .word CURSOR
 2080 43 00                    .word AD
 2082
 2082 10          USER_TABLE   .byte 10H       ;Basic-Token
 2083 4C4344494E49             .text "LCDINIT"      ;Schlüsselwort
 2089 54
 208A 00                       .byte 00H       ;end
 208B 11                       .byte 11H
 208C 435552534F52             .text "CURSOR"
 2092 00                       .byte 00H
 2093 12                       .byte 12H
 2094 41 44                    .text "AD"
 2096 FF                       .byte 0FFH      ;Tabellenende
 2097

 

Der Maschinencode der Befehlserweiterung läßt sich mit einigen BASIC-Zeilen in das RAM kopieren.

 

1000   REM Spracherweiterungen LCD und AD-Wandler  (TOKEN.BAS)
1010   MTOP=8191
1999   REM   0    1    2    3    4    5    6    7
2000   DATA 000H,000H,05AH,000H,000H,000H,000H,000H
2001   FOR N=0 TO 7 :  READ D: XBY(02000H+N)= D:  NEXT N
2048   DATA 0D2H,02DH,022H,000H,000H,000H,000H,000H
2049   FOR N=0 TO 7 :  READ D: XBY(02048H+N)= D:  NEXT N
2070   DATA 090H,020H,07CH,022H,000H,000H,000H,000H
2078   DATA 090H,020H,082H,022H,042H,050H,042H,07FH
2080   DATA 043H,000H,010H,04CH,043H,044H,049H,04EH
2088   DATA 049H,054H,000H,011H,043H,055H,052H,053H
2090   DATA 04FH,052H,000H,012H,041H,044H,0FFH,000H
2091   FOR N=0 TO 39 :  READ D: XBY(02070H+N)= D:  NEXT N

Die Spracherweiterung läßt sich ohne weiteres auch in einem EPROM unterbringen. Brennt man zusätzlich die unteren 8 K des BASIC-52-Systems in dasselbe 32-K-EPROM, dann läßt sich ein CMOS-System mit einem 80C32 aufbauen. Die Begleitdiskette enthält das komplette System in der Datei BASIC52X.BIN.

Das kleine Beispielprogramm ADLCD2.BAS demonstriert die Anwendung der neuen Befehlsworte LCDINIT, AD und CURSOR.

100    REM Vierkanal-Voltmeter        (ADLCD2.BAS)
110    LCDINIT 
120    FOR N=0 TO 3
130    AD (128+64+16*N+14) :  REM Kanal 1,3,5,7
140    POP D
150    IF N<2 THEN  CURSOR (8*N)
160    IF N>1 THEN  CURSOR (64+8*(N-2))
170    PRINT @ D,"mV",
180    NEXT N
190    FOR I=1 TO 500 :  NEXT I
200    GOTO 120


 

8.5 Meßwerterfassung mit Druckerausgabe

Der BASIC-52 verfügt über eine zweite, softwaremäßig realisierte serielle Schnittstelle zum Anschluß eines Druckers. Der Datenausgang liegt an P1.7 und muß durch einen Leitungstreiber invertiert werden. Dazu könnte man den noch freien Treiber im MAX232 einsetzen. Abb. 8.4 zeigt dagegen den Anschluß über einen einfachen Transistortreiber.

Abb. 8.4 Anschluß eines Druckers an den 8052AH-BASIC

Die Zeichenausgabe über die zweite serielle Schnittstelle erfolgt mit PRINT#. Über das BAUD-Kommando muß zuvor die Übertragungsrate eingestellt werden.

 

100    REM 4-Kanal-Messung und Ausgabe  (PRINTER.BAS)
110    BAUD 1200
120    TIME=0 :  CLOCK 1 :  REM Echtzeituhr starten
130    ZEIT=60 :  REM Messung nach 60 Sekunden
140    T=1 :  REM 1. Messung
150    DO  :  WHILE TIME<(ZEIT*T)
160    GOSUB 500
170    T=T+1
180    GOTO 150
500    REM Messung und Ausgabe
510    PRINT #T,"      ",
520    FOR N=0 TO 3
530    AD (128+64+16*N+14) :  REM Kanal 1,3,5,7
540    POP D
550    PRINT #D,
560    NEXT N
570    PRINT #"mV"
580    RETURN 

 

Abb. 8.5 zeigt einen Beispielausdruck des Programms. Mit einem Papierverbrauch von etwa einer Seite pro Stunde lassen sich Langzeitprotokolle für bis zu acht Meßkanäle aufnehmen.

Abb. 8.5 Ein Beispielausdruck des Programms PRINTER.BAS