Der Makrocompiler MC für 8048, 8051 und 80535


Der Makrocompiler MC ist ein Werkzeug zur vereinfachten Programmierung von Mikrocontrollern. Der Anwender kann auch ohne Vorerfahrungen nach geringer Einarbeitungszeit bereits einfache Programme entwickeln. Insbeson-dere kleine und mittlere Aufgaben lassen sich daher mit sehr geringem Zeitaufwand lösen. Der erzeugte Programmcode ist extrem kurz und schnell, so daß sich auch zeitkritische Programme schreiben lassen. Einige höhere Programmstrukturen stellen eine erhebliche Erleichterung gegenüber der Assembler-Programmierung dar. Zudem werden zahlreiche mögliche Fehlerquellen ausgeschlossen und typische Probleme der Programmentwicklung durch die feste Zuordnung von Prozessor-Ressourcen und Programmstrukturen vermieden.

Der Compiler ist als Vollversion und als Freeware mit leicht eingeschränktem Funktionsumfang für spezielle Prozessoren und Systeme erhältlich. Die freien Versionen können hier geladen werden:

MC48 für das ES48 mit 8048-Controller (ES48.zip, 124K)

MC51 für das ES51 und beliebige 8051-Controller (ES51.zip 190K)

MC535 für das ES535 mit 80C535-Controller (ES535.zip 228 K)

MCSIOS für das SIOS-Interface (MCSIOS.zip 86 K)

MC2051 für beliebige Systme mit dem Flash-Controller 89C2051 (MC2051.zip, 59K)


Handbuch der MC-Vollversion

Das Programm MC.EXE stellt eine integrierte Entwicklungsumgebung mit Editor, Compiler, Übertragungspro-gramm, Terminalprogramm und Code-Editor für beliebige Mikrocontroller-Systeme mit 8048-, 5051- und 80535-Prozessoren bereit. Insbesondere werden die Entwicklungssysteme ES48, ES51 und ES535 von Modul-Bus unterstützt.

Der Makrocompiler ist für die Mikrocontroller 8048, 8051 oder 80535 konfigurierbar. Alle relevanten Einstellungen sind in der Configurationsdatei MC.CFG eingetragen und können im Option-Menü verändert werden. Bei der Aus-lieferung enthält MC.CFG die Einstellungen für MC535 und das Entwicklungssystem ES535.

Vor dem ersten Gebrauch sollten Sie eine Sicherheitskopie der Programmdiskette machen. Soll das Programm auf einer Festplatte installiert werden, dann kann es z.B. mit COPY *.* in das entsprechende Verzeichnis (z.B. C:\MC) kopiert werden. Für eine ordnungsgemäße Funktion müssen mindestens die Dateien MC.EXE, MCxx.HLP MC.CFG und die Code-Tabellen MC48.TAB bis MC535.TAB im selben Verzeichnis stehen.

Dateien:

MC.EXE   : Das Compilerprogramm
MCxx.TAB : Die Übersetzungstabellen des Compilers
MCxx.HLP : Hilfetexte
*.M48    : MC48-Quelltexte für 8048
*.M51    : MC51-Quelltexte für 8051
*.M35    : MC535-Quelltexte für 80535
*.BIN    : Ausgabefile des Compilers im Binärformat

1. Der MC-Compiler

Der Programmaufruf MC startet das Programm mit den Einstellungen in MC.CFG. Voreingestellt ist der 80535-Prozessor und der Betrieb über die zweite serielle Schnittstelle (COM2). Die entsprechenden Dateien MC48.CFG, MC51.CFG und MC535.CFG stellen geeignete Muster für die Entwicklungssysteme ES48, ES51 und ES535 dar und können im Option-Menü geladen werden.

Bei der Programmentwicklung sind typisch folgende Schritte zu durchlaufen.

1.Ein Quelltext wird geladen oder neu eingegeben.
2. Das Programm wird compiliert. Falls der Compiler einen Fehler erkennt, wird mit einer Fehlermeldung in den Editor verzweigt. Ein übersetztes Programm kann als Binärfile abgespeichert werden.
3. Wenn ein Entwicklungssystem (ES48...ES535) angeschlossen ist, kann das compilierte Programm ins RAM des Systems übertragen und unmittelbar gestartet werden.
4. Zu Testzwecken kann über die Terminalfunktion ein Datenaustausch mit dem Entwicklungssystem durchgeführt werden.
5. Bei Badarf läßt sich das compilierte Programm im Hexedit-Menü editieren. Es können auch bereits compilierte oder assemblierte Programme geladen und gestartet werden.

Nach dem Start befindet sich das Programm im Hauptmenü. Menüpunkte können durch ihre Anfangsbuchstaben oder durch Verschieben des Leuchtbalkens mit den Pfeiltasten und <Return> ausgewählt werden. Alternativ kann eine einfache Maussteuerung verwendet werden, wobei die linke Maustaste der Return-Taste entspricht und die rechte Maustaste der Esc- Taste.

File
    Laden und Speichern von MC-Quelltexten.
File/Load
    Ein Dateimenü erlaubt die Auswahl eines Quelltextes
    *.M35 (bzw. M51, M48, je nach eingestelltem Prozessor).
    Verläßt man das Menü mit Esc, dann kann eine beliebige andere
    Datei direkt angegeben und geladen werden. Nach dem Laden
    eines Quelltextes springt das Programm in den Editor.
File/New
    Der Editor wird für ein neues Programm mit leerem Text
    aufgerufen. Dem zu bearbeitenden neuen Quelltext wird der
    Name "NEW.M35" (bzw. NEW.M51, NEW.M48) zugewiesen, der aber
    auch geändert werden kann.
File/Save
    Der Quelltext wird unter dem aktuellen Namen abgespeichert.
    Der Name kann auch verändert werden.
File/Help
    Der aktuelle Hilfetext zum Sprachumfang von MC wird gezeigt.
File/Quit
    Rückkehr ins Betriebssystem.

Edit
    Der Editor dient zum Eingeben oder Verändern von
    Quelltexten. Die Bedienung ist weitgehend WordStar-
    kompatibel. Nur die Blockoperationen funktionieren etwas
    anders: ein Block wird nicht vorher markiert, sondern man
    gibt Anfang und Ende des Blocks durch die Cursorposition an.
    Aus dem Editor heraus kann mit <F1> das Hilfesystem
    aufgerufen werden. Beim Verlassen des Editors mit Esc wird
    der Text in der Datei WORK.M35 (bzw. WORK.M48, WORK.M51)
    abgespeichert. Diese Datei enthält also immer die letzte
    Version eines bearbeiteten Programms, so daß sich die
    aktuelle Arbeit im Notfall wiederherstellen läßt. Die
    folgende Übersicht zeigt die verfügbaren Editor-Kommandos:

      Editor verlassen         :   Esc oder F10
      Hilfe aufrufen           :   F1
      Einfügen/Überschreiben   :   Ins (Einfg) - Taste
      Zeile löschen            :   Ctr-Y

      Blockbefehle:
        Block kopieren         :   Ctr-K C
        Block verschieben      :   Ctr-K V
        Block löschen          :   Ctr-K Y
        Block laden            :   Ctr-K R
        Block speichern        :   Ctr-K W


Compile
    Übersetzung des Quelltextes in lauffähigen Programmcode.
Compile/Compile
    Der Compiler übersetzt den Quelltext unter Verwendung der
    Übersetzungstabelle MC353.TAB (bzw. MC48.TAB, MC51.TAB). Der
    Übersetzungsvorgang kann am Bildschirm verfolgt werden. Er
    kann mit einer beliebigen Taste angehalten und fortgesetzt
    werden. Bei fehlerfreiem Quelltext erscheint am Ende der
    Übersetzung eine Liste des erzeugten Programmcodes. Wenn
    während der Übersetzung ein Fehler festgestellt wird, bricht
    MC den Vorgang ab, springt automatisch in den Editor und
    stellt den Cursor auf die fehlerhafte Zeile.
Compile/Save
    Das compilierte Programm wird mit der Kennung .BIN
    als reines Binärfile abgespeichert. In dieser Form kann es
    später im Hexedit-Menü erneut geladen und gestartet werden.
