. |
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
Erfahrungen nach geringer Einarbeitungszeit bereits einfache Programme entwickeln. Insbesondere kleine und mittlere Aufgaben lassen sich daher mit sehr geringem Zeitaufwand lösen. Der erzeugte Programmcode ist extrem kurz und schnell, so
dass 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 im Download-Bereich geladen werden:
|
Handbuch zur MC-Vollversion
Das Programm MC.EXE stellt eine integrierte Entwicklungsumgebung mit Editor, Compiler, Übertragungs-
programm, Terminalprogramm und Code-Editor für beliebige Mikrocontroller-Systeme mit 8048-, 5051- und 80535-Prozessoren bereit. Insbesondere werden die Entwicklungssysteme ES48, ES51 und ES535 unterstützt.
Der Makrocompiler ist für die Mikrocontroller 8048, 8051 oder 80535 konfigurierbar. Alle relevanten Einstellungen sind in der Konfigurationsdatei MC.CFG eingetragen und können im Option-Menü verändert werden. Bei der Auslieferung 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
|
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.
- Ein Quelltext wird geladen oder neu eingegeben.
- Das Programm wird kompiliert. Falls der Compiler einen Fehler erkennt, wird mit einer Fehlermeldung in den Editor verzweigt. Ein übersetztes Programm kann als Binärfile abgespeichert werden.
- Wenn ein Entwicklungssystem (ES48...ES535) angeschlossen ist, kann das kompilierte Programm ins RAM des Systems übertragen und unmittelbar gestartet werden.
- Zu Testzwecken kann über die Terminalfunktion ein Datenaustausch mit dem Entwicklungssystem durchgeführt werden.
Bei Bedarf läßt sich das kompilierte Programm im Hexedit-Menü editieren. Es können auch bereits kompilierte 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,
dass 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
muss dagegen im Standard-Modus 0 die Startseite 128 gewählt werden. Die Startseite kann als Hexadezimalzahl in der Schreibweise $80 eingegeben 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
Übersetzungstabelle 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
dass 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. |
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 Variable. Daneben verwenden viele Rechen- operationen das Register B. Das folgende Beispiel zeigt den direkten Zugriff auf einen Port des Mikrocontrollers. Kommentartexte 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:
- Makrobefehle und ihre Parameter müssen durch Leerzeichen getrennt sein.
- Byte-Konstanten können dezimal (255), hexadezimal
(FFh) oder binär (11111111b) geschrieben werden.
- MC arbeitet mit den globalen Byte-Variablen A (=Akku) und B.
- Alle Schreibzugriffe auf Speicher, Register und Ports sind durch Wr gekennzeichnet und verwenden den Akku A.
- Alle Lesezugriffe sind durch Rd gekennzeichnet und verwenden den Akku A.
- Es können Prozeduren mit eigenem Namen gebildet werden, die dann wie vordefinierte Makrobefehle eingesetzt werden. Jeder Prozedur kann mit einer Byte-Konstanten aufgerufen werden, die zuvor in den Akku geladen wird.
- Zusätzliche MEM-Register stehen als globale Hilfsvariablen zur Verfügung. Als höhere Programmstrukturen existieren Zählschleifen, bedingte Wiederholschleifen und bedingte Prozeduraufrufe.
- Jede Zeile darf für den 8048 maximal einen Befehl und einen Parameter enthalten. Für den 8051 existieren auch Drei-Byte-Kommandos, d.h einige Befehle verlangen zwei Parameter. Bei bedingten Aufrufen können bis zu vier Parameter in einer Zeile stehen.
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 wahlweise auch als Konstante hinter den Befehl geschrieben werden. In diesen Fall wird das Byte zuerst in A geschrieben. 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 Zeichen 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 Programmierung 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. |
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 unterscheidet 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 vornehmen. 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 Entwicklungssystem 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 Runtime-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 empfangen 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 If A=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 gedrü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
|
|
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 Tastendrucks 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 nachträ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. Regelmäß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 verzichtet 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 Aufnahme 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. |
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 Makrobefehle 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ü einzutragen.
Befehlserweiterungen setzen eine genaue Kenntnis des Makrocompilers voraus. Es ist nützlich, sich die bereits definierten 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 verdeutlicht, daß die Portzugriffe über den Akku laufen. Der Makrobefehl WrP1 enthält aber zusätzlich die spezielle Compiler-Anweisung PA (für Parameter- Übergabe). PA bewirkt, daß der Compiler überprüft, ob hinter dem Makrobefehl 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 Wirkung, 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 Assembleranweisungen bestehen können. Etwas komplizierter wird es, wenn der Compiler höhere Programmstrukturen wie z.B. Wiederholschleifen oder Fallabfragen übersetzen soll. In diesem Fall müssen nämlich Sprungadressen berechnet werden, 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 unterscheiden:
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
|
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 Erweiterungen 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 ¦
+-------------------------------+
|
Download-Protokolle
Die Übertragung eines kompilierten 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 Download-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 vergleichbaren 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
muss 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. |
Literatur
Das folgende Buch beschreibt ausführlich die Arbeit mit dem Makrocompiler und den Entwicklungssystemen:
B. Kainka, Erfolgreich Messen, Steuern und Regeln mit Mikrocontrollern, Franzis 2. Auflage 1998
Nähere Informationen und zwei Kapitel im Volltext auf der Homepage von B. Kainka. Die Entwicklungssysteme ES48, ES51 und ES535 werden in technischen Anwenderhandbüchern beschrieben. Das Inteface-System SIOS kann ebenfalls mit dem Makrocompiler programmiert werden. |
|
|
. |