Run
    Compilierte Programme werden über die serielle Schnittstelle
    in das angeschlossene Entwicklungssystem übertragen und
    gestartet. Es stehen verschiedene Übertragungsprotokolle zur
    Verfügung, die im Option-Menü ausgewählt werden können und
    weiter unten genauer erläutert werden. Die Funktion Run kann
    zeitsparend sofort nach dem Verlassen des Editors unter
    Umgehung des Compiler-Menüs aufgerufen werden, wobei der
    Quelltext automatisch und mit erhöhter Geschwindigkeit
    compiliert wird. Für schnelle Testläufe genügt also <Esc, R>,
    um den Editor zu verlassen und das Programm zu starten.
Terminal
    Direkter Datenaustausch mit dem angeschlossenen
    Entwicklungssystem. Es können beliebige Bytes in dezimaler
    Schreibweise eingegeben und mit der voreingestellten Baudrate
    übertragen werden. Alle vom System gesendeten Bytes werden in
    einem eigenen Fenster dezimal angezeigt. Programme, die die
    serielle Schnittstelle eines Mikrocontrollers verwenden, um
    Daten zu empfangen und zu senden, können direkt getestet
    werden. Wird das Terminal sofort nach dem Verlassen des
    Editors aufgerufen, dann wird das editierte MC-Programm
    zuerst compiliert, geladen und gestartet. Für schnelle
    Testläufe genügt also die Tastenfolge Esc, T.
Hexedit
    Direkte Bearbeitung des Programmcodes.
Hexedit/Edit
    Hexdump eines compilierten Programms. Das Programm kann
    editiert werden, um Maschinenprogramme direkt einzugeben oder
    zu verändern.
Hexedit/Run
    Ein Programm im Editorpuffer wird in das Entwicklungssystem
    übertragen und gestartet. Nach dem direkten Editieren eines
    Programms ist das zuletzt übertragene Byte das, auf dem der
    Editor-Cursor steht. Ein Programm, das zuvor durch den
    Makrocompiler compiliert wurde, wird bis zum letzten
    compilierten Byte übertragen. Ein von Diskette geladenen
    Binärfile wird ebenfalls bis zum letzen geladenen Byte
    übertragen.
Hexedit/Load
    Eine binäre Programmdatei *.BIN wird in den Editorpuffer
    geladen.
Hexedit/Save
    Der Speicherinhalt der Editorpuffers wird bis zum Ende des
    zuletzt editierten 256-Byte-Bereichs mit der Kennung .BIN als
    Binärdatei abgespeichert.
Option
    Im Option-Menü lassen sich alle relevanten Einstellungen des
    Makrocompilers überprüfen und verändern. Alle Einstellungen
    werden beim Start aus der Configurationsdatei MC.CFG gelesen.
    Sie können einzeln verändert oder aus einer anderen CFG-Datei
    nachgeladen werden. Der Anwender kann sich eigene CFG-Dateien
    für besondere Aufgaben erstellen. Im folgenden werden jeweils
    in Klammern die Voreinstellungen für 80535-Controller und das
    ES535-Entwicklungssystem (MC535.CFG) mit angegeben.
Option/COM            (2)
    Wahl der seriellen Schnittstelle COM1 bis COM4
Option/Baud           (9600)
    Wahl der Übertragungsrate zum Entwicklungssystem.
Option/Prozessor      (80535)
    Wahl des Zielprozessors 8048, 8051 oder 80535. Entsprechend
    dem eingestellten Prozessor enthalten die MC-Quelltexte die
    Kennungen M48, M51 und M35. Während 8051 und 80535 zueinander
    insoweit kompatibel sind, daß die Code-Tabellen MC51.TAB und
    MC535.TAB ausgetauscht werden können, verfügt MC48 für den
    8048 über eigene Übersetzungsregeln und kann nur mit der
    Tabelle MC48.TAB verwendet werden.
Option/Startseite      (128)
    Die Startseite ist derjenige 256-Byte-Bereich, auf der der
    Programmcode beginnen soll. Bei der Einstellung "128" (80h)
    erwartet der Compiler, daß das compilierte Programm bei
    Adresse 8000h gestartet wird und setzt dort einen
    Sprungbefehl zum Beginn das Hauptprogramms ein. Alle
    EPROM-basierten Systeme benötigen im Normalfall einen
    Programmstart bei Seite 0. Es kann aber sinnvoll sein, ein
    Programm als eigenständiges Programm-Modul an einer höheren
    Startadresse einem bestehenden Programm anzufügen. Für
    Testläufe mit den Entwicklungssystemen ES48 und ES51 ist
    grundsätzlich die Startseite 0 zu wählen, da ein Programm
    durch Hardware-Reset gestartet wird. Beim ES535 muß dagegen
    im Standard-Modus 0 die Startseite 128 gewählt werden. Die
    Startseite kann als Hexadezimalzahl in der Schreibweise $80
    eigegeben werden.
Option/Startadresse    (80)
    Hier wird die Startadresse der ersten Prozedur relativ zum
    Anfang der Startseite angegeben. Die ersten Adressen werden
    oft für Interrupt-Einsprünge benötigt und müssen deshalb
    freigehalten werden. Der Compiler füllt die Adressen bis zur
    Startadresse mit Nullen auf, die bei Bedarf durch
    Interrupt-Sprungvektoren überschrieben werden.
Option/Tabelle         (MC535.TAB)
    Alle Makrobefehle des Compilers werden über die externen
    Tabellen MC48.TAB, MC51.TAB und MC535.TAB definiert. Der
    Programmierer kann sich eigene, z.B. erweiterte Tabellen
    erstellen und unter einem eigenen Namen bereithalten. Ebenso
    ist es möglich, auf dem ES535 mit der Tabelle MC51.TAB reine
    8051-Programme zu entwickeln.
Option/Hilfe           (MC535.HLP)
    Hier sollte die zur Übersetzungtabelle passende Hilfedatei
    MC48.HLP, MC51.HLP oder 80535.HLP gewählt werden.
Option/Protokoll       (2)
    Auswahl des Übertragungsprotokolls zwischen MC und
    Entwicklungssystem:
    1:  ROM/RAM-Umschaltung für ES48 und ES51
    2:  Download ab 8000h für ES535 (Modus 0)
    3:  Download ab 0000h für ES535 (Modus 1)
    4:  Download ab 0000h für ES535 (Modus 2)
    Das ES535 kann nur im Modus 0 mit dem Protokoll 2 die
    erweiterten Makrobefehle der Tabelle MC535.TAB als Aufrufe
    von Betriebssystem-Routinen ausführen. Im Modus 1 mit dem
    Übertragungsprotokoll 3 dagegen ist das ES535 zum ES51
    kompatibel, so daß sich reine 8081-Programme entwickeln
    lassen. Die Übertragungsprotokolle werden weiter unten
    genauer beschrieben.
Option/Delay           (0)
    Für die Datenübertragung mit dem Protokoll 1 kann eine
    Wartezeit in Millisekunden angegeben werden, um mit dem ES48
    oder dem ES51 Programmcode in EEPROMs zu laden.
Option/Load Config
    Hier kann eine beliebige .CFG-Datei geladen werden, um MC mit
    neuen Einstellungen zu versehen.
Option/Save Config
    Alle Einstellungen des Option-Menüs werden in einer
    Config-Datei gespeichert. Der voreingestellte Dateiname ist
    MC.CFG.

2. Der Sprachumfang des Makrocompilers

Der Makrocompiler verarbeitet ähnlich wie ein Assembler einzelne Befehle, die in Zeilen angeordnet sind. Fast alle Befehle verwenden den Akku A des Prozessors als universelle Varable. Daneben verwenden viele Rechenoperatio-nen das Register B. Das folgende Beispiel zeigt den direkten Zugriff auf einen Port des Mikrocontrollers. Kom-mentartexte werden durch ein Semikolon abgetrennt.

  ;Test1: Portausgabe im Hauptprogramm
  Begin
  WrP1 11110000b
  End

Alle Befehle sind mit ihren Schüsselworten und dem zu erzeugenden Programmcode in den Übersetzungstabellen MC48.TAB, MC51.TAB und MC535,TAB definiert.

Für den Makrocompiler existieren folgende Sprachregeln:

Die folgende Auflistung zeigt alle Makrobefehle des Compilers, wie sie in den mitgelieferten Befehlstabellen MC48.TAB, MC51.TAB und MC535.TAB definiert sind. Die Tabellen können leicht um weitere Makrobefehle erweitert werden. Neben den gemeinsamen Befehlen gibt es spezielle Befehle für die einzelnen Prozessoren. In der Übersicht sind sie wie folgt gekennzeichnet:

    8048   :  Nur in MC48.TAB für 8048-Prozessoren
    8051   :  In MC51.TAB und MC535.TAB für alle 8051-Derivate
    80535  :  Nur in MC535.TAB für alle 80535-Systeme
    ES535  :  Betriebssystem-Aufruf, nur für ES535, Modus 0


Laden/Speichern

       A Byte          Eine Konstante in A Laden  (z.B. A 100)
       B Byte          Eine Konstante in B Laden
       WrB             Den Inhalt von A nach B schreiben
       RdB             Den Inhalt von B nach A lesen
       SwapAB          Die Inhalte in A und B tauschen
       WrMem Nummer    A in einen Speicher (0...31) schreiben
       RdMem Nummer    Einen Speicher auslesen
       RdMem(A)        Durch A adressierten Speicher lesen
8051:  WrRAM           Ein Byte in das Daten-RAM schreiben
8051:  RdRAM           Ein Byte aus dem Daten-RAM lesen
8051:  ResetRAM        Das Daten-RAM zurücksetzen
8051:  Wr@DPTR         Ein durch DPTR addressiertes Byte ins RAM
                       schreiben
8051:  Rd@DPTR         Ein durch DPTR addressiertes Byte aus dem
                       RAM lesen


Eingabe/Ausgabe

       WrP0 Byte       Ausgabe eines Byte über den Port 0
       RdP0            Einlesen vom Port 0
       WrP1 Byte       Ausgabe eines Byte über den Port 1
       RdP1            Einlesen vom Port 1
       WrP2 Byte       Ausgabe eines Byte über den Port 2
       RdP2            Einlesen vom Port 2
8051:  WrP3 Byte       Ausgabe eines Byte über den Port 3
8051:  RdP3            Einlesen vom Port 3
80535: WrP4 Byte       Ausgabe eines Byte über den Port 4
80535: RdP4            Einlesen vom Port 4
80535: WrP5 Byte       Ausgabe eines Byte über den Port 5
80535: RdP5            Einlesen vom Port 5
80535: RdP6            Einlesen vom Port 6

Die durch Schreibbefehle (Wr...) übergebenen Bytes werden immer über den Akku transportiert, können aber wahl-weise auch als Konstante hinter den Befehl geschrieben werden. In diesen Fall wird das Byte zuerst in A geschrie-ben. A 15 ... WrP1 und WrP1 15 haben also die selbe Wirkung. Zahlen dürfen auch hexadezimal (FFh) oder binär (11110000b) geschrieben werden.

Schreiben und Lesen der SFR

8051:  WrSBUF Byte     SBUF beschreiben
8051:  RdSBUF          SBUF auslesen
8051:  WrSCON Byte     SCON beschreiben
8051:  WrTH1  Byte     TH1 beschreiben
8051:  RdTH1           TH1 auslesen
8051:  WrTL1  Byte     TL1 beschreiben
8051:  RdTL1           TL1 auslesen
8051:  WrTH0  Byte     TH0 beschreiben
8051:  RdTH0           TH0 auslesen
8051:  WrTL0  Byte     TL0 beschreiben
8051:  RdTL0           TL0 auslesen
8051:  WrTMOD Byte     TMOD beschreiben
8051:  WrTCON Byte     TCON beschreiben
8051:  WrSP   Byte     SP beschreiben
8051:  RdSP            SP auslesen
8051:  WrDPH  Byte     DPH beschreiben
8051:  RdDPH           DPH auslesen
8051:  WrDPL  Byte     DPL beschreiben
8051:  RdDPL           DPL auslesen
8051:  WrIE   Byte     IE beschreiben
8051:  RdIE            IE auslesen
8051:  DPTR Hi Lo      DPTR als 16-Bit-Register beschreiben

Für den 80535 werden in gleicher Weise die folgenden Register gelesen (Rd) und beschrieben (Wr): IEN0 IP0 IEN1 IP1 IRCON CCEN CCL1 CCH1 CCL2 CCH2 CCL3 CCH3 T2CON CRCL CRCH TL2 TH2 ADCON ADDAT DAPR ADCON ADDAT

Mathematische und logische Operationen

       + Byte          A mit einer Konstanten addieren
       +B              A mit B addieren
       - Byte          Von A eine Konstante subtrahieren
       -B              B von A subtrahieren
       A+1             A um 1 erhöhen
       A-1             A um 1 verkleinern
       B+1             B um 1 erhöhen
       B-1             B um 1 verkleinern
       AND Byte        A UND Konstante
       AndB            A UND B
       OR Byte         A ODER Konstante
       OrB             A ODER B
       XOR Byte        A EXKLUSIV-ODER Konstante
       XorB            A EXKLUSIV-ODER B
       NOT             NICHT A (invertieren)
       ShiftLeft       Bits in A um eine Stelle nach links verschieben
       ShiftRight      Bits in A um eine Stelle nach rechts verschieben
       SwapNibbles     Bit 0...3 mit Bit 4...7 tauschen
8051:  *B              Multiplikation A * B, Übertrag in B
8051:  /B              Division A/B, Rest in B
Prozeduren
       Procedure Name  Anfang einer eigenen Prozedur
       EndProc         Ende der eigenen Prozedur
       ExitProc        Eine Prozedur verlassen

Der Name der Prozedur wird wie ein Befehl behandelt. Er kann in weiter unten definierten Prozeduren aufgerufen werden. Maximal sind beim 8048 acht geschachtelte Aufrufe erlaubt, beim 8051 16. Ein Name darf bis zu 20 Zei-chen lang sein. Prozedurnamen dürfen wahlweise mit einer Konstanten aufgerufen werden, die dabei in A geladen wird.

Bedingte Prozeduraufrufe

       IfA=B Name      Aufruf der Prozedur Name, wenn A und B gleich
       IfA<>B Name     Aufruf, wenn A und B ungleich
       IfA>=B Name     Aufruf, wenn A größer oder gleich B
       IfA<B  Name     Aufruf, wenn A kleiner als B
       IfA=0 Name      Aufruf, wenn A gleich Null
       IfA>0 Name      Aufruf, wenn A größer als Null
8051:  IfA= Byte Name  Aufruf, wenn A = Byte

Außer Prozeduren dürfen mit MC48 nur solche Befehle aufgerufen werden, die keinen Parameter haben. Mit MC51 und MC535 dagegen dürfen auch Befehle mit eigenen Parametern aufgerufen werden.
Zählschleifen      (Zähler 1...8)

       Count1 Byte    Schleifenzähler 1 mit einer Zahl laden
       WrCount1       Schleifenzähler 1 mit A laden
       Loop1 Name     Zähler-1-mal Prozedur Name aufrufen
       RdCount1       Schleifenzähler 1 auslesen
       Loop Name      Endlosschleife

Es gibt insgesamt acht Schleifenzähler, mit denen man Zählschleifen aufbauen kann. Außer Prozedurnamen können auch Befehle aufgerufen werden.
Bedingte Programmschleifen

       WhileNotDone    Schleifenanfang
       ...             (Programmzeilen)
       EndWhile        Schleifenende
       Done            Den Schleifendurchlauf verhindern
       NotDone         Den Schleifendurchlauf freigeben
       WhileA=0        Schleifenbedingung: A gleich Null
       WhileA>0        Schleifenbedingung: A größer Null

In einer Schleife dürfen beliebig viele Programmzeilen stehen. Schleifen dürfen achtfach geschachtelt werden.

Programmstruktur

       Begin           Anfang des Hauptprogramms
       Stop            Einfrieren des Programmzustandes
       End             Ende des Hauptprogramms
       ;Text           Kommentartext
       Nop             2,5µs (8048) bzw. 1µs (8051) warten
       Inline Text     Maschinencode oder Tabellen einfügen
8051:  Define          Deklaration einer Konstanten
8051:  CodeAdr Hi Lo   Das Programm bei der Adresse (Hi.Lo)
                       fortsetzen



Der Text nach dem Inline-Befehl muß in hexadezimaler Form geschrieben werden. Als Trennzeichen zwischen Bytes ist das Komma erlaubt, also Inline FF00FF oder Inline FF,00,FF.
Interrupts und Timerbefehle

8048:  StartTimer        Zeitgeber starten
8048:  StartCounter      Ereigniszähler starten
8048:  StopCounter       Zeitgeber/Zähler stoppen
8048:  WrCounter         Zähler laden
8048:  RdCounter         Zähler auslesen
8048:  CounterInterrupt  Interruptprozedur Zähler/Timer
8048:  HardInterrupt     Interruptprozedur /Int-Pin
8048:  EnableHardInt     Hardware-Interrupt freigeben
8048:  DisableHardInt    Hardware-Interrupt sperren
8048:  EnableCounterInt  Zählerinterrupt freigeben
8048:  DisableCounterInt Zählerinterrupt sperren
8051:  Interrupt Adr     Interruptprozedur des Vektors Adr
       EndInterrupt      Ende einer Interruptprozedur



Die folgenden Makrobefehle gehören zum erweiterten Sprachumfang für 8051-Prozessoren für harwarenahe Pro-grammierung und direkte Speicherzugriffe. Sie setzen eine besondere Vorsicht des Programmierers voraus, weil Adressenkonflikte durch Programmierfehler vom Compiler nicht mehr verhindert werden können.

Direkte Zugriffe auf das interne RAM

8051:   WrAdr Adr        Den Inhalt von A in Adr schreiben
8051:   RdAdr Adr        Die Adresse Adr auslesen
8051:   MovAdr Adr Byte  Die Konstante Byte in Adr schreiben
8051:   AndAdr Adr Byte  Adr mit Byte UND-verknüpfen
8051:   OrAdr Adr Byte   Adr mit Byte ODER-verknüpfen
8051:   IncAdr Adr       Den Inhalt von Adr um 1 erhöhen
8051:   DecAdr Adr       Den Inhalt von Adr um 1 verkleinern



Schleifen mit frei wählbaren RAM-Adressen

8051:   LoopAdr Adr Byte   Schleifenzähler Adr mit Byte laden
        ...
8051:   EndLoopAdr         Adr verkleinern, Rücksprung wenn > 0
                           (Sprungweite bis -127)
8051:   WhileDecAdr        Adr verkleinern, Schleife solange > 0
                           (Sprungweite beliebig)


Direkter Zugriff auf Bitadressen

8051:   ClearBit Adr       Bit(Adr)= 0
8051:   SetBit Adr         Bit(Adr)= 1
8051:   IfBit Adr Name     Prozeduraufruf, wenn Bit(Adr)= 1
8051:   IfNotBit Adr Name  Prozeduraufruf, wenn Bit(Adr)=0
8051:   WhileBit Adr       Wiederholung, solange Bit(Adr)=1
8051:   WhileNotBit Adr    Wiederholung, solange Bit(Adr)=0



Systemaufrufe in MC535.TAB für das ES535 im Modus 0

ES535:  WrCOM              serielle Ausgabe mit 9600 Baud
ES535:  RdCOM              serielle Eingabe mit 9600 Baud
ES535:  Delay Zeit         Wartezeit (Zeit * 0,1 ms)
ES535:  RdAD Kanal         8-Bit-Messung an AN0...AN7
ES535:  RdAD10 Kanal       10-Bit-Messung, Highbyte in B



Der Delay-Befehl stellt ein genaues Zeitraster bereit, d.h. es wird immer bis zur nächsten abgelaufenen Zeiteinheit gewartet. Solange die Rechenzeiten zwischen den Delay-Aufrufen kleiner als 0,1ms bleiben, wirken sie sich nicht aus.

3. Einführung in die Programmierung mit MC

Jedes MC-Programm besteht wie ein Pascal-Programm aus Prozeduren und einem Hauptprogramm. Prozeduren können im Hauptprogramm und in weiteren Prozeduren genau wie vordefinierte Befehle und Funktionen aufgerufen werden. Damit Prozedurnamen leichter vom vorhandenen Sprachumfang unterschieden werden können, sollte man alle Prozedurnamen klein schreiben, während alle Befehle auch Großbuchstaben enthalten. Der Compiler unter-scheidet grundsätzlich nicht zwischen Groß- und Kleinbuchstaben, sondern die Unterscheidung dient allein der besseren Lesbarkeit der Programme. Kommentare können an jede Zeile angefügt werden und müssen mit einem Semikolon beginnen.

Der grundsätzliche Aufbau eine MC-Programms wird im Programm Test2 gezeigt. Die Prozedur "ausgeben" wird vom Hauptprogramm mit einer Konstanten aufgerufen. In diesem Fall wird Bit 6 des Ports aktiv low. Die ersten Programmbeispiele gehen alle davon aus, daß man eine LED-Reihe mit acht LEDs und Vorwiderständen von z.B. 470 Ohm an den Port P1 des Prozessors gegen +5V angeschlossen hat. Dies ist bei allen drei Entwicklungssystemen ES48, ES51 und ES535 in gleicher Weise möglich.

   ;Test2: Portausgabe in einer Prozedur

   Procedure ausgeben
   Not                 ;invertieren für LEDs gegen +5V
   WrP1                ;an Port P1 ausgeben
   EndProc

   Begin
   ausgeben 64
   End

Oft müssen Vorgänge in einer endlosen Schleife durchlaufen werden. Dann bietet es sich an, eine Prozedur mit Loop immer wieder aufzurufen. Das folgende Beispiel verschiebt laufend ein Bit am Ausgabeport. Der globale Hilfsspeicher Mem 1 wird im Hauptprogramm zunächst initialisiert und dann in der Ausgabeprozedur laufend verändert. Hier zeigt sich neben der Übergabe im Akku A bzw. dem Aufruf einer Prozedur mit einer Konstanten, die ebenfalls im Akku übergeben wird, eine weitere Möglichkeit, Daten an eine Prozedur zu übergeben.

Die hohe Geschwindigkeit im Mikrosekundenbereich führt dazu, daß alle am Port angeschlossenen LEDs nur schwach leuchten. Die Ausgabegeschwindigkeit ist vom verwendeten Prozessor und der Taktfrequenz abhängig und kann z.B. mit einem Oszilloskop ermittelt werden.

   ;Test3: Verschieben und Ausgeben in einer Schleife


   Procedure ausgeben
   RdMem 1       ;globale Variable Mem 1
   ShiftLeft     ;Bit verschieben
   WrMem 1       ;abspeichern
   Not           ;invertieren für LEDs gegen +5V
   WrP1          ;an Port P1 ausgeben
   EndProc

   Begin
   A 1
   WrMem 1         ;Mem 1 = 1
   Loop ausgeben   ;Endlosschleife
   End

Für eine verlangsamte und optisch erkennbare Ausgabe über die LEDs ist eine Warteschleife erforderlich. Hierzu stellt der Makrocompiler die Zählschleifen 1 bis 8 zur Verfügung. Eine Schleife muß zunächst mit einer Konstanten geladen werden (Count1 255) und kann dann einen Makrobefehl oder eine Prozedur mehrfach aufrufen (Loop1 NOP). Im folgenden Programmbeispiel wird eine Zählschleife in der Prozedur "warten" gebildet, die dann selbst 255 mal in der Prozedur "ausgeben" aufgerufen wird.

   ;Test4: langsames Lauflicht

   Procedure warten
   Count1 255    ;Wiederholschleife 1 laden
   Loop1 Nop     ;255 mal Nichts
   EndProc

   Procedure ausgeben
   RdMem 1       ;globale Variable Mem 1
   ShiftLeft     ;Bit verschieben
   WrMem 1       ;abspeichern
   Not           ;invertieren für LEDs gegen +5V
   WrP1          ;an Port P1 ausgeben
   Count2 255    ;Wiederholschleife 2 laden
   Loop2 warten  ;255 mal warten
   EndProc

   Begin
   A 1
   WrMem 1         ;Mem 1 = 1
   Loop ausgeben   ;Endlosschleife
   End

Um mit einer einfachen Zählschleife ein definiertes Zeitraster einzuhalten, müßte man genaue Messungen vorneh-men. Es ist daher besser, eine Prozedur zu verwenden, die auf einen Hardware-Timer zugreift. Die Prozedur Delay ist für alle drei Prozessoren verfügbar und wird auf unterschiedliche Weise realisiert. Programme für das Entwick-lungssystem ES535 greifen auf eine Systemroutine zurück und erlauben ein genaues Zeitraster in Einheiten von 0,1ms. Für den 8051 und den 8048 werden Runtime-Prozeduren hinzugeladen, die die Prozedur Delay mit einer Zeiteinheit von 1ms bereitstellen.

In gleicher Weise werden auch die Prozeduren zum seriellen Senden (WrCOM) und Empfangen (RdCOM) im Run-time-System bereitgestellt. Hier wird immer eine Baudrate von 9600 Baud eingehalten.

Das folgende Programmbeispiel zeigt die Verwendung des Delay-Befehls und der seriellen Ausgabe für den 80535:

   ;Test5: Anwendung der seriellen Schnittstelle
   ;und des Delay-Befehls mit MC535

   Procedure ausgeben
   RdMem 1       ;globale Variable Mem 1
   ShiftLeft     ;Bit verschieben
   WrMem 1       ;abspeichern
   WrCOM         ;zum Terminal senden
   Not           ;invertieren für LEDs gegen +5V
   WrP1          ;an Port P1 ausgeben
   Delay 100     ;10 ms warten
   EndProc

   Begin
   A 1
   WrMem 1         ;Mem 1 = 1
   Loop ausgeben   ;Endlosschleife
   End

Dasselbe Programm für den 8051 muß die seriellen Übertragungsroutinen und die Delay-Prozedur in einem Runtime-System SYSTEM51.M51 bereitstellen, das bei Bedarf in eigene Programme eingebunden werden muß. Hier muß im Hauptprogramm zunächst die Initialisierungsroutine Init aufgerufen werden.

   ;Test5: Anwendung des Runtime-Systems für MC51

   ;Basisroutinen für MC51      (SYSTEM51.M51)

   Procedure Init
   Define RI  98h         ;SCON.0
   Define TI  99h         ;SCON.1
   WrTH1  FAH             ;6 bis Überlauf: 9600 Baud
   WrTL1  FAH
   WrTH0  252             ;942 bis Überlauf: ca. 1ms
   WrTL0  122
   WrTMOD  00100001b      ;Timer1: 8-Bit-Auto-Reload, Timer0: 16 Bit
   WrTCON  01010000b      ;beide Timer starten
   WrSCON  01010010b      ;InitRS232 (50H + TI)
   WrPCON  10000000b      ;80H, SMOD=1
   EndProc

   Procedure RdCOM
   WhileNotBit RI         ;Warten bis RI
   EndWhile
   ClearBit   RI          ;RI zurücksetzen
   RdSBUF
   EndProc

   Procedure WrCOM
   WhileNotBit TI         ;Warten bis letztes Byte gesendet
   EndWhile
   WrSBUF
   EndProc

   Procedure Delay        ;0...255ms
     Define TF0  8Dh      ;TCON.5
     Define TR0  8Ch      ;TCON.4
     Define TH0  8Ch
     Define TL0  8Ah
   WhileA>0
     WhileNotBit TF0
     EndWhile
     ClearBit  TR0        ;Timer0 stoppen
     ClearBit  TF0
     MovAdr TH0  252      ;922 bis Überlauf: ca. 1ms
     MovAdr TL0  112      ;122 - 10 Zyklen Zeitausgleich
     SetBit TR0           ;Timer neu starten
     A-1
   EndWhile
   EndProc

   Procedure ausgeben
   RdMem 1       ;globale Variable Mem 1
   ShiftLeft     ;Bit verschieben
   WrMem 1       ;abspeichern
   WrCOM         ;zum Terminal senden
   Not           ;invertieren für LEDs gegen +5V
   WrP1          ;an Port P1 ausgeben
   Delay 100     ;100 ms warten
   EndProc

   Begin
   Init            ;RS232 und Timer initialisieren
   A 1
   WrMem 1         ;Mem 1 = 1
   Loop ausgeben   ;Endlosschleife
   End

Für den 8048 existiert ein vergleichbares Runtime-System, das durch Einbinden passender Maschinenprogramme realisiert wurde. Hier ist zu beachten, daß diese Prozeduren am Anfang des Programms stehen müssen und nicht verschoben werden dürfen. Der Code muß bei Adresse 0009h (Startadresse 9 im Option-Menü) beginnen. Vor der Verwendung des Delay-Befehls muß mit StartTimer der interne Zeitgeber eingeschaltet werden. Dem Runtime-System liegt das Assemblerprogramm SYSTEM48.ASM zugrunde. Es findet sich zusammen mit der Datei SY-STEM48.M48 auf der MC-Diskette.

   ;Runtimesystem für MC48-Programme     (SYSTEM48.M48)

   Procedure WrCOM               ;9600 Baud
   Inline BA,08,9A,7F,BB,10,EB,0F
   Inline 97,67,F6,19,9A,7F,E6,1D
   Inline 8A,80,8A,80,BB,0F,EB,1F
   Inline EA,11,23,00,23,00,8A,80
   Inline BB,01,EB,2B
   EndProc

   Procedure RdCOM              ;9600 Baud
   Inline 86,33,97,E6,2E,BA,19,EA
   Inline 35,BB,08,97,86,49,00,A7
   Inline 2C,67,2C,BA,0F,EA,43,EB
   Inline 39,FC,83,00,97,2C,67,2C
   Inline BA,0F,EA,50,EB,39,FC
   EndProc

   Procedure Delay                 ;A * 1 ms
   Inline AD,16,5C,97,E6,57,AE,23
   Inline F4,62,23,00,23,00,23,00
   Inline 23,00,FE,55,ED,57
   EndProc

Eine der höheren Programmstrukturen des Makrocompilers sind die While-Schleifen. Die Schleife kann beliebig viele Zeilen enthalten und wird mit EndWhile abgeschlossen. Die Bedingung, unter der die Schleife wiederholt wird, ist durch den While-Befehl festgelegt. Im folgenden Beispiel wird eine Taste an P1.7 abgefragt. Die Schleife wird mit WhileA>0 solange durchlaufen, bis A durch einen Tastendruck Null wird.

   ;Test6, Demonstration der While-Schleifen
   ;Tatenabfrage an P1.7, aktiv low

   Procedure taste-erwarten
   WhileA>0          ;solange P1.7 = high
     RdP1            ;Port P1 auslesen
     And 10000000b   ;P1.7 maskieren
   EndWhile          ;beendet, wenn P1.7 = low
   EndProc

   Begin
   WrP1 FFh
   taste-erwarten
   WrP1 11110000b
   End

Eine weitere hilfreiche Programmstruktur sind die IF-Abfragen. Ein Befehl oder eine Prozedur wird unter einer definierten Bedingung ausgeführt. Im folgenden Beispiel soll ein Kommando von der seriellen Schnittstelle emp-fangen und decodiert werden. Der Mikrocontroller wird zu einem Interface, das auf Kommandos des PC reagiert und einen Datenaustausch zum Port P1 durchführt. "16" steht für Portausgaben und "32" für Porteingaben. Hier wird mit IfA=B ein Vergleich des empfangenen Kommandos mit einem Vergleichswert durchgeführt.

   ;Test7, Demonstration von If-Abfragen
   ;Serielles Interface mit Commando-Dekodierung

   ;für MC51 oder MC48 hier das Runtime-System einfügen

   Procedure ausgeben
   RdCOM           ;Ausgabebyte empfangen
   WrP1            ;An Port P1 ausgeben
   A 16            ;altes Kommando wiederherstellen
   EndProc

   Procedure einlesen
   RdP1            ;Port P1 auslesen
   WrCOM           ;Ergebnis senden
   A 32            ;altes Kommando wiederherstellen
   EndProc

   Procedure kommando-erwarten
   RdCOM           ;Kommando empfangen
   WrMem 1         ;zwischenspeichern
   B 16            ;Vergleichswert
   IfA=B ausgeben  ;Kommando 16 = Ausgeben
   RdMem 1         ;Kommando lesen
   B 32
   IfA=B einlesen  ;Kommando 32 = Einlesen
   EndProc

   Begin
   ;Init           ;Init nur für MC51
   ;StartTimer     ;nur für MC48
   Loop kommando-erwarten
   End

Komplexe Bedingungen lassen sich durch die WhileNotDone-Schleife berücksichtigen. Sie verwendet ein globales Flag Done (Done steht hier für "ausgeführt"), das mit Done gesetzt und mit NotDone zurückgesetzt werden kann. Meist wird vor der Schleife NotDone verwendet, während Done in der Schleife nach einer Bedingung ausgeführt wird. Möglich ist es aber auch, Done in einer untergeordneten Prozedur auszuführen, die innerhalb der While-Schleife aufgerufen wird. Das Beispielprogramm Test8 fragt sieben Eingabetasten ab. Sobald eine der Tasten ge-drückt wird, erfolgt eine Meldung an das Terminal.

   ;Test8, Demonstration von WhileNotDone-Schleifen
   ;Auswertung von sieben Meldeleitungen an P1.1...P1.7
   ;über P1.0 könnan alle Meldeleitungen gesperrt werden

   ;für MC51 oder MC48 hier das Runtime-System einfügen

   Procedure signal-erwarten
   NotDone
   WhileNotDone
     RdP1
     WrMem 1        ;zwischenspeichern
     B 11111110b
     IfA<B Done     ;ein Signal an P1.1 ... P1.7 ?
     RdP1
     AND 1
     IfA=0 NotDone  ;alle Signale über P1.0 gesperrt?
   EndWhile
   RdMem 1          ;Portzustand lesen
   NOT              ;aktiv-high invertieren
   And FEh          ;alle Meldeleitungen maskieren
   WrCOM            ;Meldung senden
   RdCOM            ;Bestätigung erwarten
   EndProc

   Begin
   ;Init            ;Init nur für MC51
   ;StartTimer      ;nur für MC48
   Loop signal-erwarten
   End

4. Anwendungsbeispiele

Auf der Programmdiskette befinden sich drei größere Programmbeispiele, die typische Einsatzmöglichkeiten des Makrocompilers demonstrieren. Zahlreiche weitere Anwendungen werden im unten angegebenen Buch beschrieben.

- Das Programm TIMER.M48 stellt einen einfachen Zeitgeber vor, der in seiner Funktion etwa mit einer Eieruhr vergleichbar ist. Der Timer verwendet eine Leuchtbandanzeige aus acht LEDs am Port P1, die eine Restzeit von Null bis acht Minuten anzeigen. Als einziges Bedienelement kommt ein Tastschalter an P2.3 zum Einsatz, über den der Timer "geladen" werden kann. Dabei soll der Benutzer durch einzelne Tastendrücke oder die Länge des Tasten-drucks die Timer-Zeit einstellen. Jeweils eine halbe Sekunde steht für eine Minute. Die eingestellte Zeit erscheint gleichzeitig in der Leuchtbandanzeige, so daß die Einstellung nicht schwerfällt. Der Timmer erlaubt auch ein nach-trägliches Höherstellen der Restzeit. Mit dem Ablauf der Uhr beginnt ein Blinken aller LEDs, das entweder nach einer Minute aufhört oder durch neues Laden des Timers beendet wird.

Die genaue Zeitsteuerung der Uhr gestaltet sich dank der oben vorgestellten Delay-Prozedur recht einfach. Regel-mäßige Aufrufe ergeben ein genaues Millisekundenraster, wobei die eigentliche Rechenzeit dazwischen kürzer als eine Millisekunde ist und nicht nicht den Zeitablauf beeinflußt. Es wurde darauf geachtet, daß in regelmäßigen Abständen die Taste abgefragt wird.

- Das Programm MORSEN.M51 liest und dekodiert die Eingaben über eine Morsetaste, die an Port 1.7 gegen Masse angeschlossen ist. Die Morsezeichen werden mit fest eingestellter Geschwindigkeit verarbeitet, wobei Striche ab einer Länge von 200ms erkannt werden. Damit ergibt sich eine optimale Geschwindigkeit von 60 BpM (Buchsta-ben pro Minute), also 100ms Punktlänge und 300ms Strichlänge, und ein Arbeitsbereich von ca. 50 BpM bis 80 BpM.

Alle erkannten Morsezeichen werden auf einer zweizeiligen LCD-Anzeige dargestellt. Die Anzeige scrollt mit jeder vollen Zeile nach oben. Gleichzeitig wird ein Mithörton generiert, der als Rechtecksignal mit 500Hz an P1.0 bis P1.3 ansteht. Hier kann ohne weitere Elektronik ein Piezo-Schallgeber angeschlossen werden. Das Programm ver-zichtet auf jeden Datenzugriff auf das externe RAM. Deshalb ist es möglich, es auf dem ES51 in einem EEPROM einzusetzen, also permanent bereitzuhalten. Der gesamte Code benötigt weniger als ein Kilobyte und zeigt damit die speicherökonomische Arbeitsweise des Makrocompilers.

Das Programm liefert zugleich alle erforderlich Basisroutinen zur Ansteuerung des LCD-Displays mit dem ES51 oder ES535. Die Prozeduren wurden als systemnahe Ressourcen geschrieben, wobei keine Mem-Speicher belegt wurden und alle wichtigen Register (z.B. der Datapointer DPTR) wiederhergestellt werden. Als Zwischenspeicher werden hier die internen RAM-Adressen 02h bis 05h eingesetzt.

- Das Programm ROBOT.M35 steuert zwei Fernsteuer-Servos über die interne PWM-Einheit des 80535. Der Anwender bewegt die Servos über zwei Potis an den Analogeingängen AN0 und AN1. Die Steuerspannungen werden in Pulsbreiten zwischen 1ms und 2ms umgesetzt, wobei alle 10 Millisekunden eine Aktualisierung der Steuerdaten erfolgt. Gleichzeitig werden alle Daten im RAM gespeichert. Mit den gegebenen Einstellungen dauert die Aufnah-me von Meßdaten etwa eine Minute. Nach Ablauf dieser Zeit werden die gespeicherten Daten wieder aus dem RAM gelesen und erneut in PWM-Signale umgesetzt. Das Programm erlaubt die Realisierung eines einfachen Robotor-Modells mit Teach-Modus. Gewünschte Steuersequenzen werden einfach über Potis erzeugt und stehen dann für endlose Wiederholungen zur Verfügung.

Das Programm demonstriert die direkte Programmierung von Spezialfunktionsregistern zur Steuerung der Capture-Compare- Einheit. Es können Impulse bis zu 65 Millisekunden bei einer Auflösung von einer Mikrosekunde erzeugt werden. Der 80535 generiert Impulse im Abstand von 4 ms. Die Variation der Pulslänge erfolgt mit einer Auflösung von 10 Bit in etwa 1000 Schritten. Dememtsprechend wird der AD-Wandler des 80535 über den Befehl RdAna-log10 mit einer Auflösung von 10 Bit betrieben.

5 Befehlserweiterungen

Alle Makrobefehle des Compilers werden durch Übersetzungstabellen (z.B. MC51.TAB) definiert. Diese Tabellen lassen sich mit einem beliebigen ASCII-Editor bearbeiten und erweitern. So kann der Anwender eigene Makrobe-fehle erzeugen, um z.B. seinen Programmcode für bestimmte Aufgaben zu optimieren. Weiterhin lassen sich leicht die erforderlichen Erweiterungen für weitere Prozessoren wie z.B. 80552, 87C752 usw. anfügen. Erweiterungen können als kurze Assemblerrountinen geschrieben und assembliert werden. Der Anwender muß dann einen neuen Befehlsnamen definieren und zusammen mit dem Code an die Befehlstabelle anfügen. Außerdem ist es möglich, abgeänderte oder erweiterte Tabellen unter eigenen Namen bereitzuhalten und bei Bedarf im Option-Menü einzu-tragen.

Befehlserweiterungen setzen eine genaue Kenntnis des Makrocompilers voraus. Es ist nützlich, sich die bereits defi-nierten Makrobefehle genau anzusehen. Der folgende Ausschnitt zeigt die Behandlung des Ports P1 in MC51.TAB. Der Port wird über das SFR P1 an der Adresse 90h erreicht. Der angefügte Assemblertest im Kommentar verdeut-licht, daß die Portzugriffe über den Akku laufen. Der Makrobefehl WrP1 enthält aber zusätzlich die spezielle Com-piler-Anweisung PA (für Parameter- Übergabe). PA bewirkt, daß der Compiler überprüft, ob hinter dem Makrobe-fehl eine Konstante angegeben wurde (z.B. WrP1 255). In diesem Fall wird die Konstante zunächst in den Akku geladen und darauf erst der eigentliche Befehl ausgeführt. Steht hinter WrP1 kein Wert, dann bleibt PA ohne Wir-kung, d.h. es wird der gerade im Akku vorhandene Wert übergeben.

WrP1           PA F5 90     ;mov P1,A
RdP1           E5 90        ;mov A,P1

Eine andere wichtige Compileranweisung ist XX. Sie bewirkt, daß eine hinter dem Befehl angegebene Konstante direkt in den Code eingesetzt wird. Auf diese Weise werden z.B. A und B geladen:

A              74 XX        ;mov A,#XX
B              75 F0 XX     ;mov B,#XX

In Assembler-Programmen wird oft direkt mit AND- oder OR-Verkmüpfungen auf Ports zugegriffen. Falls dies auch für MC-Programme erwünscht wird, können z.B. die folgenden Makrobefehle neu gebildet und an die Tabelle angehängt werden:

AndP1          53 90 XX     ;anl P1,#XX
OrP1           43 90 XX     ;orl P1,#XX

Auf diese Weise lassen sich sehr einfach neue Kommandos bilden, die z.B. auch aus mehreren Assembleranweisun-gen bestehen können. Etwas komplizierter wird es, wenn der Compiler höhere Programmstrukturen wie z.B. Wie-derholschleifen oder Fallabfragen übersetzen soll. In diesem Fall müssen nämlich Sprungadressen berechnet wer-den, die über weitere Compileranweisungen gesteuert werden. Sie sind durch zwei Buchstaben gekennzeichnet und liegen oberhalb von FF, während die direkten OP-Codes in hexadezimaler Schreibweise zwischen 00 und FF liegen. Die folgende Liste zeigt alle definierten Compileranweisungen, wobei einige sich je nach Zielprozessor unterschei-den:

       XX Die Konstante nach dem Befehl wird hier eingesetzt.

8051:  YY Die zweite Konstante nach dem Befehl wird hier
          eingesetzt.

       RR Angabe des Mem-Speichers: Die Konstante wird mit 32
          (8048) bzw. 48 (8051) addiert und hier eingesetzt.

       PA Optionale Parameterübergabe: Wird hinter dem Befehl ein Wert
          angegeben, wird dieser zuvor in A geladen.

       PD Definition einer Prozedur. Der Prozedurname wird
          zusammen mit dem Befehlscode zu seinem Aufruf an die
          Befehlsliste angefügt.

       HA Hauptprogramm-Anfang. Ein Sprungbefehl auf die
          aktuelle Adresse wird nachträglich an den Anfang der
          Startseite (Reset-Vektor) gesetzt.

       HH Der Compiler merkt sich die aktuelle Adresse für einen
          späteren Rücksprung.

       SS An dieser Stelle wird die bei "HH" gespeicherte Adresse
          als Rücksprungadresse eingetragen.

8051:  SR Hier wird die bei "HH" gespeicherte Adresse als
          relative Srungweite eingetragen..

       PR Hier wird ein Befehl oder ein Prozeduraufruf
          eingesetzt.

8048:  NN Das zweite Wort der Programmzeile ist ein
          Prozedurname oder ein Befehl. Es wird die Länge des
          Maschinencodes festgestellt und die Vorwärts-Sprung-
          adresse zum bedingten Überspringen des Befehls an
          dieser Stelle eingesetzt.

8051:  NR Für die bedingte Ausführung eines Befehls
          wird die Länge des Maschinencodes festgestellt und die
          Vorwärts-Sprungadresse zum bedingten Überspringen des
          Befehls an dieser als relative Sprungweite eingetragen.

8048:  JP An dieser Stelle wird der JMP-Befehl 04, 24, 44 usw.
          je nach aktueller Seite (0...7) des Programmspeichers
          eingesetzt.

       HS Für While-Schleifen wird der Schleifenzähler
          inkrementiert, und die aktuelle Adresse wird für einen
          späteren Rücksprung in einer bedingten Programmschleife
          gespeichert.

       JS Es werden die Befehle zum Rücksprung an die mit HS
          bezeichnete Stelle eingesetzt.

8048:  J3 Es wird die Adresse für einen drei Byte weiten
          Vorwärtssprung berechnet und hier eingesetzt.

       JZ In die aktuelle Adresse wird das vorläufige Sprungziel
          "00" eingesetzt, und die Adresse wird für das spätere
          Einsetzen der richtigen Sprungadresse gespeichert.

       JE Die aktuelle Sprungadresse wird in die bei "JZ"
          gespeicherte Adresse eingesetzt. Der Schleifenzähler
          wird dekrementiert.

       SO Es wird am Ende einer Prozedur oder des Hauptprogramms
          geprüft, ob noch Schleifen geöffnet sind.

       HX Es werden die folgenden hexadezimalen Bytes in das
          Programm eingesetzt (Inline-Code).

8048:  TI Timer-Interruptprozedur: Ein Sprungbefehl auf die
          aktuelle Adresse wird in Adresse 03 eingetragen.

8048:  HI Hardware-Interruptprozedur: Ein Sprungbefehl auf die
          aktuelle Adresse wird in Adresse 07 eingetragen.

8051:  IN Ein Sprungbefehl auf die Startadresse einer
          Interruptprozedur wird an der angegebenen
          Interrupt-Einsprungadresse eingesetzt.

8051:  XD Definition einer Konstanten mit dem Define-Kommando.

8051:  XO Codeadresse hi, lo festlegen, unter der die Übersetzung
          fortgesetzt wird.

Zur Verdeutlichung seien hier einige Programmstukturen als Assemblerlisting wiedergegeben:

 Assemblerlisting der Wiederholschleifen in MC48

  0002 83          Name           ret

  0003 D5          Count1         sel     rb1
  0004 B8 05                      mov     r0,#05
  0006 C5                         sel     rb0

  0007 D5          WrCount1       sel     rb1
  0008 A8                         mov     r0,a
  0009 C5                         sel     rb0

  000A D5          RdCount1       sel     rb1
  000B F8                         mov     a,r0
  000C C5                         sel     rb0

  000D C5          Loop1          sel     rb0     ;HH
  000E 94 02                      call    Name
  0010 D5                         sel     rb1
  0011 E8 0D                      djnz    r0,Loop1 ;SS
  0013 C5                         sel     rb0

  0014 94 02       Loop           call    Name
  0016 84 14                      jmp     Loop

Alle Zählschleifen werden mit Registern der Registerbank 1 gebildet, die sonst in MC48 nicht verwendet wird. Deshalb ist eine Bankumschaltung erforderlich. Mit MC51 vereinfachen sich die Wiederholschleifen, weil auf die entsprechenden Register über ihre Adressen zugegriffen werden kann.

 Assemblerlisting der While-Schleifen in MC48

  0003 85          Done           clr     F0      ;F0=0

  0004 85          NotDone        clr     F0
  0005 95                         cpl     F0      ;F0=1

  0006             WhileNotDone
  0006 B6 0A       HS             jF0     J3
  0008 04 0D                      jmp     JZ
  000A             J3             ...             ;Programm-
                                  ...             ;zeilen
  000B 04 06       EndWhile       jmp     HS
  000D             JZ             nop

Während beim 8048 das allgemeine Flag F0 als Done-Flag dient, wird beim 8051 die Bitadresse 00h verwendet. Weitere Strukturen lassen sich aus den Kommentaren in der Übersetzungstabelle entnehmen.

 Assemblerlisting der While-Schleife in MC51

  0002 D2 00       Done           setb 00

  0004 C2 00       NotDone        clrb 00

  0006             WhileNotDone
  0006 30 00 03    HS             jnb 00 03
  0009 02 00 0F    JZ             ljmp JZ
                                  ...             ;Programm-
                                  ...             ;zeilen
  000C 02 00 06    EndWhile       ljmp    HS
  000F             JZ             nop

6. Speichernutzung

Der Makrocompiler verwendet eine feste Zuordnung von Adreßbereichen und vordefinierten Programmstruktuen. Dies erleichtert die sichere Programmierung, weil Adressenkonflikte nahezu ausgeschlossen sind. Für eigene Er-weiterungen oder zusätzliche Programmteile in Assembler ist es jedoch wichtig, die Speicherbelegung zu kennen. Sie unterscheidet sich je nach Zielprozessor, wobei MC535 sich an die Speicherbelegung von MC51 hält.

    Internes RAM  8048                  Externes RAM  8048
 +-------------------------------+   +-------------------------------+
 ¦ 3Fh                           ¦   ¦ 03FFh                         ¦
 ¦ ...      MEM-Speicher 0...31  ¦   ¦ ...    Programmcode           ¦
 ¦ 20h      reserviert           ¦   ¦ 0009h                         ¦
 +-------------------------------¦   +-------------------------------¦
 ¦ 1Fh      Registerbank 1       ¦   ¦ 0008h  frei für               ¦
 ¦ ...      Count1...Count8      ¦   ¦ ...    Interrupt-Vektoren     ¦
 ¦ 18h      Loop1...Loop8        ¦   ¦ 0000h  Reset-Vektor           ¦
 +-------------------------------¦   +-------------------------------+
 ¦ 17h                           ¦
 ¦ ...      Stack für 8 Ebenen   ¦
 ¦ 08h                           ¦
 +-------------------------------¦
 ¦ 07h R7   reserviert für       ¦
 ¦ ...      Systemroutinen       ¦
 ¦ 00h R0   R0, R6 gesperrt      ¦
 +-------------------------------+

    Internes RAM  8051                  Externes RAM  8051
 +-------------------------------+   +-------------------------------+
 ¦ 7Fh                           ¦   ¦ 7FFFh                         ¦
 ¦ ...      Stack für 16 Ebenen  ¦   ¦ ...    Datenspeicher          ¦
 ¦ 60h                           ¦   ¦ 2000h                         ¦
 +-------------------------------¦   +-------------------------------¦
 ¦ 5Fh                           ¦   ¦ 1FFFh                         ¦
 ¦ ...      MEM-Speicher 0...47  ¦   ¦ ...    Programmcode           ¦
 ¦ 30h      reserviert           ¦   ¦ 0033h                         ¦
 +-------------------------------¦   +-------------------------------¦
 ¦ 2Fh      Bitadressen 0...7F   ¦   ¦ 0032h  frei für               ¦
 ¦ ...      reserviert           ¦   ¦ ...    Interrupt-Vektoren     ¦
 ¦ 20h      Bit 00h gesperrt     ¦   ¦ 0000h  Reset-Vektor           ¦
 +-------------------------------¦   +-------------------------------+
 ¦ 1Fh                           ¦
 ¦ ...      reserviert           ¦
 ¦ 10h                           ¦
 +-------------------------------¦
 ¦ 0Fh      Count1 ... Count8    ¦
 ¦ ...      Loop1 ... Loop8      ¦
 ¦ 08h                           ¦
 +-------------------------------¦
 ¦ 07h R7   reserviert für       ¦
 ¦ ...      Systemroutinen       ¦
 ¦ 00h R0   R0, R7 gesperrt      ¦
 +-------------------------------+

7. Download-Protokolle

Die Übertragung eines compilierten Programms erfolgt nach einem festgelegten Protokoll, das im Option-Menü ausgewählt werden kann. Die Entwicklungssysteme ES48 und RS51 verwenden das Protokoll 1. Hierbei wird über zwei Handshakeleitungen der seriellen Schnittstelle ein Reset ausgelöst (RTS) und eine Umschaltung in den Down-load-Modus des Systems (DTR) vorgenommen. Die im Option-Menü einstellbare Delay-Zeit ist nur im Protokoll 1 wirksam und dient der verlangsamten Übertragung in EEPROMs im ES48 und ES51.

Download Protokoll 1 für ES48 und ES51:

  - RTS = 1, Reset
  - DTR = 1, Download-Modus einschalten
  - RTS = 0, Reset beenden
  - 100ms warten
  - Übertragung der Programmbytes über TXD mit 9600 Baud
    (nach jedem Byte ein Delay von 0...20ms einhalten)
  - RTS = 1, Reset
  - DTR = 0, Download-Modus ausschalten
  - RTS = 0, Reset beenden

Alle folgenden Modi sind für das Entwicklungssystem ES535 vorgesehen. Im Protokoll 2 wird der Betriebsmodus 0 unterstützt, bei dem Software im RAM-Bereich ab 8000h gestartet wird. Für den Ladevorgang wird das RAM als Datenspeicher im Adreßbereich 0000h bis 7FFFh angesprochen.

Download Protokoll 2 für ES535, Modus 0:

  - RTS = 1, Master-Reset
  - RTS = 0, Reset beenden
  - 100ms warten
  - Download des Programms ab der RAM-Adresse 0000h
  - Programmstart bei Adresse 8000h

Der Betriebsmodus 1 des ES535 arbeitet ohne EPROM und stellt jeweils 16kB Daten- und Programmspeicher ab Adresse 0000h bereit. Das Download-Protokoll 2 schaltet diesen Modus durch einen Programmsprung nach 7400h ein. Er eignet sich zur Programmentwicklung für EPROM-basierte 8051- und 80535-Systeme, die einen vergleich-baren Speicheraufbau besitzen. Alle Makrobefehle in MC535.TAB, die auf das System-EPROM zurückgreifen, dürfen hier nicht verwendet werden.

Download Protokoll 3 für ES535, Modus 1:

  - RTS = 1, Master-Reset
  - RTS = 0, Reset beenden
  - 100ms warten
  - Download des Programms ab der RAM-Adresse 0000h
  - Sprungbefehl (ljmp 0000h) nach 3400h laden
  - Programmsprung zur Adresse 7400h

Das Download-Protokoll 4 unterstützt den Modus 2 des ES535. Der Programmcode beginnt ebenfalls ab Adresse 0000h im RAM, wobei jedoch das ganze RAM als gemeinsamer Programm- und Datenspeicher fungiert.

Download Protokoll 4 für ES535, Modus 2:

  - RTS = 1, Master-Reset
  - RTS = 0, Reset beenden
  - 100ms warten
  - Download des Programms ab der RAM-Adresse 0000h
  - Sprungbefehl (ljmp 0000h) nach 7800h laden
  - Programmsprung zur Adresse 7800h

Die gesamte Konfiguration des Compilers und des Download- Protokolls erfolgt im Option-Menü und kann in der Datei MC.CFG abgespeichert werden. Hier gibt es zahlreiche Möglichkeiten der Anpassung an das Zielsystem. Als Beispiel seien hier die erforderlichen Einstellungen für die Entwicklung von 8051-Programmen auf dem ES535 gezeigt. Obwohl das ES535 den 80535-Prozessor verwendet, wird hier der 8051 mit der Tabelle MC51.TAB eingetragen. Der Programmcode beginnt bei 0000h und muß mit dem Download-Protokoll 3 in das ES535 geladen werden. Falls das Zielsystem getrennten Programm- und Datenspeicher verwendet, sollte das Protokoll 4 gewählt werden.

8. Literatur

Das folgende Buch aus dem Franzis-Verlag beschreibt ausführlich die Arbeit mit dem Makrocompiler und den Ent-wicklungssystemen:

B. Kainka, Erfolgreich Messen, Steuern und Regeln mit Mikrocontrollern, Franzis 2. Auflage 1998

Die Entwicklungssysteme ES48, ES51 und ES535 werden in technischen Anwenderhandbüchern beschrieben, die auch einzeln bei Modul-Bus bezogen werden können. Die entsprechenden Texte finden sich außerdem auf der MC-Programmdiskette im Verzeichnis ES.

Das Inteface-System SIOS von Modulbus kann ebenfalls mit dem Makrocompiler programmiert werden. Nähere Informationen zu SIOS und passende MC-Steuerdateien befinden sich auf der MC-Diskette im Verzeichnis SIOS.