Assembler-Direktiven - Netzmafia
Assembler-Direktiven - Netzmafia
Assembler-Direktiven - Netzmafia
Erfolgreiche ePaper selbst erstellen
Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.
Mikrocomputertechnik
Mikrocomputertechnik<br />
Table of Contents<br />
Mikrocomputertechnik................................................................................................................1<br />
Mikrocomputertechnik..........................................................................................................................1<br />
Inhalt............................................................................................................................................1<br />
1 Einführung.........................................................................................................................1<br />
2 Hardware von Mikrocomputern.........................................................................................1<br />
3 Programmierung des Mikroprozessors 68HC11................................................................1<br />
4 Prozessor des Systems 68HC11.........................................................................................1<br />
5 Peripherie des Systems 68HC11........................................................................................2<br />
6 Ausblick: andere Controller...............................................................................................2<br />
Anhang..................................................................................................................................2<br />
Jack Kilby: der Vater des Mikrochips..................................................................................3<br />
Mikrocomputertechnik..........................................................................................................4<br />
Prolog.......................................................................................................................................................6<br />
1 Einführung...........................................................................................................................................7<br />
1.1 Von-Neumann-Architektur....................................................................................................8<br />
Vorteile der v. Neumann-Architektur:................................................................................11<br />
1.2 Befehlszyklus......................................................................................................................11<br />
Ablauf des Befehlszyklus...................................................................................................13<br />
1.2 Erhöhung der Leistungsfähigkeit........................................................................................14<br />
Vermeiden oder Mildern des v. Neumann-Flaschenhalses.................................................14<br />
1.4 Die Harvard-Architektur.....................................................................................................16<br />
RISC "Reduced Instruction Set Computer"........................................................................16<br />
1.5 Begriffe................................................................................................................................16<br />
Mikrocomputer:..................................................................................................................16<br />
1.6 Entwicklung.........................................................................................................................17<br />
Mikrocomputer als Ersatz festverdrahteter Logik..............................................................18<br />
Einsatzbeispiele:.................................................................................................................19<br />
Mikrocomputer als Universalrechner.................................................................................19<br />
1.7 Embedded Systems..............................................................................................................22<br />
Design von Embedded Systems..........................................................................................22<br />
Mikrocomputertechnik........................................................................................................23<br />
2 Hardware von Mikrocomputern......................................................................................................23<br />
2.1 Struktur eines Mikrocomputers...........................................................................................23<br />
Prinzipieller Aufbau............................................................................................................23<br />
Der System-Bus..................................................................................................................24<br />
Bus-Treiber.........................................................................................................................25<br />
Systembeispiel....................................................................................................................25<br />
2.2 Mikroprozessor....................................................................................................................26<br />
Versorgung und Steuerung.................................................................................................26<br />
Steuerungs-Signale.............................................................................................................28<br />
2.3 Arbeitsspeicher....................................................................................................................28<br />
Speicher-Bausteine.............................................................................................................29<br />
Zusammenschalten von Speicherbausteinen.......................................................................30<br />
2.4 Ein-/Ausgabe-Bausteine......................................................................................................30<br />
Struktur von E/A-Bausteinen..............................................................................................33<br />
Steuerung von E/A-Bausteinen...........................................................................................34<br />
Anschluß von E/A-Bausteinen............................................................................................35<br />
Programmgesteuerter E/A-Transfer (Polling).....................................................................36<br />
i
Mikrocomputertechnik<br />
Table of Contents<br />
2 Hardware von Mikrocomputern<br />
Direktspeicherzugriff (DMA = Direct Memory Access)....................................................37<br />
2.5 Timer (Zeitgeber)................................................................................................................38<br />
2.6 Systemkonfigurationen........................................................................................................38<br />
Aufteilung des Adreßraums................................................................................................39<br />
Systembeispiel....................................................................................................................40<br />
Beispiele zur Systemkonfiguration.....................................................................................42<br />
2.7 Programmunterbrechungen.................................................................................................45<br />
Unterbrechungsgesteuerter E/A-Transfer...........................................................................46<br />
Mikrocomputertechnik........................................................................................................47<br />
3. Programmierung des Mikroprozessors 68HC11...........................................................................47<br />
3.1 Überblick.............................................................................................................................47<br />
Programmiermodell............................................................................................................48<br />
Einteilung der Befehle........................................................................................................49<br />
3.2 Adressierungsarten..............................................................................................................50<br />
Konstanten-Adressierung (Immediate Addressing)............................................................50<br />
Absolute Adressierung........................................................................................................51<br />
Implizite Adressierung (Inherent Addressing)....................................................................51<br />
Indizierte Adressierung (Indexed Addressing)...................................................................52<br />
3.3 <strong>Assembler</strong>-Befehlsaufbau....................................................................................................54<br />
1. Quellcode........................................................................................................................55<br />
3.4 Pseudobefehle (<strong>Assembler</strong>-<strong>Direktiven</strong>)...............................................................................56<br />
Speicher-Organisation.........................................................................................................57<br />
Grundsätzlicher Aufbau eines 68HC11-<strong>Assembler</strong>programms..........................................59<br />
3.5 CPU-Befehle........................................................................................................................59<br />
Transport-Befehle...............................................................................................................61<br />
Arithmetische Befehle........................................................................................................64<br />
Logische Befehle................................................................................................................66<br />
Schiebe- und Rotationsbefehle...........................................................................................68<br />
Test- und Statusregisterbefehle...........................................................................................69<br />
Bitorientierte Befehle..........................................................................................................70<br />
Beeinflussung des Systemzustands.....................................................................................70<br />
Sprungbefehle.....................................................................................................................74<br />
Unterprogrammsprünge (jump/branch to subroutine)........................................................76<br />
Programmunterbrechungsbefehle.......................................................................................76<br />
Reine Verzögerungsbefehle................................................................................................76<br />
3.6 Stapelspeicher (Stack).........................................................................................................77<br />
Befehle für den Stack-Zugriff.............................................................................................77<br />
Anwendung des Stack.........................................................................................................78<br />
3.7 Unterprogramme (Subroutines)...........................................................................................79<br />
Unterprogramm-Sprungbefehle..........................................................................................79<br />
Parameter-Übergabe...........................................................................................................81<br />
3.8 Interrupts (Programmunterbrechungen)..............................................................................82<br />
Interruptsystem des 68HC11:.............................................................................................84<br />
Mikrocomputertechnik........................................................................................................85<br />
4. Bausteine des Systems M68HC11...................................................................................................85<br />
4.1 Mikroprozessor 68HC11.....................................................................................................85<br />
Der Prozessor......................................................................................................................86<br />
Die wichtigsten Anschlußpins............................................................................................87<br />
Reset....................................................................................................................................88<br />
ii
Mikrocomputertechnik<br />
Table of Contents<br />
4. Bausteine des Systems M68HC11<br />
Der Bus...............................................................................................................................88<br />
Der Speicher........................................................................................................................89<br />
Asynchrone serielle Schnittstelle........................................................................................89<br />
Timer-System......................................................................................................................90<br />
Digitale Ein- und Ausgänge................................................................................................91<br />
Impulszähler........................................................................................................................91<br />
Analog-Digital-Wandler.....................................................................................................91<br />
Synchrone serielle Peripherieschnittstelle..........................................................................92<br />
4.2 Typische Anwendungsschaltung.........................................................................................93<br />
Stückliste für das Mikrocontroller-Board...........................................................................94<br />
4.3 Praktikumssystem PS11 mit M68HC11A0.........................................................................94<br />
Blockschaltung....................................................................................................................94<br />
Praktikumsrechner mit Experimetierboard.........................................................................95<br />
Der ZWERG11plus.............................................................................................................96<br />
Anschluß des "Zwerg 11" an den PC..................................................................................96<br />
Belegung des Schnittstellenkabels und des Experimentierboards......................................97<br />
Bootloader Firmware for MC68HC11A8 (essentials)........................................................98<br />
Mikrocomputertechnik........................................................................................................99<br />
5. Peripherie des Systems M68HC11..................................................................................................99<br />
5.1 Peripherie-Register............................................................................................................100<br />
5.2 Parallele Schnittstellen......................................................................................................101<br />
Port A................................................................................................................................102<br />
Port B und STRB..............................................................................................................102<br />
Port C und STRA..............................................................................................................103<br />
Port D................................................................................................................................104<br />
Port E................................................................................................................................104<br />
Programmbeispiele...........................................................................................................107<br />
5.3 Serielle Schnittstellen........................................................................................................107<br />
SCI (serial communication interface asynchronous)........................................................110<br />
SPI (serial peripherial interface synchronous)..................................................................110<br />
Programmbeispiele...........................................................................................................114<br />
5.4 Zähler.................................................................................................................................116<br />
Der Timer..........................................................................................................................126<br />
5.5 Geschützte Register...........................................................................................................127<br />
5.6 Interrupts............................................................................................................................128<br />
Auslösen einer Unterbrechung..........................................................................................137<br />
Mikrocomputertechnik......................................................................................................138<br />
6 Ausblick: andere Controller...........................................................................................................138<br />
6.1 Atmel-Mikrocontroller......................................................................................................138<br />
Beispiel: Blockschaltung des ATTtiny.............................................................................142<br />
6.2 PIC-Microcontroller von Microchip..................................................................................143<br />
Beispiel: Blockschaltung und Pins des PIC16F84............................................................147<br />
6.3 MSP-430-Microcontroller von Texas Instruments............................................................147<br />
Blockschema des MSP430................................................................................................149<br />
6.4 8051-Microcontroller........................................................................................................149<br />
Blockschema des 8051......................................................................................................150<br />
Mikrocomputertechnik......................................................................................................151<br />
iii
Mikrocomputertechnik<br />
Table of Contents<br />
7 Anhang..............................................................................................................................................151<br />
7.1 Literatur und Links............................................................................................................151<br />
Literatur.............................................................................................................................152<br />
68HC11 Links...................................................................................................................153<br />
7.2 Tips zur Programmierung..................................................................................................154<br />
Grundlegende Prinzipien:.................................................................................................154<br />
Programm-Dokumentation...............................................................................................155<br />
7.3 ASCII-Tabelle...................................................................................................................155<br />
ASCII Tabelle (sedezimal)...............................................................................................155<br />
7.4 I/O-Register.......................................................................................................................160<br />
7.5 Interrupt-Adressen.............................................................................................................160<br />
7.6 Das Motorola-S-Format.....................................................................................................161<br />
Copyright © FH München, FB 04, Prof. Jürgen Plate......................................................161<br />
Mikrocomputertechnik......................................................................................................162<br />
Programmbeispiel-Sammlung...........................................................................................................162<br />
Den folgenden "Programmschnipseln" fehlt noch das "Drumrum" (Definitionen von<br />
Variablen, Hauptprogramm, usw.). Sie dienen der Illustration verschiedener<br />
Programmiertechniken in <strong>Assembler</strong>.....................................................................................162<br />
Allgemeiner Vorspann für's Praktikum............................................................................170<br />
Nützliche Unterprogramme..............................................................................................175<br />
Komplette Programmbeispiele..........................................................................................184<br />
Mikrocomputertechnik......................................................................................................185<br />
Praktikum Mikrocomputer...............................................................................................................185<br />
Allgemeines.............................................................................................................................185<br />
Installation der IDE-Software...........................................................................................185<br />
Einschalten und Starten.....................................................................................................186<br />
Programm-Namen und Ordner SAVE..............................................................................186<br />
Beenden und Abschalten...................................................................................................186<br />
Bearbeiten eines Quellprogramms....................................................................................187<br />
Übersetzen eines Quellprogramms (source code).............................................................188<br />
Simulieren eines Zielprogramms (object code)................................................................190<br />
Tools → Load in Target.....................................................................................................190<br />
Arbeiten mit der seriellen Schnittstelle.............................................................................190<br />
Hinweise zur Programmerstellung....................................................................................191<br />
Tools → Terminal..............................................................................................................192<br />
Belegung des Experimentier-Boards................................................................................193<br />
Beschaltung der Eingänge des 68HC11............................................................................195<br />
Anhang: Binär zu ASCII-Decodierung (hx4a).................................................................196<br />
Mikrocomputertechnik......................................................................................................197<br />
Praktikum Mikrocomputer...............................................................................................................197<br />
Versuch 1: Parallel-Ports, Unterprogramme, Zeitverzögerungen...........................................198<br />
Versuch 2: Parallel-Ports, 7-Segmentanzeige, Tabellenzugriff..............................................200<br />
Versuch 3: Serielle Schnittstelle, ASCII-Zeichenketten.........................................................202<br />
Versuch 4: Zähler, bedingte Unterbrechungen........................................................................203<br />
Anhang: Binär zu ASCII-Decodierung (hx4a).................................................................title<br />
iv
Inhalt<br />
1 Einführung<br />
1. Von-Neumann-Architektur<br />
2. Verbesserung der Leistungsfähigkeit<br />
3. Befehlszyklus<br />
4. Harvard-Architektur<br />
5. Begriffe<br />
6. Entwicklung<br />
7. Embedded Systems<br />
2 Hardware von Mikrocomputern<br />
1. Struktur eines Mikrocomputers<br />
2. Mikroprozessor<br />
3. Arbeitsspeicher<br />
4. E/A-Bausteine<br />
5. Timer (Zeitgeber)<br />
6. System-Konfiguration<br />
Mikrocomputertechnik<br />
3 Programmierung des Mikroprozessors 68HC11<br />
1. Überblick<br />
2. Adressierungsarten<br />
3. <strong>Assembler</strong>-Befehlsaufbau<br />
4. Pseudobefehle (<strong>Assembler</strong>-<strong>Direktiven</strong>)<br />
5. CPU-Befehle<br />
6. Stapelspeicher (Stack)<br />
7. Unterprogramme (Subroutines)<br />
8. Interrupts (Programmunterbrechungen)<br />
4 Prozessor des Systems 68HC11<br />
1. Mikroprozessor 68HC11<br />
2. Typische Anwendungsschaltung<br />
3. Praktikumssystem PS11 mit M68HC11A0<br />
5 Peripherie des Systems 68HC11<br />
1. Peripherie-Register<br />
2. Parallele Schnittstellen<br />
3. Serielle Schnittstellen<br />
4. Zähler<br />
5. Geschützte Register<br />
6. Interrupts<br />
Mikrocomputertechnik 1
6 Ausblick: andere Controller<br />
1. Atmel AVR<br />
2. Microchip PIC<br />
3. Texas Instruments MSP430<br />
4. Intel 8051<br />
Anhang<br />
1. Literatur<br />
2. Tips zur Programmierung<br />
3. ASCII-Tabelle<br />
4. I/O-Register<br />
5. Interrupt-Adressen<br />
6. Das Motorola S-Format<br />
7. Programmbeispiel-Sammlung<br />
8. 68HC11 Kurz-Befehlstabelle (PDF, 80 KByte)<br />
9. 68HC11 A8 Reference Manual (PDF, 3,8 MByte)<br />
10. 68HC11 Reference Manual (PDF, 7,6 MByte)<br />
11. What's a Microcontroller? (Parallax Inc., 5,15 MByte)<br />
12. Hinweise zur Software-Sammlung<br />
13. Praktikumsanleitung<br />
14. Versuche 1 bis 4<br />
15. Muster-Prüfungsaufgaben<br />
Skript als PDF (aus HTML konvertiert)<br />
Download des gesamten Skripts<br />
Mikrocomputertechnik<br />
Mein besonderer Dank gilt dem Kollegen Prof. Peter Schwalb, der mir viele seiner Grafiken zur<br />
Verfügung gestellt hat.<br />
Jack Kilby: der Vater des Mikrochips<br />
Jack Kilby baute 1958 den ersten integrierten Schaltkreis<br />
zusammen und legte damit die Grundlage für alle modernen<br />
Computerchips. Und das ist nur die bekannteste seiner<br />
Erfindungen.<br />
Der Physik-Nobelpreisträger Jack Kilby starb am 20.6.2005 im Alter von 81 Jahren nach einem<br />
Krebsleiden in Dallas.<br />
Bereits am 12. September 1958 präsentierte der Physiker den ersten Mikrochip in den Labors von<br />
Texas Instruments. Schon der erste Chip war nicht größer als eine Heftklammer. Mit geliehenen<br />
Werkzeugen hatte Kilby den ersten integrierten Schaltkreis konstruiert.<br />
Für Texas Instruments entwickelte Kilby Chipanwendungen für Militär, Industrie und Wirtschaft. Von<br />
1978 bis 1984 war der Amerikaner Professor an der Texas A&M Universität. In den letzten Jahren<br />
6 Ausblick: andere Controller 2
machte Kilby außerdem mit der Entwicklung verbesserter Systeme zur solaren Energiegewinnung von<br />
sich reden.<br />
Kilby besaß 60 Patente und ermöglichte unter anderem die Entwicklung des Taschenrechners und des<br />
Handys. "Es gibt heute praktisch kaum noch einen Bereich des Lebens, der nicht irgendwie durch die<br />
integrierte Halbleiterschaltung beeinflusst wird", sagte Richard Templeton, President von Texas<br />
Instruments.<br />
Im November 1993 erhielt Kilby das japanische Pendant zum Nobelpreis, den Kyoto-Preis. Ein<br />
Mitarbeiter von TI soll über ihn gesagt haben: "Jack hat die angeborene Fähigkeit, Probleme anders zu<br />
sehen, als es die meisten von uns tun. Ich denke, dass der neugierige Geist des Erfinders dahinter<br />
steckt."<br />
Nach der Verleihung des Nobelpreises im Jahr 2000 verbrachte Kilby seine letzten Jahre als Berater<br />
von Texas Instruments und auf Vortragsreisen um die Welt. Kilby hinterlässt zwei Töchter, einen<br />
Schwiegersohn und fünf Enkeltöchter.<br />
Im Jahr 2000 war Kilby zusammen mit dem Deutschen Herbert Kroemer und dem Russen Zhores<br />
Alferov der Physik-Nobelpreis verliehen worden. Kilby wurde für seine bahnbrechenden Arbeiten am<br />
Mikrochip ausgezeichnet. Der Inhaber von 60 Patenten war auch an der Entwicklung des<br />
Taschenrechners und des Thermoprinters beteiligt.<br />
Kilbys erster integrierter Schaltkreis<br />
hatte optisch keine große Ähnlichkeit mit<br />
heutigen Chips<br />
Copyright © FH München, FB 04, Prof. Jürgen Plate<br />
Letzte Aktualisierung: 07. Okt 2012<br />
Mikrocomputertechnik<br />
In seinem alten Notizbuch befindet sich<br />
das Originaldesign von Kilbys Chip<br />
Mikrocomputertechnik<br />
Prof. Jürgen Plate<br />
Jack Kilby: der Vater des Mikrochips 3
Prolog<br />
In dieser Vorlesung erfahren Sie, wie Computer funktionieren und dass es sich bei einem Computer<br />
lediglich um ein synchrones Schaltwerk oder einen Verbund mehrerer synchroner Schaltwerke<br />
handelt. Die Programmierung erfolgt dabei in einer maschinennahen Sprache, bei der die elementaren<br />
Befehle des Computers lediglich durch mnemotechnische Bezeichnungen etwas verständlicher sind,<br />
als der reine Binärcode. Das Programm zum Übersetzen der sogenannten Mnemonics in den<br />
Binärcode wird "<strong>Assembler</strong>" genannt, weshalb die Programmiersprache in der Regel auch<br />
"assemblersprache" heisst.<br />
Dass die Vorstellungen /uuml;ber Mikrocpmputer, PCs und sogenannte Heimcomputer früher nicht<br />
immer ganz klar waren, beweist das folgende Bild, dass ich samt Bildunterschrift im Internet fand. Es<br />
sollte angeblich aus der Zeitschrift "Popular Electronics" stammen:<br />
Sehr viel sp&aumL;ter entpuppte sich das Bild als Hoax, eine Photomontage. Es handelt sich um das<br />
Photo eines U-Boot-Kontrollstands (Stromversorgung, Dampf etc.) aus einer Ausstellung des<br />
Smithsonian's National Museum of American History, das leicht modifiziert und in ein Graustufenbild<br />
umgewandelt wurde:<br />
Prolog 4
Mikrocomputertechnik<br />
Siehe auch:<br />
http://www.museumofhoaxes.com/hoax/photo_database/image/home_computer_of_the_future/<br />
Auch heute sollten Sie nicht immer alles glauben, was Ihnen über die Leistung und Möglichkeiten von<br />
Computern erzählt wird.<br />
Prolog 5
1 Einführung<br />
Mikro-Computer sind sehr kompakte Computersysteme auf der Basis integrierter Steuer- und<br />
Verarbeitungsbausteine (Mikroprozessoren, Mikrocontroller) und Speicher (VLSI und<br />
ULSI-Bausteine) für allgemeine und spezielle DV-Anwendungen (z. B. Steuerung, Regelung):<br />
• Tisch-/Personal-Computer (PC),<br />
• Einplatinen-Computer (embedded systems),<br />
• Ein-Chip-Computer.<br />
Der folgende Überblick zeigt die Entwicklung des Computers seit Mitte des 20. Jahrhunderts. Mit<br />
Fortschreiten der Integration wurden die Rechner auch immer billiger und kleiner.<br />
Zeitraum Schaltungstechnik Verbreitung Programmierung Geschwindigkeit<br />
1945-1955 Relais, Röhren<br />
wenige<br />
Exemplare<br />
Steckbrett,<br />
Maschinencode<br />
10 3 Op./s<br />
1955-1965 Transistoren, Dioden Hunderte <strong>Assembler</strong>, FORTRAN 10 4 Op./s<br />
1965-1980 Integrierte Schaltungen Tausende<br />
ab 1980<br />
Hoch integrierte<br />
Schaltungen (VLSI)<br />
Millionen<br />
höhere<br />
Programmierspachen<br />
höhere<br />
Programmiersprachen<br />
10 6 Op./s<br />
> 10 7 Op./s<br />
Handelte es sich bei den ersten Systemen noch um nur in wenigen Stückzahlen gefertige Geräte mit<br />
hohen Anschaffungs- und Betriebskosten sowie riesigem Platzbedarf und geringer Zuverlässigkeit, so<br />
beanspruchen die die ab 1955 entwickelten Maschinen ihre Rolle als erste kommerziell erfolgreiche<br />
Systeme.<br />
Die Fortschritte der Fertigungstechnik erlauben eine immer weiter voranschreitende Packungsdichte<br />
der integrierten Schaltungen und verbilligen gleichzeitig deren Herstellung. Mit dem Personal<br />
Computer (PC) und den Heimcomputern (denen nur eine kurze Lebendauer beschieden war) begann<br />
der Einzug der Mikrocomputer und Mikrocontroller in alle Lebensbereiche. Heute enthält<br />
beispielsweise ein Mittelklassse-PKW eine zweistellige Anzahl vom Mikrocontrollern.<br />
Parallel zur Entwicklung der CPU entwickelte sich die Landschaft der zugehörigen Peripherie. Die<br />
erste Rechnergeneration verfügte noch über keine dedizierten Peripheriegeräte. Eingaben wurden<br />
direkt, durch Schalttafeln und Erstellung von Hardwareverbindungen, an der Maschine vorgenommen.<br />
Ausgaben erfolgten über Lampen oder andere Signalgeber. Ab den 1955er Jahren finden sich<br />
zunehmen externe Geräte zur Abwicklung und dauerhaften Speicherung der verarbeiteten Daten und<br />
Programme. Es begann mit Lochstreifen, die später durch Lochkarten abgelöst wurden. Als Ein- und<br />
Ausgabegerät kamen modifizierte Fernschreiber oder entsprechend angepasste elektrische<br />
Schreibmaschinen hinzu. Später wurden sie von Textbildschirmen abgelöst. Bei Embedded Systemen<br />
(Computersysteme, die in Geräten zur Steuerung dienen) gibt es meist keine Peripherie im klassischen<br />
Sinn, sondern dort fungieren Sensoren und Aktoren (Relais, Motoren etc.) als Ein- und Ausgabe.<br />
Wesentliches Element einer Rechnerarchitektur ist der Prozessor (engl. central processing unit, CPU),<br />
der die Hauptteile der Verarbeitung übernimmt. Der stetiger Leistungszuwachs der CPU richtete sich<br />
in der Vergangenheit nach dem Moore'schen Gesetz, das auf Basis empirischer Daten eine<br />
Verdopplung der Transistorenanzahl pro Chip (und damit der Leistungsfähigkeit) alle anderthalb Jahre<br />
voraussagt.<br />
Aktuelle Prozessoren folgen dem folgenden schematischen Aufbau, der die zentralen<br />
Architekturkomponenten Leitwerk, Rechenwerk (arithmetic and logic unit, ALU), Registersatz und<br />
typischerweise den Mikroprogrammspeicher umfaßt.<br />
1 Einführung 6
Mikrocomputertechnik<br />
Diese, nach dem Erfinder als "von-Neumann-Architektur" bezeichnete, Architektur prägt den Aufbau<br />
von Rechenanlagen seit den 1950er Jahren und gilt im Kern bis heute (siehe unten). Einige Engpässe<br />
der von-Neumann-Architektur beruhen auf der Gleichbehandlung von Daten und darauf arbeitenden<br />
Programmen und der sequenziellen Verarbeitung.<br />
Moderne CPU-Architekturen (z. B. Intel Pentium, AMD Athlon und Power PC) verfügen innerhalb<br />
einer CPU über mehrere Rechenwerke, insbesondere solche für Fest- und Gleitkommaoperationen.<br />
Das Leitwerk steuert den gesamten Verarbeitungsfluss. Zur Regelung der Verarbeitung speichert das<br />
Leitwerk prozessorinterne Zustände (Status von Berechnungen und Fehlerindikatoren) in<br />
CPU-internen Speichern, den sog. Registern.<br />
Der Registersatz wird durch eine Reihe von Speicherzellen, die direkt in der CPU untergebracht sind<br />
realisiert. Diese Speicherform stellt die schnellste und gleichzeitig teuerste Form des Speichers dar.<br />
Register besitzen typischerweise eine feste Länge, die mit der verarbeitbaren Wortlänge der CPU<br />
korrespondiert. Häufig werden die zur Verfügung stehenden Register bezüglich ihrer Funktionsweise,<br />
d.h. ihres Einsatzgebietes unterschieden, da oftmals nicht jedes Register für jeden Maschinenbefehl<br />
zur Verfügung steht. Minimalanforderung an einen Registersatz ist die Bereitstellung eines<br />
Befehlszählers (Befehlszeigerregister, engl. Instruction Pointer Register), der die Adresse des<br />
nächsten abzuarbeitenden Befehls enthält.<br />
Darüber hinaus sind Register zur Aufnahme des Rechenergebnisses (Akkumulator) und zur Aufnahme<br />
von Adressen (Stackpointer, Indexregister) sowie ein Status- und Kontrollregister üblich.<br />
1.1 Von-Neumann-Architektur<br />
Im Jahre 1944 legte John von Neumann, ein ehemaliges Mitglied des ENIAC-Projektes, ein<br />
Architektur-Konzept für einen speicherprogrammierten Universalrechner vor. Sein erster Entwurf ist<br />
heute als "von-Neumann-Maschine" oder "von-Neumann-Architektur" bekannt - ein weitsichtiges und<br />
visionäres Konzept, das auch noch aktuellen Computern zugrunde liegt. Eine<br />
Von-Neumann-Maschine weist folgende wichtige Merkmale auf:<br />
1.1 Von-Neumann-Architektur 7
• Steuerwerk, Leitwerk (Befehlsprozessor), das den Programmablauf steuert. Die Befehle<br />
werden interpretiert und deren Ausführung veranlasst, gesteuert und überwacht<br />
(Ablaufsteuerung zur Bearbeitung der Befehle).<br />
• Rechenwerk (Datenprozessor), das die zu bearbeitenden Daten verknüpft und verändert. Dern<br />
Kern bildet die ALU (Arithmetical and Logical Unit) zur Bearbeitung der Daten.<br />
• Speicher, der sowohl Programmbefehle als auch Daten aufnimmt (Hauptspeicher,<br />
Arbeitsspeicher, Main Memory). Die Daten/Befehle liegen binär verschlüsselt, also als<br />
0/1-Folgen vor. Prinzipiell besteht kein Unterschied zwischen Daten und Befehlen.<br />
Unterteilung in Speicherplätze (Speicherzellen, Speicherworte), die über Adressen<br />
angesprochen werden.<br />
• Ein- und Ausgabewerk (E/A-Prozessoren), welche die Schnittstelle zur Außenwelt<br />
(Peripherie) bilden. Zusammen mit den E/A-Geräten besorgen sie die Kommunikation mit der<br />
realen Umwelt.<br />
Leitwerk und Rechenwerk bilden die zentrale Verarbeitungseinheit (CPU, Prozessor).<br />
Die Struktur des Rechners ist unabhängig von dem zu bearbeitenden Problem ( Universalrechner).<br />
Die verschiedenen Aufgaben werden durch entsprechende Programme gelöst. Programme und von<br />
diesen benötigte Daten werden in einem gemeinsamen Speicher abgelegt. Die Speicherplätze sind<br />
gleichlang und werden über Adressen einzeln angesprochen.<br />
Die bedeutendste Neuerung war von Neumanns Idee, Programm und Daten zuerst in den Speicher zu<br />
laden und dann auszuführen. Bis dahin war das Programm noch hardwaremäßig verschaltet oder<br />
wurde über Lochstreifen schrittweise eingelesen und sofort (streng sequentiell) bearbeitet. Nun war es<br />
möglich:<br />
• Sprünge aufgrund logischer Entscheidungen auszuführen<br />
• Programmcode während des Programmablaufes zu modifizieren<br />
Von Neumann erreichte mit seinem Konzept, dass der Rechner selbstständig logische Entscheidungen<br />
treffen kann. Damit ist der Übergang vom starren Programmablauf zur flexiblen Programmsteuerung<br />
vollzogen.<br />
Vorteile der v. Neumann-Architektur:<br />
(Dies ist der Hauptgrund für ihre Langlebigkeit)<br />
Mikrocomputertechnik<br />
• Einfachheit (übersichtlich, minimaler HW-Aufwand)<br />
• maximale Flexibilität (bei genügend elementaren Befehlen)<br />
Vorteile der v. Neumann-Architektur: 8
Nachteile der v. Neumann-Architektur:<br />
• Im Speicher kann man Befehle und Daten nicht unterscheiden.<br />
• nur ein Verbindungsweg zwischen CPU und Speicher (zwischen CPU und Speicher wird<br />
immer nur ein Wort transportiert)<br />
• sequentielle Verarbeitung von Befehl und Datum<br />
Da Daten und Befehle im Speicher gehalten werden, wird die Verbindung und Datenübertragung<br />
zwischen CPU und Speicher bzw. zur Ein-/Ausgabe über den Systembus zum sogenannten<br />
Von-Neumann-Flaschenhals. Jeglicher Datenverkehr von und zur CPU wird über den internen Bus<br />
abgewickelt, dessen Transfergeschwindigkeit langsamer ist, als die Verarbeitungsgeschwindigkeit der<br />
CPU. Dieses Problem versucht man in modernen Prozessoren durch die Verwendung von schnellem<br />
Cache-Speicher, der meist in der CPU integriert ist, abzuschwächen.<br />
Operationsprinzip<br />
Mikrocomputertechnik<br />
Die CPU kann nur elementare, (fest verdrahtete) Befehle verarbeiten ( Maschinenbefehle). Jedes<br />
Programm besteht also aus einer Folge elementarer Befehle. Da im Speicher nicht zwischen Daten<br />
und Befehlen unterschieden wird, muss das Leitwerk entscheiden, ob der Inhalt einer Speicherzelle als<br />
Befehl oder Datum aufzufassen ist. Es gibt somit zwei Zustände des Rechners: Befehl holen<br />
(Interpretieren als Befehl) und Befehl ausführen (Interpretation als Datum). Entsprechend gibt es zwei<br />
Phasen der Programmabarbeitung:<br />
• 1. Phase: Der (durch den sogenannten Befehlszähler) referierte Speicherplatzinhalt wird<br />
geholt und als Befehl interpretiert (Befehlsholphase, instruction fetch)<br />
• 2. Phase: Der Speicherplatzinhalt der durch den Befehl spezifizierten Adresse wird geholt, als<br />
Datum interpretiert und dem Befehl entsprechend verarbeitet (Befehlsausführungsphase,<br />
instruction execution)<br />
Dieses Zweiphasenschema erfordert eine streng sequentielle Ausführung eines Programms, d.h. es<br />
sind zwar Sprünge möglich, jedoch keine parallele Bearbeitung mehrerer Befehle. Ein v.<br />
Neumann-Rechner bearbeitet zu jedem Zeitpunkt immer nur einen Befehl, der immer eine<br />
Datenoperation im Rechenwerk bewirkt.<br />
Komponenten der von-Neumann-Rechnerarchitektur<br />
Vorteile der v. Neumann-Architektur: 9
Mikrocomputertechnik<br />
Die CPU besteht aus Recheneinheit (ALU) und Steuereinheit. Die ALU hat eine feste Wortbreite, z.<br />
B. 8, 16, 32 oder 64 Bit, ihre Aufgabe besteht in der Bearbeitung der Daten, besonders dem Ausführen<br />
von arithmetischen und logischen Operationen.<br />
Zur wichtigsten Aufgabe der Steuereinheit gehört die Koordination der zeitlichen Abläufe im<br />
Rechner. Dazu muss die Steuereinheit die Befehle aus dem Speicher holen, entschlüsseln und deren<br />
Ausführung steuern. Die Steuereinheit besteht aus Befehlsregister, Befehlsdecoder,<br />
Speicheradressregister und Befehlszähler (Program Counter).<br />
Der Speicher eines von-Neumann-Rechners besteht aus einer Vielzahl von Speicherworten, die<br />
wahlfrei adressiert werden können.<br />
Innerhalb eines von-Neumann-Rechners erfolgt der Datentransport auf internen Datenwegen, den<br />
Bussen:<br />
• Der Datenbus wird normalerweise parallel übertragen, d. h. bei einem 32-Bit-System besteht<br />
der Datenbus aus 32-Leitungen. Er transportiert Speicher- oder E/A-Daten von und zur CPU.<br />
• Der Adressbus besteht aus den Adressleitungen, deren Anzahl vom Adressbereich der CPU<br />
abhängt.<br />
• Der Steuerbus koordiniert den Zugriff auf die Komponenten und enthält u. a. Leitungen für<br />
die Interrupt-Steuerung, Buszugriffssteuerung, der Taktung, Reset- und Statusleitungen.<br />
Vorteile der v. Neumann-Architektur: 10
1.2 Befehlszyklus<br />
Das folgende Bild zeigt den prinzipiellen Ablauf bei Bearbeiten eines Befehls.<br />
• Im Befehlsregister (IR, Instruction Register) befindet sich jeweils der aktuell bearbeitete<br />
Befehl<br />
• Der Befehlsdecoder entschlüsselt den Befehl und erzeugt die zur Ausführung notwendigen<br />
Hardware-Steuersignale<br />
• Im Speicheradressregister (MAR, Memory Adress Register) steht die Adresse des nächsten<br />
auszuführenden Befehls oder die Adresse eines Datenwortes, falls zur Ausführung eines<br />
Befehls ein Datenwort vom Speicher geholt bzw. in den Speicher gebracht werden muss.<br />
• Der Befehlszähler (PC, Program Counter) enthält die Adresse des nächsten auszuführenden<br />
Befehls.<br />
Der Befehlszyklus wird also von der CPU ständig durchlaufen:<br />
• die Befehle stehen im Speicher.<br />
• das Leitwerk "weiß" jederzeit, welcher Befehl als nächster auszuführen ist.<br />
• die Adresse (= Nummer der Speicherzelle) des nächsten auszuführenden Befehls steht in<br />
einem speziellen Register des Leitwerks, dem Befehlszähler (Program Counter, PC, BZ,<br />
Instruction Address Register, IAR, Instruction Pointer, IP).<br />
• üblicherweise stehen aufeinanderfolgende Befehle in aufeinander folgenden Speicherzellen,<br />
der zuerst auszuführende Befehl hat die niedrigste Adresse.<br />
• zu Beginn des Programms wird der BZ mit dessen Startadresse geladen.<br />
Ablauf des Befehlszyklus<br />
Mikrocomputertechnik<br />
1.2 Befehlszyklus 11
Mikrocomputertechnik<br />
In der Befehlsholphase erfolgt ein Speicherzugriff (1a) auf die vom Befehlszähler (BZ) angezeigte<br />
Adresse. Der entsprechende Befehl wird in das Befehlsregister (IR) des Leitwerks gebracht (1b).<br />
Anschließend wird der BZ um 1 erhöht. Er zeigt damit auf den nächsten Programmbefehl. Besteht ein<br />
Befehl aus mehreren Speicherworten, setzt sich diese Phase auch aus mehreren Speicherzugriffen<br />
zusammen (BZ wird jedes Mal erhöht), bis der Befehl vollständig im IR steht. Es erfolgt hier in der<br />
Befehlsholphase bereits eine Teilauswertung des Operations-Codes (s. Grafik). Das Befehlsregister<br />
besteht hier aus Op-Code-Register (OR, Befehlsregister) und Adress-Register (AR).<br />
Der Befehl im OR wird nun decodiert (Befehlsdecoder) und der Ablaufsteuerung zugeführt. Diese ist<br />
in der Regel als Mikroprogramm realisiert. Die Ablaufsteuerung erzeugt nun die nötigen<br />
Steuersignale.<br />
Benötigt der Befehl Operanden, so wird deren Adresse aus dem Inhalt des AR ermittelt. Häufig ist im<br />
Befehl nicht die tatsächliche Operandenadresse, sondern nur eine Teilinformation enthalten, die noch<br />
geeignet ergänzt werden muss ( Adressrechnung.<br />
Nun erfolgt ein Speicherzugriff (4a) auf die so festgestellten Operanden-Adresse. Der Operand wird in<br />
das vom Op-Code spezifizierte Register oder in das Rechenwerk (4b) oder in die ausgewählte<br />
Speicherzelle gebracht.<br />
Falls durch den Op-Code weitere Teiloperationen gefordert sind, werden diese nun ausgeführt. Dabei<br />
kann auch der Inhalt des BZ verändert werden (Sprungbefehle, Unterprogramm-Aufrufe).<br />
Ablauf des Befehlszyklus 12
Mikrocomputertechnik<br />
Jeder Befehlszyklus besteht aus einer Anzahl von Teilschritten. Die Anzahl der Teilschritte kann für<br />
unterschiedliche Befehle verschieden sein, auch die Zeitdauer der einzelnen Befehle kann<br />
unterschiedlich sein.<br />
Die Befehlszyklen verschiedener Befehle können unterschiedlich lang sein. Die tatsächliche Dauer<br />
eines Befehlszyklus hängt von der Taktfrequenz der CPU ab. Der gesamte Ablauf in der CPU wird<br />
durch einen zentralen Takt gesteuert. Ein Befehlszyklus kann in eine Reihe von Maschinenzyklen<br />
zerlegt werden (z.B. Speicherzugriff in einem Maschinenzyklus). Ein Maschinenzyklus kann eine oder<br />
mehrere Taktperioden (Arbeitstakt des Prozessors) dauern.<br />
1.2 Erhöhung der Leistungsfähigkeit<br />
• Verlagerung der Prozessorfunktionen bei der Ein-/Ausgabe auf das E/A-Werk ("intelligente"<br />
Schnittstellen, E/A-Prozessoren, Vor-Rechner, Front-End-Rechner).<br />
• Weiterentwicklung des Architekturprinzips durch Steuerung der einzelnen Funktionseinheiten<br />
über eigene Prozessoren, wodurch eine teilweise Parallelarbeit möglich wird.<br />
• Bearbeiten einzelner, spezieller Befehle durch Spezialprozessoren, die abwechselnd mit der<br />
"normalen" CPU arbeiten (z. B. Arithmetik-Koprozessor).<br />
1.2 Erhöhung der Leistungsfähigkeit 13
Vermeiden oder Mildern des v. Neumann-Flaschenhalses<br />
• Neue Rechnerarchitekturen durchbrechen den streng sequentiellen Ablauf des v.<br />
Neumann-Rechners durch Parallelisierung verschiedener Abläufe im Computer.<br />
• Feldrechner bestehen aus mehreren parallelen Rechenwerken, mit gemeinsamen Steuerwerk.<br />
So kann die gleiche Operation auf vielen verschiedenen Datenwerten (Feldern) gleichzeitig<br />
ausgeführt werden.<br />
Asynchrone Trennung von Befehlshol- und -ausführungsphase<br />
•<br />
Pipeline-Rechner: Entweder mehrere hintereinandergeschaltete Rechenwerke, die verschieden<br />
Aufgaben erfüllen, aber gemeinsam gesteuert werden oder Aufbau eines Prozessors mit<br />
hintereinandergeschalteten spezialisierten Teilelementen. Die einzelnen Befehle werden in<br />
Teilaufgaben zerlegt, die nach einander von den Teilelementen bearbeitet werden.<br />
Die nächste Operation kann bereits begonnen werden, wenn die vorhergehende in die nächste<br />
"Station" gelangt ist.<br />
(schematisch dargestellt)<br />
Gleichzeitige Bearbeitung mehrerer Befehle<br />
Zur selben Zeit führt jedes Verarbeitungselement verschiedene Operationen auf<br />
unterschiedlichen Daten durch.<br />
überlappende Befehlszyklen<br />
• Vektorrechner: Kombination mehrerer Pipelines<br />
• Multiprozessorsysteme: Koppelung mehrerer Prozessoren, die auf den gleichen Speicher<br />
(bzw. Speicherbereich) zugreifen und weitgehend unabhängig voneinander arbeiten. Jede<br />
CPU kann ein eigenes Programm bearbeiten MIMD.<br />
• Polyprozessorsysteme: Multiprozessorsystem mit verteilter Kontrolle, bei dem die einzelnen<br />
CPUs autonom arbeiten, aber miteinander kommunizieren und kooperieren.<br />
Meist besitzt jeder Prozessor einen eigenen Speicher, z. B. Transputer. Fehlertolerante<br />
Mehrrechnersysteme eng/lose gekoppelt (z. B. in der Raumfahrt).<br />
1.4 Die Harvard-Architektur<br />
Mikrocomputertechnik<br />
Die Harvard-Architektur ist im Kern älter als die von-Neumann-Architektur, denn die ersten<br />
Computer (etwa die Zuse 3) hatten eigentlich nur einen Datenspeicher. Der "Programmspeicher"<br />
Vermeiden oder Mildern des v. Neumann-Flaschenhalses 14
Mikrocomputertechnik<br />
manifestierte sich als Lochstreifen oder -karten. Erst später wurde das Programm auf Speichermedien,<br />
z. B. einem Trommelspeicher abgelegt. Typisch war also die Trennung von Daten- und<br />
Programmspeicher.<br />
Die Harvard-Architektur bezeichnet heute ein Schaltungskonzept zur Realisierung besonders schneller<br />
CPUs und Signalprozessoren. Befehlsspeicher und Datenspeicher sind voneinander getrennt und<br />
werden über getrennte Busse angesteuert. Daher können Befehle und Daten gleichzeitig geladen, bzw.<br />
geschrieben werden. Bei einer klassischen Von-Neumann-Architektur sind hierzu mindestens zwei<br />
aufeinander folgende Buszyklen notwendig. Zudem sorgt die Trennung von Daten und Programm<br />
dafür, dass bei Softwarefehlern kein Programmcode überschrieben werden kann. Nachteilig ist<br />
allerdings, dass nicht benötigter Datenspeicher nicht als Programmspeicher genutzt werden kann.<br />
Die Harvard-Architektur wurde zunächst überwiegend in RISC-Prozessoren konsequent umgesetzt.<br />
"RISC" steht für "Reduced Instruction Set Computer" (Computer mit eingeschränktem Befehlssatz -<br />
siehe unten). RISC-Prozessoren haben einen kleinen Befehlssatz, bei dem aber fast alle Befehle<br />
innerhalb eines einzigen Taktzyklus ausgeführt werden können.<br />
Moderne Prozessoren in Harvard-Architektur sind in der Lage, parallel mehrere Rechenwerke<br />
gleichzeitig mit Daten zu füllen und auf diesen Daten Befehle auszuführen. Ein weiterer Vorteil der<br />
Trennung besteht darin, dass Datenwortbreite und Befehlswortbreite unabhängig voneinander sind.<br />
Damit kann, falls erforderlich, die Effizienz des Programmspeicherbedarfs verbessert werden, da sie<br />
nicht direkt von den Datenbusbreiten abhängig ist, sondern ausschließlich vom Befehlssatz. Besonders<br />
bekannte Vertreter dieser Architektur sind die Produkte der Firma Microchip Technology Inc. (PIC)<br />
und die Mikrocontroller der AVR-Reihe von Atmel.<br />
Eine bedeutende Erweiterung der Harvard-Architektur wurde von Analog Devices durch die<br />
Einführung der SHARC-(Super-Harvard-Architecture)-Technologie vorgenommen, bei der die<br />
Speichersegmente als Dual-Port-RAMs realisiert wurden, die kreuzweise zwischen den Programmund<br />
Daten-Bussen liegen.<br />
Viele moderne Prozessoren verwenden eine Mischform aus Harvard- und von-Neumann-Architektur,<br />
bei der innerhalb des Prozessors Daten und Programm voneinander getrennt verwaltet werden. Es<br />
existieren eigene Cache-Speicher und Memory Management Units mit getrennten internen Bussen.<br />
1.4 Die Harvard-Architektur 15
Extern wird jedoch in einem gemeinsamen Speicher zugegriffen. Beim Pipelining besteht der Vorteil<br />
dieser Mischform darin, dass deren einzelne Pipelinestufen in Bezug auf Speicherzugriffe getrennt<br />
arbeiten können.<br />
RISC "Reduced Instruction Set Computer"<br />
(Computer mit eingeschränktem Befehlssatz)<br />
Hat man anfangs versucht, beim Design neuer Prozessor-Chips immer mehr und immer<br />
leistungsfähigere Befehle zu integrieren (Complex Instruction Set Computer, CISC), so wird beim<br />
RISC-Prozessor der umgekehrte Weg beschritten.<br />
Für jeden Befehl des Prozessors gibt es eine fest verdrahtete Folge von Ablaufschritten im Chip, das<br />
Mikroprogramm. Je komplexer und mächtiger ein Befehl ist, desto mehr Einzelschritte muss das<br />
Mikroprogramm auf den Chip durchlaufen und desto mehr Taktzyklen sind notwendig, bis der<br />
Prozessor den nächsten Befehl verarbeiten kann. So liegt z.B. beim Prozessor 8088 die Zahl der<br />
Taktzyklen für einen Befehl zwischen 2 und 190.<br />
RISC-Prozessoren haben einen kleinen Befehlssatz, bei dem aber fast alle Befehle innerhalb eines<br />
einzigen Taktzyklus ausgeführt werden können. Das bedeutet auch eine Vereinfachung des Chips und<br />
erreicht auf diese Weise höhere Taktfrequenzen. Typische RISC-Mikrocontroller sind die<br />
PIC-Modelle von Microchip und etliche Atmel-Prozessoren.<br />
1.5 Begriffe<br />
Mikrocomputer:<br />
• Datenverarbeitungssystem mit einem Mikroprozessor als CPU<br />
• Extrem räumlich verkleinertes DVS (PC, Laptop, Steuerechner, etc.)<br />
• Leistungsfähigkeit eingeschränkt gegenüber Mini- und Groß-DVS<br />
• Verwendung häufig als Steuerungsrechner<br />
Mikroprozessor:<br />
• Auf einem Chip integrierte Steuer- und Verarbeitungseinheit, die als CPU im Mikrocomputer<br />
verwendet wird (Steuer- und Leitwerk)<br />
• Mikroprozessor alleine ist nicht einsatzfähig - erst der Mikrocomputer<br />
• Mikrocomputer = Mikroprozessor + Speicher + E/A-Bausteine [+ Peripherie]<br />
Mikrocontroller:<br />
• Mikrocomputer, die auf einem Chip integriert sind Single-Chip-Mikrocomputer<br />
• begrenzter Arbeitsspeicher (meist weniger als 1 MByte)<br />
• kein Massenspeicher (Festplatte,...)<br />
• längere Zykluszeiten (PC: bis GHz, MC: wenige MHz)<br />
• Möglichkeit der Signalverarbeitung (z. B.: integrierte serielle Schnittstelle,<br />
Analog-/Digital-Wandler, Zeitgeber, Impulszähler)<br />
1.6 Entwicklung<br />
Mikrocomputertechnik<br />
RISC "Reduced Instruction Set Computer" 16
Mikrocomputertechnik<br />
Mikroprozessor und Mikrocomputer sind Ergebnis der Entwicklungen im Bereich der<br />
Halbleitertechnik Mikroelekronik, ständige Erhöhung der Integrationsdichte.<br />
• SSI (small scale integration): einige Gatter<br />
• MSI (medium scale integration): Zähler, Register, ALU<br />
• LSI (large scale integration): Mikroprozessor, Speicher<br />
• VLSI (very large scale integr.): komplexere Mikroprozessor, Speicher<br />
• ULSI (ultra large scale integr.): Speicher hoher Kapazität<br />
Die zunehmende Integrationsdichte führte zu immer stärkerer Spezialisierung der Funktion und zur<br />
Einschränkung der Einsatzmöglichkeiten kundenspezifische LSI-Schaltkreise. Auswege:<br />
• standardisierte Bausteine<br />
• programmgesteuerte Bausteine (Mikroprozessor, Mikrocomputer)<br />
Der erste Mikroprozessor wurde 1970/71 von Intel als Steuerbaustein für ein Bildschirmterminal<br />
entwickelt. Da er für den vorgesehenen Zweck zu langsam war, wurde er als universeller<br />
Steuerbaustein vermarktet (4004, 8008). Durch Zufall kam dieses Produkt zur richtigen Zeit als<br />
Alternative zu kundenspezifischen Bausteinen auf den Markt. Folge: sensationell zunehmende<br />
Entwicklung des Mikrocomputer-Einsatzes. Die Entwicklung erfolgte in zwei Richtungen:<br />
• Ersatz festverdrahteter Logikschaltungen<br />
Steuerungsrechner<br />
Verwendung des Mikrocomputer als spezieller<br />
• Entwicklung kleiner und billiger Universalrechner Personal Computer<br />
Die ersten Mikroprozessoren von Intel, 4004 und 8008<br />
Mikrocomputer als Ersatz festverdrahteter Logik<br />
Einsatz für komplexe Steuerungsaufgaben in sich ständig ausweitenden Anwendungsgebieten. Die<br />
weitaus größere Zahl von Mikroprozessoren wird hier eingesetzt. Das Programm für eine bestimmte<br />
Aufgabe wird im ROM abgelegt. Ein kleiner RAM-Bereich speichert die Variablen, z. B.:<br />
1.6 Entwicklung 17
• Single-Chip-Mikrocomputer mit RAM und ROM auf dem Chip<br />
• Mikroprozessor + ROM + E/A-Baustein mit integr. RAM<br />
Einsatzbeispiele:<br />
Mikrocomputertechnik<br />
• Meßtechnik:<br />
komfortable und leistungsfähige Meßgeräte (Bereichswahl, Berechnung, Eichkurven, graph.<br />
Darstellung, ...)<br />
• Steuerung:<br />
NC-Maschinen, Prozeßsteuerung, Roboter, SPS, automat.Testsysteme, KFZ-Technik<br />
• Nachrichtentechnik:<br />
Fernsprechtechnik + Vermittlungstechnik (Nebenstellenanlagen, ISDN, Mobiltelefon, ...),<br />
Telefax, Sender + Empfänger, Radar, Spracherkennung, ...<br />
• Bürotechnik:<br />
Kopierer (heute schon voll digital), Registrierkassen, Schreibautomaten, Anrufbeantworter, ...<br />
• KFZ-Elektronik:<br />
Motorsteuerung, ABS, Bord-Computer, Verkehrsleitsysteme, Diagnose-Computer, ... letzte<br />
Entwicklungen: autonomes, "sehendes" Fahrzeug<br />
• Haushaltelektronik:<br />
Waschmaschine, Nähmaschine, Heizungssteuerung, Alarmanlagen, ...<br />
• Unterhaltungselektronik:<br />
Radio- und Fernsehgeräte, HIFI-Geräte, Videorecorder, Satelliten-Empfänger, ...<br />
• Datenverarbeitung:<br />
Intelligente Peripherie (Terminals, Drucker, Plotter, Scanner, ...)<br />
Eines der ersten Entwicklungssysteme: KIM1 mit Prozessor 6502, 1 kByte Speicher, Hex-Tastatur<br />
und Siebensegmentanzeige<br />
Mikrocomputer als Ersatz festverdrahteter Logik 18
Mikrocomputer als Universalrechner<br />
Ursprünglich als Entwicklungssysteme für den o.g. Anwendungsbereich konzipiert erfolgte eine<br />
Weiterentwicklung zu Arbeitsplatzrechnern (PC, Homecomputer).<br />
• Durch Vernetzung dezentrale DV<br />
• Vorstoß in den Bereich der Minicomputer Die 16-, 32- und 64-Bit-Mikroprozessor zielen in<br />
diese Richtung.<br />
Kennzeichen:<br />
• Verwendung höherer Programmiersprachen<br />
• komplexe und leistungsfähige Betriebssysteme<br />
• Funktionsmerkmale von Großrechnern (virtuelle Speicherung, Cache)<br />
Technische Entwicklung:<br />
Anzahl Transistoren eines Intel 8080 Mikroprozessors 4 500<br />
Anzahl Transistoren eines Intel 80286 Mikroprozessors 134 000<br />
Anzahl Transistoren eines Intel 80386 Mikroprozessors 275 000<br />
Anzahl Transistoren eines Intel Pentium Mikroprozessors 3 100 000<br />
Anzahl Transistoren eines Intel Pentium 4 Mikroprozessors 42 000 000<br />
Anzahl Transistoren eines AMD KG (Athlon 64) Mikroprozessors 105 900 000<br />
Anzahl Transistoren eines Intel Core i7 Mikroprozessors 731 000 000<br />
Anzahl Transistoren eines Eight Core Xeon Nehalem-EX Mikroprozessors 2 300 000 000<br />
Anzahl Transistoren eines RV820 ATI/AMD Grafikprozessors 2 154 000 000<br />
Anzahl Transistoren eines GF100 NVIDIA Grafikprozessors 3 000 000 000<br />
Festplattenkosten pro Gigabyte 1990 53 000<br />
Festplattenkosten pro Gigabyte 1995 850<br />
Festplattenkosten pro Gigabyte 2000 20<br />
Festplattenkosten pro Gigabyte 2005 1<br />
Festplattenkosten pro Gigabyte 2010 0.1<br />
RAM-Kosten pro Gigabyte 1990 120 000<br />
RAM-Kosten pro Gigabyte 1995 33 000<br />
RAM-Kosten pro Gigabyte 2000 1 400<br />
RAM-Kosten pro Gigabyte 2005 190<br />
RAM-Kosten pro Gigabyte 2010 20<br />
(Alle Preisangaben in US-Dollar)<br />
1.7 Embedded Systems<br />
Mikrocomputertechnik<br />
"Embedded Systems" ist der englische Fachbegriff für eingebettete (Computer-)Systeme, die in der<br />
Regel unsichtbar ihren Dienst in einer Vielzahl von Anwendungsbereichen und Geräten versehen, wie<br />
Mikrocomputer als Universalrechner 19
z.B. in Flugzeugen, Autos, Kühlschränken, Fernsehern, Werkzeugmaschinen, Kaffeeautomaten,<br />
DVD-Playern oder anderen Geräten. In der Computerbranche werden solche Systeme auch gerne<br />
"Appliance" genannt. ("appliance: A device or instrument designed to perform a specific<br />
function, especially an electrical device, such as a toaster.)<br />
Wenn man den Begriff aufschlüsselt ergibt sich:<br />
Mikrocomputertechnik<br />
• Ein "System" ist in diesem Kontext immer eine informationsverarbeitende Maschine<br />
• "eingebettet" bedeutet: für einen spezifischen Zweck in einer technischen Umgebung<br />
entworfen, eingebaut und betrieben.<br />
Ein eingebettetes System verrichtet, weitgehend unsichtbar für den Benutzer, den Dienst in einer<br />
Vielzahl von Anwendungsbereichen und Geräten, wie z. B. in Flugzeugen oder Autos,<br />
Haushaltsgeräten, in der Unterhaltungselektronik, bei Mobiltelefonen oder in industriellen<br />
Steuerungen. Ein eingebettetes System interagiert mit seiner meist elektromechanischen Umwelt.<br />
Dabei ist kein menschlicher Benutzer vonnöten; er muss auch keinerlei Kenntnisse über die<br />
technischen Innereien des eingebetteten Systems haben, um das Gesamtsystem bedienen zu können.<br />
Im Fall von komplexen Gesamtsystemen handelt es sich dabei meist um eine Vernetzung einer<br />
Vielzahl von autonomen, eingebetteten Systemen.<br />
Eingebettete Systeme können in Einzelfällen auf ähnlicher Hardware wie Arbeitsplatzcomputer<br />
basieren (sogenannte embedded-PCs), in der Regel unterliegen sie jedoch stark einschränkenden<br />
Randbedingungen: Minimale Kosten, geringer Platz-, Energie-, Speicherverbrauch. Einzelne<br />
Komponenten wie Prozessor oder Arbeitsspeicher müssen auch wesentlich länger auf dem Markt<br />
verfügbar sein, um die langfristige Einsetzbarkeit und Ersatzteilbeschaffung zu gewährleisten.<br />
Moderne eingebettete Systeme basieren auf den verschiedensten Prozessor-Plattformen, die in<br />
Bezug auf die Peripheriemodule hochintegriert sind und durch moderne Stromspartechniken wenig<br />
Energie verbrauchen.<br />
"Embedded Systems" vereinigen daher durch ihre oftmals sehr hardwarenahe Konstruktion die große<br />
Flexibilität von Software mit der Leistungsfähigkeit der Hardware. Die Software-Entwicklung für<br />
diese Systeme unterscheidet sich oft grundsätzlich von jener für Desktop- oder PC-Systeme: oftmals<br />
werden Betriebssysteme eingesetzt, die zwar nicht über eine grafische Benutzeroberfläche verfügen,<br />
dafür jedoch Echtzeitanforderungen genügen.<br />
Bevorzugte Programmiersprachen sind daher z. B. <strong>Assembler</strong> oder C. Bekannte<br />
Embedded-Betriebssysteme sind z.B. QNX, VxWorks, Windows CE, DOS, LynxOS, Nucleus,<br />
zunehmend auch spezielle Linux-Derivate, wenn die Echtzeitbedingungen keine dominante Rolle<br />
spielen. Einige Beispiele für Embedded Systems sind:<br />
• Die Elektronik in einem Kaffeevollautomaten. Mit ihr wird beispielsweise die Kaffeemenge<br />
und -stärke sowie die Wassermenge reguliert. Die Kaffemaschine an sich ist kein<br />
datenverarbeitendes System.<br />
• Auch die Elektronik in einem Videorecorder ist ein eingebettetes System, auch wenn der<br />
Videorecorder selbst ein (eingeschränkt) datenverarbeitendes System ist.<br />
• Der Zündcomputer im Auto ist ebenfalls ein im Stillen wirkendes System, wobei in einem<br />
Fahrzeug der Oberklasse inzwischen einige Dutzend Computer werkeln.<br />
• Die Steuerungen von NC-Werkzeugmaschinen (NC = Numeric Control) oder anderen<br />
industriellen Systemen sind fast immer Embedded Systems.<br />
• Fast alle Peripheriegeräte in der Datenverarbeitung (Drucker, Scanner, Barcode-Leser, Router<br />
usw.) sind mit eigener Intelligenz zur Verarbeitung der Daten ausgerüstet.<br />
Kennzeichnende Merkmale von embedded Systemen sind:<br />
1.7 Embedded Systems 20
Mikrocomputertechnik<br />
• sie sind fester Bestandteil eines technischen Systems<br />
• sie sind zweckbestimmt (im Gegensatz zum Universalrechner)<br />
• sie interagieren mit der Umgebung durch Sensoren und Aktoren<br />
• sie reagieren meist in Realzeit<br />
Sekundäre Merkmale von embedded Systemen sind:<br />
• sie werden oft für Regelungs- und Steuerungsaufgaben vorgesehen<br />
• sie sind häufig Massenware, Konsumgut, billig<br />
• sie sind vielfach schlecht bzw. nicht wartbar und nicht erweiterbar<br />
• sie sind manchmal auch sicherheitskritisch<br />
Eingebettete Systeme beanspruchen einen Marktanteil bei der Prozessor-Produktion von ca. 98%. Die<br />
restlichen 2% dienen dem Aufbau von interaktiven Systemen wie z. B. Laptops, Desktop-Computern<br />
und Servern. Nahezu die Hälfte der gesamten Microcontroller-Jahresproduktion sind immer noch<br />
8-Bit-Prozessoren. Bereits heute gibt es mehr eingebettete Systeme als Menschen auf der Welt. Deren<br />
Elektronik dient oft als Wegwerf-Artikel (z. B. RFID-Tags, Grusspostkarten).<br />
Man setzt deshalb für die Definition des eingebetteten Systems voraus, dass<br />
• die genaue Aufgabe des Systems vor der Entwicklung feststeht,<br />
• immer nur ein einziges Programm abläuft und<br />
• Hardware und Software eine funktionale Einheit bilden.<br />
Tatsächlich haben sich im der Industrie immer häufiger Standard-PC-Komponenten bei<br />
Neuentwicklungen von eingebetteten Systemen durchgesetzt -- geringe bis mittlere Stückzahlen und<br />
kurze Produktzyklenzeiten vorausgesetzt. Die Komponenten von der Stange ("Commodity of the<br />
Shelf", COTS) kosten oft nur einen Bruchteil vergleichbarer proprietärer Industrielösungen und sind<br />
dabei wesentlich flexibler. Diese "Embedded PCs" sind aber nicht überall sinnvoll: Oft zwingen rauhe<br />
Umgebungen und Platzmangel zu speziellen Eigenentwicklungen. Bei hohen Stückzahlen ist dies<br />
ohnehin obligatorisch.<br />
Anders als stationäre Systeme haben eingebettete Systeme besondere Anforderungen hinsichtlich<br />
Robustheit, Energieverbrauch und Speicherbedarf, Im Gegensatz zu einem Arbeitsplatzrechner wird<br />
ein eingebettetes System im Allgemeinen nicht "heruntergefahren", bevor man es ausschaltet. Es muss<br />
im Gegenteil damit zurechtkommen, dass ihm der Strom jederzeit und ohne Vorwarnung abgestellt<br />
werden kann. Damit ein solcher Shutdown, etwa aufgrund eines Stromausfalls, problemlos<br />
überstanden wird und die Software nach dem Booten in einen definierten Anfangszustand gelangt.<br />
Bewegliche Teile wie Lüfter oder Festplatte sind meist nicht erwünscht. Besonders sind auch meist<br />
die Umgebungsbedingungen wie Temperatur und Feuchtigkeit. Um auch diesen Anforderungen<br />
gerecht zu werden, steht eine möglichst geringe Stromaufnahme des Prozessors bzw. des Boards im<br />
Vordergrund. Im Vergleich zum "Stomfresser" im Desktop-Rechner kommt ein embedded Board<br />
meist mit weniger als 1 Watt aus. Embedded Systems laufen buchstäblich während ihrer gesamten<br />
Lebensdauer, also an sieben Tagen pro Woche und 24 Stunden pro Tag. Gelegentliche Abstürze mit<br />
der Notwendigkeit eines Neustarts sind hier absolut inakzeptabel (insofern fällt mein kürzlich<br />
erworbener DVB-T-Empfänger/Decoder aus dem Rahmen, bei schlechtem Empfang hängt er sich<br />
schon mal auf).<br />
Embedded Systems basieren also oft auf ähnlicher Hardware wie Arbeitsplatzcomputer, unterliegen<br />
jedoch meist stark einschränkenden Randbedingungen: minimale Kosten und damit geringer Platz-,<br />
Energie-, Speicherverbrauch. Die Fertigung in großen Stückzahlen, oft im Millionen-Bereich, ist ein<br />
weiterer wichtiger Punkt zur Kostenreduzierung. Hinzu kommt, dass die einzelnen Komponenten wie<br />
Prozessor und RAM auf Weiterentwicklungen älterer Komponenten basieren, was die Langlebigkeit<br />
1.7 Embedded Systems 21
steigert, Stromverbrauch und -kosten jedoch senkt.<br />
Für viele Anwendungen können auch ältere Komponenten eingesetzt werden, wenn zudem die<br />
Vereinfachung der Architektur des ursprünglichen Systems dazu beiträgt, weitere Kosten zu senken.<br />
Programme eines Embedded Systems müssen oft Echtzeitanforderungen genügen. In der Regel<br />
existieren verglichen mit Desktop-PC-Hardware nur stark reduzierte Ressourcen, zumeist ohne<br />
Festplatte, Betriebssystem, Tastatur oder Bildschirm. Ein ROM- oder Flash-Speicher ersetzt meist<br />
mechanische Speicherkomponenten wie eine Festplatte: bewegliche Teile bedeuten Verschleiß, der<br />
hier unerwünscht ist. Wenn überhaupt, dann gibt es meist nur ein Tastenfeld und die Ausgabe wird -soweit<br />
überhaupt vorgesehen -- durch ein LCD realisiert.<br />
Design von Embedded Systems<br />
Die Elektronik wird meist von einem Mikroprozessor mit entsprechender Peripherie oder einem<br />
Microcontroller gebildet. Vielfach handelt es sich auch um komplette PC-Boards mit stromsparenden<br />
Bauteilen und anderem Formfaktor. Ein solcher PC gilt bereits als groß, wenn er Postkartenformat<br />
besitzt. Um das Board herum ist dann die dem Aufgabengebiet entsprechende Peripherie angeordnet.<br />
Folgende Aspekte spielen u. a. bei Designentscheidungen von Embedded Systems eine Rolle:<br />
• Integration: Je mehr Funktionalität der verwendete Mikrocontroller bereits besitzt, desto<br />
weniger Peripheriebausteine werden benötigt, um die Anbindung an die benötigten<br />
Systemschnittstellen (Ein-/Ausgabe) zu ermöglichen. Je weniger Bausteine eine Platine<br />
benötigt, desto geringer sind der Platzbedarf der Leiterbahnen und die Signallaufzeiten<br />
zwischen den Bausteinen.<br />
• Echtzeitanforderungen: Hohe Verfügbarkeit und definierte Antwortzeit sind häufig gestellte<br />
Anforderungen an ein Embedded System und somit auch an dessen Betriebssystem und die<br />
Software. Die Verwendung spezieller Echtzeitbetriebssysteme erlaubt es, schon in der<br />
Entwicklungsphase die Reaktionszeiten des Gesamtsystems abzuschätzen.<br />
• Cross-Entwicklung: Oft ist das System, auf dem die Software entwickelt wird, nicht<br />
identisch mit dem Zielsystem. Es werden dann Compiler eingesetzt, die Binärcode für das<br />
Zielsystem erzeugen. Bei kleinen Embedded Systems (die oft nicht einmal ein Betriebssystem<br />
besitzen) erfolgt der Programmtransfer durch Programmieren des Flash-Speichers auf dem<br />
Entwicklungsrechner. Der Speicherbaustein wird dann zum Testen ins Zielsystem eingesteckt.<br />
Bei modernen Microcontrollern ist in der Regel die Möglichkeit gegeben, den Flash-Speicher<br />
on board zu programmieren -- es genügen dann ein paar Drähte zwischen Entwicklungs- und<br />
Zielsystem. Besitzt das Zielsystem ein eigenes Betriebssystem, kann der Datentransfer auch<br />
über Standardschnittstellen oder Netzwerk erfolgen.<br />
Zum vorhergehenden Abschnitt Zum Inhaltsverzeichnis Zum nächsten Abschnitt<br />
Copyright © FH München, FB 04, Prof. Jürgen Plate<br />
Letzte Aktualisierung: 07. Okt 2012<br />
Mikrocomputertechnik<br />
Mikrocomputertechnik<br />
Prof. Jürgen Plate<br />
Design von Embedded Systems 22
2 Hardware von Mikrocomputern<br />
2.1 Struktur eines Mikrocomputers<br />
Prinzipieller Aufbau<br />
Ein Mikrocomputer hat grundsätzlich die gleichen Eigenschaften, wie ein größeres DV-System, die<br />
von-Neumann-Struktur. Die Besonderheiten sind:<br />
• CPU ist in einem Chip integriert (Mikroprozessor)<br />
• Der Arbeitsspeicher zerfällt i.A. bei Steuerungsrechnern in Programmspeicher (ROM, PROM,<br />
EPROM,...) und Datenspeicher (RAM)<br />
• Das E/A-Werk besteht aus speziellen E/A-Bausteinen, die als IC zahlreich und passend für<br />
den verwendeten Mikroprozessor-Typ angeboten werden Mikroprozessor-Familie:<br />
♦ einfache serielle/parallele E/A-Bausteine,<br />
♦ DMA-, CRT-, Floppy- und Platten-Controller,<br />
♦ E/A-Prozessoren,<br />
♦ Arithmetikprozessoren,<br />
♦ Timer,<br />
♦ Speicherverwaltungsbausteine,<br />
♦ usw.<br />
• Die Verbindung der einzelnen Komponenten erfolgt durch eine Bus-Struktur. ( teilweiser<br />
Verzicht auf Parallelarbeit einzelner Komponenten).<br />
• Ein einfacher Mikrocomputer besteht aus relativ wenigen, hochintegrierten Bausteinen.<br />
Der System-Bus<br />
Bus = Anzahl von Leitungen, an die mehrere Funktionseinheiten parallel angeschlossen sind. Der<br />
Informationsaustausch zwischen diesen Einheiten erfolgt zeitmultiplex über den Bus. Zu jedem<br />
Zeitpunkt sind immer nur zwei Einheiten (Sender, Empfänger) miteinander verbunden.<br />
• unidirektionaler Bus: Information geht nur in einer Richtung (i.a. nur 1 Sender)<br />
2 Hardware von Mikrocomputern 23
• bidirektionaler Bus: Informationsaustausch in beiden Richtungen (mehrere Sender)<br />
In Mikroprozessor-Systemen ist (mit Ausnahme des DMA) der Mikroprozessor immer einer der<br />
beiden aktiven Bausteine. Die Bus-Leitungen werden in funktionelle Gruppen gegliedert:<br />
• Adreß-Bus (A-Bus):<br />
unidirektional, 8-32 Leitungen, Auswahl von Speicherzellen, Bausteinen, E/A-Registern<br />
• Daten-Bus (D-Bus):<br />
bidirektional, 8-32 Leitungen, Datentransport zw. Mikroprozessor und Speicher/Peripherie<br />
• Steuer-Bus (Control-Bus, S-Bus):<br />
Unterschiedliche Übertragungsrichtungen - aber jede Leitung für sich unidirektional, 4-20<br />
Leitungen, Steuerung der Zusammenarbeit der einzelnen Baugruppen<br />
Der Bus ist eine ökonomische Verbindung mehrerer Baugruppen. Es sind flexible Erweiterung und<br />
systematische Verschaltung möglich (Backplane, Bus-Platine). Der Zugang erfolgt über Steckplätze<br />
(Slots). Ein Bus ist aber auch relativ langsam, da keine Parallelarbeit möglich ist und das Fan-Out der<br />
sendenden Komponenten ist begrenzt (u.U. spezielle Pufferbausteine = Bus-Treiber, Bus-Extender<br />
nötig). Es gibt Systeme, bei denen ein Teil des Busses für verschiedene Funktionen mehrfach genutzt<br />
wird Zeitmultiplex-Betrieb (z. B. 8085: Datenbus/LSB Adressbus)<br />
A-Bus Adreßbus<br />
D-Bus Datenbus<br />
S-Bus Steuerbus (Control-Bus)<br />
RAM Random-Access-Memory (Schreib-Lese-Speicher) ROM Read-Only-Memory<br />
(Festwert-Speicher) SIO Serial Input Output PIA Parallel Input Output<br />
Bus-Treiber<br />
Problem bei Bus-Systemen: Es darf immer nur ein einziger Sender am Bus aktiviert sein - alle anderen<br />
Sender müssen abgeschaltet sein.<br />
Aufgaben des Bus-Treibers:<br />
Mikrocomputertechnik<br />
• An-und Abschalten der angeschlossenen Funktionseinheiten am Bus<br />
• Durchschalten der gewünschten Übertragungsrichtung bei bidirektionalen Busanschlüssen<br />
Der System-Bus 24
• Erhöhung des Fan-Out (Anschlußkapazität) eines Busses Bustreiber sind heute in der Regel<br />
Gatter mit Tri-State-Ausgang: Der dritte Zustand (Z-State) ist ein hochohmiger Zustand =<br />
Trennen des Treibers vom Bus. Die Umschaltung des Z-State erfolgt mit einem<br />
Enable-Steuersignal.<br />
Die Ausgänge des Mikroprozessors und der übrigen Bausteine sind i. a. als Tri-State-Ausgänge<br />
ausgeführt direkter Busanschluß möglich. Für Funktionseinheiten ohne Tri-State-Ausgänge und als<br />
Bus-Extender gibt es spezielle Treiber-ICs.<br />
Unidirektionaler Treiber (Buffer, Line Driver) z. B. 74244<br />
Bidirektionaler Treiber (Transceiver) z. B. 74245 (8-fach)<br />
Systembeispiel<br />
Aufzugsteuerung mit Mikroprozessor 6802. Auf dem CPU-Chip sind 128 Byte RAM integriert. Somit<br />
wird extern nur noch E/A und ROM benötigt.<br />
2.2 Mikroprozessor<br />
Mikrocomputertechnik<br />
Zwischenbemerkung: Die Wahl des Prozessors hängt auch von der Anwendung ab (so ist z.B. für<br />
einfache Steuerungen ein 8-Bit-Prozessor vollkommen ausreichend). Die Umstellung des Entwicklers<br />
Bus-Treiber 25
von einem auf den anderen Mikroprozessor ist i.a. nicht allzu schwierig. Im praktischen Teil wird der<br />
8-Bit-Mikroprozessor 6809 verwendet, der sich durch einen einfachen, überschaubaren und<br />
orthogonalen Befehlssatz auszeichnet.<br />
Versorgung und Steuerung<br />
Gruppierung der µP-Anschlüsse:<br />
Die Steuer-Signale dienen zur programmunabhängigen Beeinflussung des Mikroprozessors, z. B.<br />
Reset, Interrupts. Deren Quittungssignale sind teilweise auch dem S-Bus zuzuordnen.<br />
Die Spannungsversorgung erfolgt heute mit + 5V; früher waren of mehrere Spannungen notwendig<br />
(+5V, -5V, +12V).<br />
Der Takt wird entweder mit einem externen Taktgenerator oder intern erzeugt. Normalerweise genügt<br />
ein Quarz, bei einfachen Systemen sogar ein R-C-Glied.<br />
• nicht überlappender Zweiphasentakt (wegen der internen Ablaufsteuerung und des<br />
Rechenwerks)<br />
• Mindestfrequenz darf bei einigen Modellen nicht unterschritten werden (Register sind als<br />
dynamische Speicher realisiert).<br />
Die Taktfrequenz sagt nichts über die tatsächliche Ablaufgeschwindigkeit aus. Bei interner<br />
Takterzeugung ist i.a. nur noch ein externer Quarz nötig. Die Quarzfrequenz beträgt ein Vielfaches der<br />
Taktfrequenz (2 - 18 * Taktfrequenz).<br />
Steuerungs-Signale<br />
Dierser Abschnitt soll einen Überblick der Signale vermitteln. Nicht jeder Mikroprozessor verfügt<br />
über alle genannten Möglichkeiten.<br />
Rücksetzen (Reset)<br />
Mikrocomputertechnik<br />
2.2 Mikroprozessor 26
Herstellen eines definierten Grundzustandes des Prozessors:<br />
• Meist durch fallende Flanke am Reset-Anschluß des Mikroprozessors<br />
• BZ auf definierten Anfangswert setzen (0, festen Wert oder durch Vektor definierten Wert)<br />
• Prozessor startet Befehlszyklus mit diesem Wert<br />
• Interrupts sperren (Freigabe muß durch Programm erfolgen)<br />
• Nicht immer: Rücksetzen der Register<br />
Wichtig: Einschaltverhalten der Mikroprozessor beachten! Reset darf erst erfolgen, nachdem die<br />
Versorgungsspannung eine bestimmte Zeit stabil anliegt (Einschwingzeit des Quarzoszillators).<br />
Warten (Wait, Memory Ready, MRDY, Ready)<br />
Dieser Anschluß dient der Anpassung an langsame Speicher oder E/A-Bausteine. Erreicht wird eine<br />
Verlängerung des Speicherzugriffszyklusses.<br />
• gezielte Verlängerung einzelner Taktphasen (z. B. 6809)<br />
• Einschieben leerer Zyklen (synchron) (80x86, "Wait States")<br />
• Warten auf Fertigmeldung (asynchron) (68000)<br />
Halten (Hold, Halt, Stop)<br />
Anhalten des Programmablaufs nach Beendigung des laufenden Befehls.<br />
• Bus geht in den Tri-State-Zustand<br />
• Mikroprozessor nach außen inaktiv (intern weiter aktiv)<br />
• Anwendungen:<br />
♦ einfache DMA-Möglichkeit<br />
♦ Start/Stop von außen (Test)<br />
♦ Einzelschrittsteuerung<br />
♦ Stop bei bestimmter Adresse<br />
• "Aufwecken" nur durch Reset oder Interrupt<br />
Befehlsunterbrechungen (DMA, BREQ)<br />
Mikrocomputertechnik<br />
Anhalten der Ausführung des aktuellen Befehls nach Beendigung des laufenden Zyklusses - also<br />
mitten im Befehl.<br />
• Bus geht in den Tri-State-Zustand<br />
• Anwendung: DMA<br />
• Nach Beendigung der Unterbrechung wird der unterbrochene Befehl fortgesetzt<br />
Steuerungs-Signale 27
Befehls-Abbruch (Abort)<br />
Abbruch des laufenden Befehls bei virtueller Speichertechnik<br />
• Wegspeichern des Programmstatus<br />
• Seitenwechsel durchführen<br />
• Programmstatus wiederherstellen<br />
• abgebrochenen Befehl neu aufsetzen<br />
Programm-Unterbrechung (Interrupt)<br />
Unterbrechung des laufenden Programms nach Beenden des laufenden Befehls. Ausführen einer<br />
Interrupt-Serviceroutine (ISR).<br />
Arten:<br />
• Abspeichern des Programmstatus<br />
• Setzen BZ auf feste oder vektorisierte Adresse<br />
• Sperren weiterer Interrupts<br />
• Auslösung durch Flanke oder Pegel<br />
• Lokalisierung durch Polling oder HW-Vektor (z.B. bei 8080)<br />
• Abarbeiten der ISR<br />
• Restaurieren des Programmstatus und Fortsetzung des Programms<br />
• bedingter (maskierbarer) Interrupt<br />
• unbedingter Interrupt<br />
2.3 Arbeitsspeicher<br />
Speicher-Bausteine<br />
Als Speicherbausteine werden Halbleiterspeicher verwendet. Folgenden Begriffe dienen zur<br />
Spezifizierung eines Speichers:<br />
• a Adreßbreite<br />
• d Wortbreite<br />
s Speicherkapazität; s = 2a •<br />
• tacc Zugriffszeit<br />
• tcyc Zykluszeit<br />
Anschlüsse:<br />
Mikrocomputertechnik<br />
• CS - Chip Select: Leitung(en) zur Bausteinauswahl<br />
• R/W - Write Enable: Festlegung der Datentransportrichtung 1 = Lesen, 0 = Schreiben<br />
• Adreß- und Datenleitungen<br />
Steuerungs-Signale 28
Organisationsformen:<br />
• d = 1: bitorganisierter Speicher, z.B. 64K x 1<br />
• d > 1: Nibble (d = 4)-, Byte (d = 8)- oder Wort (d = 8, 16, 32, 64)-organisierter Speicher<br />
Zusammenschalten von Speicherbausteinen<br />
Der Gesamtspeicher wird durch Zusammenschaltung von Speicherbausteinen gebildet (sofern nicht<br />
schon ein Baustein ausreicht). Er besteht aus RAM und ROM (PROM, EPROM). Die<br />
Zusammenschaltung kann erfolgen:<br />
• in Wortrichtung (d = Wortbreite des Mikroprozessors)<br />
• in Bitrichtung (d = 1 oder d < Wortbreite des Mikroprozessors)<br />
• gemischt (Wort- und Bitrichtung)<br />
Bei der Zusammenschaltung in Bitrichtung werden alle Bausteine parallel adressiert.<br />
In allen anderen Fälle gilt:<br />
Mikrocomputertechnik<br />
• Zur Wortadressierung innerhalb des Bausteins dient nur ein Teil der Adresse<br />
• Der Rest der Adresse dient zur Bausteinanauswahl:<br />
♦ Uncodierte Bausteinauswahl<br />
♦ Decodierung auf dem Baustein (mehrere CS-Eingänge)<br />
♦ externe Decodierung (nur 1 CS nötig)<br />
♦ Kombination externe/interne Decodierung<br />
Beispiel 1: Zusammenschaltung in Wortrichtung, uncodierte Bausteinauswahl:<br />
Speicher-Bausteine 29
Beispiel 2: Zusammenschaltung in Wortrichtung, codierte Bausteinauswahl, externe Decodierung<br />
Ergänzende Bemerkungen<br />
Ist der Adreßraum des Mikroprozessors breiter als der zur Speicheradressierung eingesetzte Adreßbus,<br />
tritt Mehrfachadressierung auf: Adressen, die sich nur in den unbenutzten höherwertigen Bits<br />
unterscheiden, sprechen die gleiche Speicherzelle an. Dieser Effekt kann erwünscht sein - das<br />
Entwicklungssystem adressiert seinen Daten-Speicher ab $8000, der Steuerungsrechner ab Adresse 0.<br />
Gelegentlich muß noch ein Signal zur zeitlichen Koordination der Speicherzugriffe eingesetzt werden.<br />
Bei ROM-Bausteinen gibt es häufig noch einen Eingang zum Schalten der Ausgänge in den<br />
Tri-State-Zustand (OE=Output Enable).<br />
2.4 Ein-/Ausgabe-Bausteine<br />
Struktur von E/A-Bausteinen<br />
Mikrocomputertechnik<br />
Der E/A-Baustein ist Bindeglied zwischen Prozessor und Peripherie. Seine Aufgaben sind unter<br />
anderem:<br />
Datentransport, zeitliche Anpasung, Signalumsetzung, Pegelumsetzung, Erweiterung der<br />
Belastbarkeit, Datenformat-Anpassung, Codeumsetzung, ...)<br />
Zusammenschalten von Speicherbausteinen 30
Mikrocomputertechnik<br />
Das Einsatzgebiet der E/A-Bausteine reicht von einfacher Byte-orientierter Ein- und Ausgabe bis zur<br />
autonomen Verwaltung komplexer Protokolle, wie z. B. die Netzwerkanbindung. E/A-Komponenten<br />
werdenin der Regel so entworfen, dass sie jeweils einen möglichst großen Bereich von Anwendungen<br />
abdecken. Die Spezialisierung für die Anwendung geschieht durch Initialisierung des Bauteils im<br />
System, ein Vorgang, der in Datenblättern und im allgemeinen Sprachgebrauch "Programmierung"<br />
genannt wird: Nach jedem Einschalten des Systems müssen bestimmte Steuerregister in diesen<br />
Bausteinen von der CPU aus mit bestimmten Werten initialisiert werden.<br />
Bausteine für programmierten E/A-Transfer<br />
Zur bitparallelen Ein/Ausgabe werden von fast jedem Hersteller Bausteine angeboten und nahezu<br />
jeder Controller verfügt über parallele E/A. Verschiedene Bezeichnung sind in Gebrauch:<br />
• PIO Parallel I/0 Interface<br />
• PIA Peripheral Interface Adapter<br />
• PPI Programmable Peripheral Interface usw.<br />
Der Baustein besitzt hierzu Steuerregister, deren Inhalte die Datenrichtung, Bedeutung von<br />
Steuersignalen (Handshake) und das Interruptverhatten festlegen.<br />
Der Zugriff auf die Peripherie erfolgt entweder programmgesteuert (polling) oder interruptgesteuert.<br />
Sie werden am häufigsten verwendet. Auch Bus-Treiber können als sehr einfache E/A-Bausteine<br />
eingesetzt werden. So wurde z. B. die Standard-Druckerschnittstelle des IBM-PC mit zwei<br />
8-Bit-Latches und zwei 8-Bit-Bustreibern realisiert. Kaum komplexer sind auch Speicher-Register mit<br />
nachgeschalteten Leistungstreibern. Sie übernehmen auch die zeitliche Anpassung. Zum Teil sind sie<br />
mit Steuerlogik, Betriebsartenwahl (Ein/Aus) und Interrupt-Auslösung versehen.<br />
Wesentlich flexibler im Einsatz sind programmierbare E/A-Bausteine, wie man sie heute verwendet.<br />
Eigenschaften und Funktion sind per Software einstellbar. Programmierbare Eigenschaften können<br />
sein:<br />
• Datenrichtung<br />
• Übertragungsgeschwindigkeit<br />
• Übertragungsformat<br />
• Paritätsprüfung<br />
• Art des Interrupt-Signals von der Peripherie<br />
• Interrupt-Maske<br />
Diese Bausteine erlauben meist sowohl programmgesteuerten programmierten E/A-Transfer als auch<br />
interruptgesteuerten programmierten E/A-Transfer. Für den einfachen E/A-Transfer gibt es zwei<br />
Bausteine-Grundtypen:<br />
1. Parallele Schnittstelle (Parallel Interface Adapter, Parallel Input Output) Schnittstelle für<br />
parallelen Datenaustausch (z.B. Centronics-Druckerschnittstelle, Relais-Ausgang,<br />
Digital-Analog- und Analog/Digital-Wandler, digitale Eingangssignale). In der Regel sind<br />
mehr als ein 8 Bit breiter "Port" vorhanden (meist 2 bis 4). Steuer- oder Statusregister können<br />
pro Port separat vorhanden sein.<br />
Struktur von E/A-Bausteinen 31
2.<br />
Mikrocomputertechnik<br />
SIA (Serial Interface Adapter, Serial Input Output) Dies ist eine Schnittstelle für bitseriellen<br />
Datenverkehr. Die Bausteine enthalten je einen Parallel-Seriell- und Seriell-Parallel-Wandler<br />
(Schieberegister).<br />
Bei seriellen Schnittstellen kann es sich um einen UART (Universal Asynchronous<br />
Receiver/Transmitter) handeln, wie man ihn von der guten alten seriellen Schnittstelle des PC<br />
her kenn, aber auch um spezielle Schnittstellen für die Kommunikation zwischen einzelnen<br />
ICs, beispielsweise die I 2 C- oder die SPI-Schnittstelle. Generell gilt:<br />
♦ CPU schreibt ein Byte (liegt "parallel" an), die serielle Schnittstelle muss es Bit für<br />
Bit aussenden.<br />
♦ Beim Empfang muss ein Bit nach dem anderen gespeichert und als komplettes Byte<br />
an die CPU geleitet werden.<br />
♦ Festzulegende Parameter: Bit-Geschwindigkeit (Baudrate), Anzahl Stoppbits, Parität,<br />
Steuerleitungen usw.<br />
Der Baustein enthält einen getrennten Sende- und Empfangsteil, sodass Vollduplexbetrieb<br />
möglich ist. Ein USART (Universal Synchronous/Asynchronous Receiver/Transmitter) bietet<br />
neben der asynchronen Betriebsweise auch synchrone Betriebsarten. Im synchronen Betrieb<br />
einer seriellen Übertragung werden Blöcke von Bytes (z. B. Zeichen oder beliebige<br />
Binärinformation) ohne Pausen übertragen. Die Synchronisation zwischen Sender und<br />
Empfänger, die beim asynchronen Betrieb für jedes Zeichen am Empfänger neu hergestellt<br />
werden muss, bleibt im synchronen Betrieb nicht nur während eines Zeichens erhalten,<br />
sondern während eines langen Bitstroms (Datenblock).<br />
Struktur von E/A-Bausteinen 32
Um die Syrichronisation auch dann aufrecht zu erhalten, wenn der Sender nicht schnell genug<br />
weitere Oktets liefern kann, wird solange automatisch ein vorgebbares<br />
Synchronisationszeichen übermittelt damit der serielle Bitstrom nie abreißt. Dadurch werden<br />
Start- und Stopbits überflüssig, was zu höheren effektiven Datenraten führt. Meist wird auch<br />
das Paritätsbit bei jedem Zeichen durch eine CRC-Prüfinfo (CRC = Cyclic Redundancy<br />
Check)am Ende einer ganzen Serie von Zeichen ersetzt, wodurch die Effektivität der<br />
Datenrate und der Fehlersicherung wesentlich erhöht wird.<br />
Daneben existieren noch viele weitere E/A-Bausteine. Sie sind i.a. wesentlich komplexer aufgebaut<br />
und bieten zahlreiche Programmierungsmöglichkeiten. Zum Beispiel:<br />
• Interrupt-Controller: Erweiterung der Interruptmöglichkeiten (Priorisierung,<br />
Vektorgenerierung)<br />
• Programmierbare Zähler (Timer, Counter) Auslösung von Interrupts in regelmäßigen<br />
Zeitabständen Erzeugen von Einzelimpulsen definierter Länge Erzeugung von<br />
Rechteckimpulsen<br />
• spezielle Steuerbausteine Memory Management, Floppy-Disk, Festplatte, Bildschirm,<br />
LC-Display, ...<br />
• Bausteine für DMA-Transfer<br />
Zusammenfassung: Aufgaben einer E/A-Schnittstelle<br />
Die Gesamtheit der Einrichtungen, über welche die CPU mit den peripheren Geräten kommuniziert,<br />
nennt man E/A-Schnittstelle. Im Allgemeinen findet ein (bidirektionaler) Datentransport zwischen<br />
Speicher und Peripherie statt. Neben dem reinen Datentransport ist eine Anpassung der<br />
Datendarstellung zwischen CPU und Peripherie erforderlich = Umsetzung der Bus- auf die<br />
Peripherieschnittstelle: Zeitliche Anpassung (CPU und Peripherie arbeiten i. a. nicht synchron, d. h.<br />
sie sind zeitlich zu entkoppeln).<br />
• Signalumsetzung (z. B. Pegelanpassung)<br />
• Datenformatanpassung (z. B. seriell/parallel-Wandlung)<br />
• Codewandlung<br />
• Fehlererkennung und -korrektur Schnittstellen können von unterschiedlicher Komplexität sein:<br />
• Im einfachsten Fall bestehen sie aus einer oder mehreren einfachen nicht-intelligenten<br />
E/A-Schnittstellen zur rein hardwaremäßigen Anpassung und Umsetzung. Die gesamte<br />
Steuerung des Datentransfers erfolgt durch die CPU programmierter E/A-Transfer.<br />
• Komplexere Schnittstellen können den Datentransfer autonom durchführen. Sie werden von<br />
der CPU nur angestoßen und wickeln den Datentransfer ohne weitere Hilfe der CPU ab<br />
Direkt- Speicher-Zugriff (DMA = Direct Memory Access) ohne Ablauf eigener<br />
Programme.<br />
• Flexiblere und leistungsfähigere Schnittstellen besitzen einen speziellen E/A-Prozessor, der<br />
nach einem Anstoß durch die CPU unabhängig vom (Haupt-)Prozessor mit eigenem<br />
Programm arbeitet und getrennten Zugriff zum Speicher besitzt.<br />
Steuerung von E/A-Bausteinen<br />
Steuersingnale von der CPU:<br />
• Rücksetzen (Reset, RES)<br />
• Freigabe, Aktivierung (Enable, E, CE)<br />
• Baustein-Auswahl (Chip Select, CS)<br />
• Register-Auswahl (Register Select, RS)<br />
• Datenrichtung (Read/Write, R/W)<br />
Mikrocomputertechnik<br />
Struktur von E/A-Bausteinen 33
Steuersignale von der Peripherie:<br />
• Interruptleitungen (Erzeugung IRQ-Signal für CPU)<br />
• weitere Steuersignale (z.B. Handshakeleitungen bei SIA)<br />
Steuerleitungen vom E/A-Baustein zur CPU:<br />
• Interrupt-Anforderung (Interr. Request, IRQ)<br />
• Weitergabe des IRQ von der Peripherie zur CPU (Maskierungsmöglichkeit)<br />
• Erzeugung eines IRQ-Signals durch E/A-Baustein selbst<br />
Anschluß von E/A-Bausteinen<br />
Mikrocomputertechnik<br />
Die Steuersignale werden mit dem Steuer-Bus verbunden. Aus dem Adreß-Bus werden die<br />
Cchip-Select- und Register-Select-Signale abgeleitet. Normalerweise werden die RS-Signale mit<br />
den niederwerigen Adreßleitungen verbunden (RS 0 mit A 0 , RS 1 mit A 1 , usw.). Über den Daten-Bus<br />
erfolgt der eigentliche Datenaustausch.<br />
Da i. a. mehrere E/A-Bausteine (mit mehreren Registern) an ein System angeschlossen werden, ist<br />
eine Adressierung der E/A-Bausteine nötig. Es gibt dafür zwei Methoden:<br />
1. Getrennte Adressierung (Isolated I/O, I/O-Mapped I/O)<br />
Der Rechner verfügt über spezielle E/A-Befehle und einen eigenen E/A-Adreßraum. Die<br />
E/A-Adresse wird oft auch Port genannt. Sie wird entweder auf separaten Adressleitungen<br />
zu den Schnittstellen geführt oder über den normalen Adreßbus geleitet. In diesem Fall gibt<br />
es (eine) zusätzliche Steuerleitung(en) zur Unterscheidung zwischen E/A- und<br />
Speicheradressen. Da i.a. der E/A-Adreßraum kleiner als der Speicheradreßraum ist, wird<br />
nur ein Teil der A-Bus-Leitungen verwendet (z. B. 8080/8085: 8 Bit, 80386: 10 Bit).<br />
2. Speicheradressierung (Memory Mapped I/O)<br />
Der E/A-Adreßraum wird in den Speicher-Adreßraum abgebildet, d.h. bestimmte Adressen<br />
stellen keine Speicheradressen, sondern E/A-Adressen dar geringfügige Einschränkung<br />
des Speicheradreßraums. Die E/A-Adressen werden von der CPU genauso behandelt und<br />
angesprochen, wie Speicheradressen. E/A-Operationen werden mit den normalen<br />
Transportbefehlen durchgeführt (z. B. Load, Store) Einsparung zusätzlichen Aufwandes<br />
für Adreß-/Steuerleitungen und für spezielle E/A-Befehle.<br />
Steuerung von E/A-Bausteinen 34
Programmgesteuerter E/A-Transfer (Polling)<br />
Einfache E/A-Schnittstellen für programmierten E/A-Transfer bestehen wesentlich aus:<br />
• E/A-Datenregister (EADR)<br />
• E/A-Steuer- und Statusregister (EASR)<br />
• Adreß- und Steuerlogik<br />
Mikrocomputertechnik<br />
Sie ist normalerweise an den Systembus der CPU angeschlossen. Das EADR dient zur<br />
Zwischenspeicherung des zu übertragenden Datenwerts (zeitliche Anpassung). Neben den zu<br />
übertragenden Daten braucht die Schnittstelle Signale zur richtigen Abwicklung des Datentransfers:<br />
• Statussignale von der Peripherie<br />
z. B. Anzeige, dass das Peripheriegerät einen neuen Wert ins EADR geliefert hat oder bereit<br />
ist, den nächsten Wert zu übernehmen.<br />
• Steuersignale zur Peripherie<br />
z. B. Anzeige, dass der vorhergehende Datenwert gelesen wurde und die Peripherie einen<br />
neuen Wert ins EADR einschreiben kann.<br />
• Steuersignale zur Schnittstelle selbst<br />
z. B. Signale zum Einstellen bestimmter Betriebsmodi bei programmierbaren Schnittstellen.<br />
Diese Signale werden - soweit sie für längere Zeit zur Verfügung stehen müssen - im EASR<br />
gespeichert. Das EASR kann auch aus separaten Registern für Status- und Steuersignale bestehen.<br />
Normalerweise verfügt ein Computer über mehr als eine E/A-Schnittstellen Adressierung<br />
erforderlich. Im allgemeinen erhalten EADR und EASR eine eigene, separate Adresse. Beide sind<br />
am Datenbus angeschlossen. Steuersignale werden wie Datenwerte ins EASR geschrieben,<br />
Statussignale werden wie Datenworte aus dem EASR gelesen - die Verarbeitung muss in der CPU<br />
durch geeignete Befehle erfolgen (z.B. logische Verknüpfung).<br />
Anschluß von E/A-Bausteinen 35
Die E/A-Befehlsfolge steht innerhalb eines Programms und wird im Rahmen der normalen<br />
Programmausführung abgearbeitet. Die gesamte Initiative zur E/A geht vom Programm aus. Zeigt<br />
der Inhalt des EASR an, dass keine neuen Daten im EADR stehen, muss das Programm erneut das<br />
EASR abfragen Warteschleife, "Polling". Dabei können zwei "Randbereiche" Probleme<br />
verursachen:<br />
• Die Zeit, die das Programm braucht, um einen Eingabewert zu bearbeiten ist manchmal<br />
(oder sogar immer) länger als die Zeitspanne innerhalb der sich das Eingangssignal ändern<br />
kann es werden Ereignisse "übersehen".<br />
• Bei "langsamen" Peripheriegeräten ist der Computer während der Übertragung eines<br />
Datenblocks die meiste Zeit mit Abfragen bschäftigt, die in den meisten Fällen negativ<br />
ausfallen.<br />
Direktspeicherzugriff (DMA = Direct Memory Access)<br />
Beim DMA steuert die E/A-Schnittstelle den Transfer nach Anstoß durch die CPU selbstständig<br />
und ohne Zuhilfenahme der CPU Datentransport zwischen Speicher und Peripherie unter<br />
Umgehung der CPU. Selbst, wen die CPU in dieser Zeit nichts anderes tut, ist ein wesentlich<br />
schnellerer Datentransport möglich (weitgehender Wegfall der Verwaltungsarbeit). Daher ist DMA<br />
für den schnellen Transfer großer Datenmengen besonders geeignet. Zum Anstoßen des<br />
DMA-Transfers übermittelt die CPU der DMA-Schnittstelle:<br />
• die Anfangsadresse (im Arbeitsspeicher) des zu übertragenden Datenblocks<br />
• die Länge des zu übertragenden Datenblocks<br />
• Gegebenenfalls muss noch - wie beim programmierten Transfer - das EASR entsprechend<br />
geladen werden Initialisierung der Schnittstelle.<br />
Die DMA-Schnittstelle benötigt zwei weitere Register:<br />
• E/A-Adreßregister (EAAR)<br />
• E/A-Blocklängenzähler (EAZR)<br />
Mikrocomputertechnik<br />
Programmgesteuerter E/A-Transfer (Polling) 36
Da während des DMA-Transfers anstelle der CPU die DMA-Schnittstelle die Kontrolle über den<br />
Systembus besitzt, muss sie zusätzlich über eine Bus-Steuerlogik verfügen (Konkurrenz zwischen<br />
DMA Schnittstelle und CPU um den Bus).<br />
Ablauf eines DMA-Transfers:<br />
• Initialisieren der DMA-Schnittstelle<br />
• Bus-Freigabe-Anforderung an die CPU (DMA-Request)<br />
• CPU bestätigt Bus-Freigabe (DMA-Acknowledge) (Die Bus-Freigabe der CPU geschieht<br />
durch Umschalten der Bustreiber-Ausgänge in den hochohmigen Zustand)<br />
• Nun bedient die DMA-Schnittstelle den Adreß-, Daten- und Steuerbus auf die gleiche Art<br />
und Weise, wie die CPU. Der Inhalt des EAAR wird an den A-Bus gelegt und die für die<br />
Speichersteuerung notwendigen Signale auf den Steuerbus. Das EADR wird mit dem<br />
Datenbus verbunden.<br />
Man unterscheidet verschiedene DMA-Modi:<br />
• Byteweise Übertragung (Byte Mode)<br />
Die CPU gibt auf DMA-Request hin den Bus nach Beendigung des gerade laufenden<br />
Maschinenzyklus frei. Nach dem Transfer eines Datenwortes erhält die CPU die Kontrolle<br />
über den Bus zurück und sie setzt den laufenden Befehl weiter fort (bis zum nächsten<br />
DMA-Request) Cycle Stealing.<br />
• Burst-Modus<br />
Auch hier wird die CPU mitten in der Bearbeitung eines Befehls kurz angehalten, jedoch<br />
für mehrere Zyklen Transfer eines ganzen Datenblocks.<br />
• Halt-Modus<br />
Die CPU wird nach Beendigung der gerade laufenden Instruktion angehalten - solange, bis<br />
der DMA-Transfer eines ganzen Blocks abgewickelt ist.<br />
• Transparent-Modus<br />
DMA-Schnittstelle und CPU arbeiten zeitmultiplex während jedes Maschinenzyklus jeweils<br />
in einer halben Periode. Dazu ist ein sehr schneller Speicher erforderlich keine<br />
Beeinträchtigung der CPU.<br />
2.5 Timer (Zeitgeber)<br />
Mikrocomputertechnik<br />
Zur Gruppe der Port-Level-Controller gehören auch die sehr häufig eingesetzten Zähler- und<br />
Zeitgeber-Bausteine. Da in den meisten Systemen Impulse gezählt oder erzeugt werden bzw. die<br />
Dauer von Impulsen gemessen werden muss, stellt es eine große Entlastung der CPU dar, wenn<br />
diese Vorgänge nicht per Programm gesteuert, sondern durch zusätzliche Hardware unterstützt<br />
werden.<br />
Ein Timer besteht aus einem programmierbaren (voreinstellbaren) Rückwärts-Zähler mit eigenem,<br />
vom Prozessor unabhängigen, Takt. Der Takt kann über Steuerregister freigegeben bzw. gesperrt<br />
werden. Der aktuelle Zählerstand kann jederzeit von der CPU ausgelessen werden. Bei Zählerstand<br />
0 wird ein maskierbarer Interrupt erzeugt. Der Timer hat in der Regel mehrere Modi:<br />
Direktspeicherzugriff (DMA = Direct Memory Access) 37
• Rechteckgenerator bzw. Zähler: Beim Erreichen des Zählerstandes 0 wird ein Interrupt<br />
erzeugt und automatisch wieder der Startwert geladen. Somit erfolgt ein Interrupt in<br />
regelmäßigen Zeitabständen.<br />
• Monoflop, One-Shot: Nach Erreichen des Zählerstandes 0 wird ein Interrupt erzeugt und<br />
dann bleibt der Timer inaktiv, bis wieder ein Startwert geladen wird. Typische<br />
Anwendungen dieser Monoflops sind auch Programmüberwachungen (Watchdog) in<br />
Systemen mit einer Endlos-Programmschleife, die zyklisch durchlaufen wird: Ein Befehl<br />
innerhalb dieser Schleife triggert das Monoflop nach; geschieht das nicht mehr, so hat sich<br />
das Programm "aufgehängt" und das System würde fehlerhaft arbeiten. Das Abfallen des<br />
Monoflops signalisiert jedoch per Interrupt den Fehler. Gegebenenfalls kann man einen<br />
Neustart des Systems (Reset) auslösen.<br />
• Frequenz- oder Periodendauermessung: Der Interrupt erfolgt, wenn die Freqenz bzw.<br />
Periodendauer eines an einem externen Eingang angelegten Signals länger dauert, als die<br />
Timerperiode. Durch Variation des Startwertes kann die Frequenz bzw. Periodendauer<br />
gemessen werden.<br />
• Rechtecksignal mit variablem Tastverhältnis<br />
• Verzögerter Impuls softwaregetriggert<br />
• Verzögerter Impuls hardwaregetriggert<br />
• und andere ...<br />
Anwendungen:<br />
• Erzeugen von Interrupts in festen Zeitabständen<br />
• Rechteckgenerator mit programmierbarer Frequenz<br />
• Monoflop mit programmierbarer Zeit<br />
• Pulsweiten-Modulation<br />
• "Watch-Dog" (Reseterzeugung, wenn nicht regelmäßig per Software nachgetriggert wird<br />
automatisches Rücksetzen bei Störungen)<br />
2.6 Systemkonfigurationen<br />
Dieses Kapitel zeigt die Zusammenschaltung von Speicher (RAM, ROM) und E/A-Bausteinen zu<br />
einem Mikrocomputer-System. Die zeitliche Koordination wied hier nicht behandelt (da von<br />
Prozessor zu Prozessor verschieden).<br />
Aufteilung des Adreßraums<br />
Mikrocomputertechnik<br />
Hierbei geht es um die Zuordnung verschiedener Speicher- und E/A-Bereiche zu den Adressen.<br />
Man unterscheidet:<br />
• Voll-Decodierung<br />
Die Adressierung jedes Bausteins wird unter Verwendung aller Adreßleitungen decodiert.<br />
2.5 Timer (Zeitgeber) 38
•<br />
Weitere Bausteine sind problemlos zuschaltbar.<br />
Vorteil: Adreßraum nur soweit nötig gebraucht, Erweiterung problemlos<br />
Nachteil: Mehr Hardware nötig<br />
Minimaldecodierung:<br />
Es wird nur eine Minimalzahl von Adreßleitungen ausgewertet. Der Speicher und die<br />
E/A-Schnittstellen erscheinen mehrmals unter verschiedenen Adressen.<br />
Vorteil: Minimaler Schaltungsaufwand<br />
Nachteil: Adreßraum wird vollständig verbraucht<br />
In der Praxis finden sich häufig Mischformen (Teildecodierung), d. h. es wird nur soweit decodiert,<br />
daß alle Bausteine einen eigenen Adreßraum besitzen - also eindeutig ansprechbar sind. Dabei kann<br />
es durchaus sein, daß ein Baustein unter mehreren Adressen ansprechbar ist Bauteileersparnis<br />
beim Decodieren.<br />
Oft erfolgt die Vergabe bestimmter Bereiche für bestimmte Gruppen von Bausteinen, z. B. ROM: 0<br />
- $7FFF, RAM: $8000 - $8FFF, E/A: F000 - FFFF.<br />
Die Vergabe ist vom Prozessor abhängig (8080: ROM bei 0, 6800: ROM bei $FFFF wegen<br />
Reset-Vektor). In letzteren Fall kann man durch Teildecodierung erreichen, daß das ROM sowohl<br />
bei 0, als auch bei $FFFF adressierbar ist.<br />
Systembeispiel<br />
Minimalsystem mit 6802:<br />
Mikrocomputertechnik<br />
• Prozessor 6802 (mit 128 Byte RAM)<br />
• EPROM 2732 als Programmspeicher (4K x 8)<br />
• PIA 6821 als E/A-Baustein<br />
• Adreßraum:<br />
♦ RAM: $0000 - $007F<br />
♦ ROM: $F000 - $FFFF<br />
♦ PIO: $0080 - $0083 (memory mapped I/O)<br />
Aufteilung des Adreßraums 39
Beispiele zur Systemkonfiguration<br />
1. Volldecodierung:<br />
Prozessor mit eingebautem RAM<br />
CS vom ROM active low!<br />
2. Volldecodierung, erweitert<br />
CS von ROM und RAM active low!<br />
3. Minimaldecodierung<br />
CS vom ROM und PIO active low!<br />
Mikrocomputertechnik<br />
Beispiele zur Systemkonfiguration 40
Adressierung modulo $1000!<br />
ROM erscheint bei $0000, $1000, $2000, ..., $D000, $E000, $F000<br />
4. Minimaldecodierung ROM und E/A<br />
Mikrocomputertechnik<br />
Adressierung modulo $1000!<br />
ROM erscheint bei $0000, $1000, $2000, ..., $7000<br />
PIO erscheint bei $8000, $8004, $8008, ..., $FFFF<br />
5. Teildecodierung (Volldecodierung mit Lücken)<br />
µP, D− und S−Bus aus Platzgründen weggelassen!<br />
CS active low!<br />
Beispiele zur Systemkonfiguration 41
Mikrocomputertechnik<br />
RAM erscheint bei $0000, $4000, usw.<br />
ROM erscheint bei $1000, $5000, usw.<br />
PIO 1 belegt den gesamten Bereich $2000 - $2FFF, $6000 - $6FFF, usw.<br />
PIO 2 belegt den gesamten Bereich $3000 - $3FFF, $7000 - $7FFF, usw.<br />
2.7 Programmunterbrechungen<br />
Programmunterbrechungen können durch Signale aus der Rechnerumgebung (z.B. vom gesteuerten<br />
Prozeß) ausgelöst werden, um quasi "die Aufmerksamkeit" des Rechners auf sich zu lenken.<br />
Insbesondere auf dringende, aber relativ selten auftretende Ereignisse können so die entsprechenden<br />
Programme (Interrupt Service Routinen) schnell reagieren.<br />
In der Regel führt die Ablaufsteuerung nach der Beendigung des gerade ausgeführten Befehls die<br />
Programmunterbrechung durch und setzt nach der Abarbeitung der Interrupt Service Routine (ISR)<br />
das unterbrochene Programm fort.<br />
Die Aufgaben der Interruptbehandlung im einzelnen:<br />
a. Aufnehmen und Überprüfen der Unterbrechungsanforderung:<br />
Im einfachsten Fall hat das Unterbrechungswerk nur eine einzige Eingangsleitung für die<br />
Unterbrechungsanforderungen. Diese führt auf ein Flip-Flop, das durch ein<br />
Anforderungssignal auf 1 gesetzt wird und bei Bedienung des Interrupts sofort wieder<br />
gelöscht werden muß um evtl. weitere Interrupt-Anforderungen aufnehmen zu können.<br />
Dieses FF ist notwendig, um die zu beliebigen Zeitpunkten ankommenden<br />
2.7 Programmunterbrechungen 42
.<br />
Mikrocomputertechnik<br />
Interrupt-Anforderungen (Interrupt-Request) so lange zu speichern, bis sie vom Leitwerk<br />
am Ende der Befehlszyklen abgefragt werden.<br />
Häufig darf jedoch eine Interrupt-Anforderung nicht sofort zur Unterbrechung führen, z.B.<br />
während der Ausführung zeitkritischer Programmabschnitte. Eine einfache Möglichkeit<br />
besteht in der "Maskierung" des Signals mit Hilfe eines Masken-FF's und eines Gatters. Nur<br />
wenn das Masken-FF gesetzt ist, führt eine "anstehende" Unterbrechungsanforderung auch<br />
zu einem Interrupt. Das Masken-FF kann i.a. durch Maschinenbefehle gesetzt und gelöscht<br />
werden ("enable" bzw. "disable interrupt").<br />
Identifizierung des Interrupt-Verursachers:<br />
Typische Anwendungen mit mehreren Quellen für Interrupt-Anforderungen verlangen, daß<br />
für jedes Signal auch ein spezifisches Unterbrechungs-Bearbeitungs-Programm (ISR =<br />
Interrupt Service Routine) vorhanden ist, da ja auf jedes Signal anders zu reagieren ist.<br />
Damit ergibt sich das Problem der Interrupt-Identifizierung als Voraussetzung für die<br />
Zuordnung der richtigen ISR und für das Löschen des richtigen<br />
Interrupt-Anforderungs-Flip-Flops.<br />
Die beiden wichtigsten Grundprinzipien der Interrupt-Identifizierung sind:<br />
♦ Polling: Der Interrupt-Verursacher kann sich nicht selbst zu erkennen geben; am<br />
Prozessor erscheint lediglich das Anforderungssignal und es ist die Aufgabe des<br />
Interrupt-Bearbeitungs-Programms, über eine Kette von Abfragen an die in Frage<br />
kommenden Peripherie-Bausteine, den aktuellen Interrupt-Verursacher<br />
herauszufinden. Mit "Abfragen" ist hier das Lesen der Statusregister der<br />
Peripheriebausteine gemeint, in denen die Tatsache der Interrupt-Anforderung<br />
jeweils in einem bestimmten gesetzten Bit (Interrupt-Request-Bit) vermerkt ist.<br />
♦ Interrupt-Vectoring: Der Interruptverursacher liefert (im Zuge der Bussequenzen<br />
bei der Interrupt-Annahme durch den Prozessor) einen "Kenn-Code" mit ab (meist<br />
über den Datenbus), an dem der Prozessor erkennen kann, um welchen Interrupt es<br />
sich handelt. Dieser sogen. "Interrupt-Vektor" wird i.a. gleich als (indirekte)<br />
Startadresse der zugehörigen ISR verwendet. Damit entfällt das zeitraubende<br />
Abfragen, die sogenannte Interrupt-Reaktionszeit wird kürzer.<br />
c. Vorrangsteuerung der Interruptverursacher:<br />
Nicht alle Interrupts sind mit der gleichen Dringlichkeit zu bearbeiten; so muß z.B. die<br />
Interrupt-Anforderung, die den Zusammenbruch der Netzspannung anzeigt, vorrangig<br />
behandelt werden gegenüber einer Interrupt-Anforderung, die lediglich zur Übernahme<br />
eines Datenwortes von einer Eingabeschnittstelle auffordert.<br />
d. Retten und Rückspeichern des Prozessorzustandes:<br />
Wenn eine Programmunterbrechung ausgeführt werden soll, so muß auf jeden Fall der<br />
Zustand des Prozessors gerettet werden. Denn das Interrupt-Service-Programm benutzt ja<br />
ebenfalls den Prozessor und verändert dabei dessen Zustand. Soll anschließend das<br />
unterbrochene Programm fortgesetzt werden, so ist es unbedingt nötig, vorher den Zustand<br />
wieder herzustellen, wie er bei Auftreten der Unterbrechung herrschte. Die<br />
Prozessorzustände, die während einer Befehlsausführung durchlaufen werden, sind nur sehr<br />
aufwendig zu beschreiben (z. B. mitten in einer Multiplikation). Entsprechend groß wäre<br />
der Aufwand zur Rettung des Prozessorzustandes, wenn man Unterbrechungen mitten im<br />
Befehlszyklus zuließe. Man läßt deshalb Unterbrechungen i. a. nur am Ende eines Befehls<br />
2.7 Programmunterbrechungen 43
Mikrocomputertechnik<br />
zu, denn dann ist der Prozessorzustand vollständig durch den Inhalt der Prozessorregister<br />
definiert.<br />
In einer typischen Interrupt-Service-Routine werden die Inhalte von Prozessor-Registern<br />
verändert. Aber selbst wenn keine derartigen Befehle in der ISR vorkommen, so müssen<br />
doch zumindest zwei Register gerettet werden: der Programmzähler und das<br />
Prozessor-Status-Register, denn die Inhalte dieser Register ändern sich in jedem Fall. Man<br />
bezeichnet diese beiden Register auch als "Zustandsvektor". Die einfachste Möglichkeit,<br />
den Zustandsvektor zu retten, besteht darin, ihn in bestimmte reservierte Speicherzellen zu<br />
schreiben, und ihn von dort nach Beendigung der ISR wieder zu lesen. Dies hat den<br />
offensichtlichen Nachteil, daß keine Verschachtelung (Nesting) von<br />
Programmunterbrechungen möglich ist, d.h. man müßte das Unterbrechen einer ISR<br />
verbieten, weil sonst der gerettete Zustandsvektor überschrieben würde.<br />
Wesentlich besser eignet sich zum Retten des Zustandsvektors ein sogenannter<br />
Kellerspeicher (engl. stack, oder auch LIFO = last in first out). Das Stackprinzip kann<br />
hardwaremäßig realisiert sein (spezielle Chips) oder in einem reservierten Bereich des<br />
normalen Arbeitsspeichers nachgebildet sein. Zu diesem Zweck existiert ein Zeigerregister,<br />
das immer den letzten Eintrag im Stack adressiert (Stackpointer zeigt immer auf den "Top<br />
of Stack", d.h. auf den letzten Eintrag).<br />
Mit jeder neuen (geschachtelten) Programmunterbrechung wächst der Kellerspeicher um<br />
die entsprechenden Einträge, mit jedem Rücksprung in ein vorher unterbrochenes<br />
Programm reduziert er sich wieder entsprechend, so daß das zuletzt unterbrochene<br />
Programm nach Beendigung des laufenden wieder aufgenommen wird. Der Stack wächst<br />
und schrumpft mit jedem Eintreten/Verlassen von ISRs, man sagt, der Stack "pulsiert".<br />
Häufig müssen außer den beiden o.g. Registern (PC und Prozessor-Status-Register) auch<br />
noch andere gerettet und rückgespeichert werden, nämlich dann, wenn sie von der ISR<br />
verändert werden. Auch hier bringt die Verwendung eines Stacks die gleichen Vorteile wie<br />
oben erwähnt. Da diese Register jedoch nicht immer gerettet werden müssen besteht hier<br />
die Möglichkeit, sie entweder genau wie den Zustandsvektor per Hardware (d.h. per<br />
Ablaufsteuerung) zu retten oder per Maschinenbefehl(e), also programmgesteuert.<br />
Während bei der Hardware-Lösung sämtliche Register gerettet werden müssen (sie "weiß"<br />
je nicht, welche es sein müssen), kann die programmierte Lösung sich auf genau die<br />
Register beschränken, die in der ISR verändert werden (der Programmierer weiß welche -<br />
hoffentlich!). Die sicherere und meist auch schnellere, jedoch auch aufwendigere Methode<br />
ist die Hardware-Lösung.<br />
Die Notwendigkeit, bei der Ausführung einer Programmunterbrechung zunächst den Zustand des<br />
unterbrochenen Programms zu retten, kann also eine Reihe von Transportoperationen benötigen;<br />
vom Moment des Eintreffens der Unterbrechnungsanforderung vergeht daher einige Zeit, die<br />
Interrupt-Reaktionszeit, bis der erste produktive Befehl der ISR ausgeführt wird. Diese<br />
Reaktionszeit setzt sich aus den folgenden Komponenten zusammen:<br />
• T1: Durchschaltezeit (der Anforderung bis zur Unterbrechungsanmeldung) aufgrund einer<br />
gesetzten Sperre (z.B. auch dann, wenn gerade eine Interrupt-Service-Routine bearbeitet<br />
wird). Diese Zeit kann u.U. recht lang sein!<br />
• T2: Wartezeit bis zur Beendigung des gerade ausgeführten Befehls (maximal die des<br />
längsten vorkommenden Befehls)<br />
• T3: Zeit zum Retten des Programm-Zustandes und Laden des Unterbrechungs-Vektors.<br />
Selbst wenn die Durchschaltung der Anforderung unmittelbar erfolgt (T1 = 0, weil keine<br />
Sperre gesetzt ist), kann die Summe von T2 und T3 für zeitkritische Echtzeitanforderungen<br />
doch noch zu groß sein.<br />
2.7 Programmunterbrechungen 44
Mikrocomputertechnik<br />
Unterbrechungsgesteuerter E/A-Transfer<br />
Die E/A-Befehlsfolge wird durch einen von der E/A-Schnittstelle ausgelösten Interrupt gestartet.<br />
Der Interrupt wird von der Schnittstelle abgesetzt, wenn ein Datenwort empfangen wurde und im<br />
EADR steht (bzw. wenn ein Datenwort aus dem EADR abgeholt wurde). Die CPU braucht nicht in<br />
einer Programmschleife zu warten, sondern kann in der Zwischenzeit ein anderes Programm<br />
bearbeiten, das durch den Interrupt kurzzeitig unterbrochen wird. Der interruptgesteuerte Transfer<br />
gestattet zudem die quasi-simultane Bedienung mehrerer langsamer Schnittstellen. Zur Realisierung<br />
muß eine Interrupt-Leitung von der E/A-Schnittstelle (EASR) zum Unterbrechungswerk der CPU<br />
vorhanden sein.<br />
Vorteil des programmierten Transfers: Sehr einfache Schnittstellen, die übersichtlich und leicht zu<br />
verwenden sind.<br />
Nachteil des programmierten Transfers: Für den Transfer jedes einzelnen Datenworts wird die CPU<br />
benötigt. Diese muss dabei relativ viel Verwaltungsaufwand leisten (Laden/lesen EASR,<br />
Interrupt-Behandlung) die maximale Datenrate ist sehr begrenzt.<br />
Durch den Interupt wird auch der Befehlszyklus erweitert. Nach Abarbeitung des Befehls wird das<br />
Vorhandensein eines Interrupts geprüft und ggebenenfalls in die Interrupt-Serviceroutine (ISR)<br />
verzweigt. Dabei werden alle Register auf dem Stack abgelegt und beim Beenden der ISR wieder<br />
restauriert.<br />
Unterbrechungsgesteuerter E/A-Transfer 45
Man unterscheidet bei der Adressangabe für die ISR zwei Möglichkeiten:<br />
• vektorisierter Interrupt: Es kann der ISR eine beliebige Adresse zugeordnet werden,<br />
welche von der CPU eingelesen wird.<br />
• nicht vektorisierter Interrupt: Der ISR wird eine feste Startadresse zugeordnet.<br />
Zum vorhergehenden Abschnitt Zum Inhaltsverzeichnis Zum nächsten Abschnitt<br />
Copyright © FH München, FB 04, Prof. Jürgen Plate<br />
Letzte Aktualisierung: 07. Okt 2012<br />
Mikrocomputertechnik<br />
Mikrocomputertechnik<br />
Prof. Jürgen Plate<br />
Unterbrechungsgesteuerter E/A-Transfer 46
3. Programmierung des Mikroprozessors<br />
68HC11<br />
3.1 Überblick<br />
Programmiermodell<br />
Da man wohl kaum einen Schaltplan des CPU-Herstellers bekommt und da dieser auch viel zu<br />
komplex ist, wird für die Programmierung mit dem sogenannten "Programmiermodell" gearbeitet.<br />
Dies umfaßt:<br />
• Die Gesamtheit der dem Programmierer zugänglichen Register der CPU<br />
• Die Gesamtheit der vom Programmierer veränderbaren Register der CPU<br />
Der Prozessor 68HC11 ist eine Weiterentwicklung des 6800 (weitgehend befehlskompatibel,<br />
erweiterter Befehlssatz, zusätzliche Register). Der 68HC11 besitzt vier 8-Bit-Register und fünf<br />
16-Bit-Register:<br />
• 2 Akkumulatoren A und B (8 Bit)<br />
♦ Zusammenfassung von A und B zum 16-Bit-Akku D (A: MSB, B: LSB)<br />
16-Bit-Instruktionen<br />
♦ Beide Akkumulatoren werden gleich behandelt<br />
♦ Zwei Akkus Vorteile bei der Programmierung (z. B. bei Schleife: A zum Rechnen,<br />
B als Schleifenzähler)<br />
• Program Counter PC (Befehlszähler, 16 Bit) 64 K Adreßraum<br />
• Stackpointer S<br />
Für Unterprogrammsprünge, Prozessor-Status bei Interrupt Der Stackpointer kann auch als<br />
Index-Register verwendet werden<br />
• 2 Indexregister X und Y (16 Bit)<br />
3. Programmierung des Mikroprozessors 68HC11 47
♦ Für indizierte Adressierung<br />
♦ Beide sind gleichwertig (Abarbeitung mit X etwas schneller als mit Y)<br />
• Condition Code Register CC (8 Bit) Statusregister (3 Bit für Stop/Interrupt-Verarbeitung, 5<br />
Bit für ALU)<br />
♦ Jedes Bit wirkt wie ein Flip-Flop (1 = gesetzt, 0 = rückges.)<br />
♦ Welche Bits (= Flags) von den einzelnen Befehlen auf welche Art beeinflusst werden,<br />
ist in der Befehlsliste angegeben.<br />
♦ Ein Flag bleibt solange unverändert, bis ein Befehl ausgeführt wird, der es beeinflusst.<br />
♦ Jedes Bit des CC kann per Befehl gezielt gesetzt/rückgesetzt werden<br />
♦ Die Bedeutung der Bits:<br />
C: Carry-Flag<br />
1, wenn bei arithmetischen Operationen ein Übertrag vom höchstwertigen Bit<br />
auftritt (bei Subtraktion: wenn "geborgt" wird). Wird ausserdem durch<br />
Schiebe- und Rotationsbefehle beeinflußt.<br />
V: Overflow-Flag<br />
1, wenn ein Arithmetik-Überlauf (Zahlenbereichsüberschreitung) auftritt.<br />
Dies tritt nur bei konegativen Zahlen auf und ist dann der Fall, wenn bei<br />
Addition oder Subtraktion die beiden Operanden das gleiche Vorzeichen<br />
besitzen und das Vorzeichen des Ergebnisses davon verschieden ist.<br />
Z: Zero-Flag<br />
1, wenn das Ergebnis einer Operation das Ergebnis Null hat.<br />
N: Negativ-Flag<br />
1, wenn das Ergebnis einer Operation negativ ist. Das N-Bit ist gleich dem<br />
höchstwertigen Bit des Ergebnisses.<br />
H: Half-Carry-Flag<br />
1, wenn bei einer 8-Bit-Operation ein Übertrag von Bit 3 nach Bit 4 auftritt.<br />
I: Interrupt Mask<br />
Falls 1, werden Interrupt-Anforderungen auf der IRQ-Leitung nicht bedient<br />
(Freigabe des IRQ I-Bit auf 0 setzen). Bleibt solange gesperrt, solange der<br />
Stackpointer nicht initialisiert wurde.<br />
X: Non Maskable Interrupt Mask<br />
Falls 1, werden Interrupt-Anforderungen auf der NMI-Leitung nicht bedient.<br />
Eigentlich ein Paradox, denn der NMI sollte ja gerade nicht maskierbar sein.<br />
Der NMI wird jedoch gesperrt, wenn der Stackpointer noch nicht initialisiert<br />
wurde und wenn gerade die NMI-Interrupt-Serviceroutine abgearbeitet wird.<br />
S: Stop disable<br />
1, wenn der STOP-Befehl nicht ausgeführt werden soll.<br />
Einteilung der Befehle<br />
Mikrocomputertechnik<br />
Programmiermodell 48
Der 68HC11 kennt 59 verschiedene Grundbefehle überschaubarer Befehlssatz. Anwendung der<br />
Befehle mit unterschiedlichen Registern und Adressierungsarten führt zu 1464 verschiedenen<br />
OP-Codes. Der OP-Code besteht (einschließlich Angabe über Adressierungart) aus einem, zwei oder<br />
drei Bytes: Der Adreßteil (falls vorhanden) besteht aus einem oder zwei Bytes; es gibt also 1-, 2-, 3-,<br />
4- und 5-Byte-Befehle. Das Befehlsformat kann also sein:<br />
Das "prebyte" erweitert den Befehlsumfang, so daß mehr als 256 Befehle möglich sind. Der Nachteil<br />
dabei ist, daß die Abarbeitung des Befehls länger dauert und der Befehl natürlich auch ein Byte mehr<br />
an Speicher braucht.<br />
Adressen werden in zwei aufeinanderfolgenden Speicherbytes abgelegt und zwar in der Form<br />
AH AL<br />
ea ea+1<br />
Mit "ea" wird die effektive Adresse = echte Adresse = Adresse des Operanden im Speicher<br />
bezeichnet. Je nach Adressierungsart (siehe unten) ist eine Adreßberechnung notwendig. Das Ergebnis<br />
der Adreßrechnung landet im Adreßregister und wird dann zur Adressierung des Speichers verwendet.<br />
Befehlsklassen:<br />
• Verarbeitungsbefehle<br />
♦ Transportbefehle<br />
♦ arithmetische Befehle<br />
♦ logische Befehle<br />
♦ Schiebe- und Rotations-Befehle<br />
• Steuerbefehle<br />
♦ Testbefehle (beeinflussen CC-Register)<br />
♦ Sprungbefehle<br />
♦ Unterbrechungsbefehle<br />
♦ Befehle zur Beeinflussung des Systemzustands<br />
Angaben über gültige Adressierungsarten, Länge, CC-Beeinflussung, Dauer (Anzahl der Taktzyklen)<br />
stehen in der Befehlstabelle.<br />
3.2 Adressierungsarten<br />
Mikrocomputertechnik<br />
Einteilung der Befehle 49
Die meisten Befehle gestatten mehrere Adressierungsarten, aber nicht alle Adressierungarten lassen<br />
sich auf jeden Befehl anwenden. Jede zulässige Adressierungsart bei einem Befehl führt zu einen<br />
eigenen OP-Code. Die zulässigen Adressierungsarten und der jeweilige OP-Code lassen sich der<br />
Befehlsliste entnehmen. Die tatsächliche Länge und Ausführungszeit eines Befehls hängen von der<br />
Adressierungsart ab. Die Zahl der Bytes eines Befehls und seine Ausführungszeit lassen sich aus der<br />
Befehlsliste entnehmen.<br />
Konstanten-Adressierung (Immediate Addressing)<br />
Die Daten folgen unmittelbar auf den OP-Code. Je nach Befehl/Register sind es 8 Bit (1 Byte) oder 16<br />
Bit (2 Byte). Im <strong>Assembler</strong> wird dies durch Voranstellen von "#" kenntlich gemacht, zum Beispiel:<br />
LDAA #20 - Lade Akku A mit dem Wert 20<br />
Absolute Adressierung<br />
Mikrocomputertechnik<br />
Absolut vollständige Adressierung (Extended Addressing)<br />
Der Adreßteil des Befehls enthält eine vollständige 16-Bit-Adresse. Es ist eine Adressierung des<br />
gesamten Adreßraums möglich. Zum Beispiel:<br />
LDAA $A174 - Lade Akku A mit dem Inhalt der Speicherzelle $A174<br />
Absolut unvollständige Adressierung (Zero Page / Direct Addressing)<br />
Der Adreßteil enthält nur den niederwertigen Teil (LSB) der Adresse. Der höherwertige Teil wird auf<br />
Null gesetzt. Damit lassen sich die Adressen zwischen 0 und 255 ($0 - $FF) erreichen. Der Befehl ist<br />
ein Byte kürzer als bei der absoluten Adressierung und deshalb auch schneller in der Ausführung. Im<br />
<strong>Assembler</strong> wird dies durch Voranstellen von "
Implizite Adressierung (Inherent Addressing)<br />
Alle Adreßangaben sind im OP-Code des Befehls enthalten, es gibt keinen Adreßteil.<br />
• AD-Teil im Befehl nicht nötig<br />
• entweder keine AD-Angabe nötig (NOP)<br />
• oder AD-Angabe bezieht sich auf Register (LSRA, ABX, ...)<br />
Indizierte Adressierung (Indexed Addressing)<br />
Die effektive Adresse ergibt sich hier aus dem Inhalt eines Adreßregisters (z. B. X oder Y) und einer<br />
dazu addierten Distanz (Offset), die auch Null sein kann. Der Offset wird grundsätzlich konegativ<br />
bewertet (-128 .. +127). Die Adreßrechnung erfolgt modulo 64 K (bleibt also immer im Adreßraum<br />
des 68HC11). Zum Beispiel:<br />
CLR 5,X (ergibt als Code: 6F 05)<br />
CLR -5,X (ergibt als Code: 6F FB)<br />
Mikrocomputertechnik<br />
Anmerkungen zur Progam Counter-relativen Adressierung:<br />
Es wird der Stand des Program Counterszum Zeitpunkt der Befehlsausführung verwendet (Dies ist<br />
nicht die Adresse, an der der Befehl beginnt, denn der Program Counter enthält ja immer die Adresse<br />
des nächsten, auszuführenden Befehls. Der Program Counter ist gleich der Adresse des Befehls +<br />
Länge des Befehls). Die Program Counter-relative Adressierung wird oft bei Sprungbefehlen<br />
verwendet. Zweck: lageunabhängige Programme (Ablauf an jeder Position im Speicher).<br />
Befehlsaufbau: offset = Zieladresse - Befehlsadresse - Befehlslänge<br />
Befehlsausführung: Zieladresse = Befehlszählerstand + offset<br />
Implizite Adressierung (Inherent Addressing) 51
Alle Adressierungsarten im Überblick<br />
zeigt die folgende Grafik:<br />
3.3 <strong>Assembler</strong>-Befehlsaufbau<br />
Der <strong>Assembler</strong> ist ein Programm zur Übersetzung mnemotechnischer Befehlsbezeichnungen in die<br />
Maschinensprache. Es erfolgt 1:1-Abbildung der Befehle in die Maschinensprache, d. h. eine<br />
<strong>Assembler</strong>zeile entspricht einem Befehl.<br />
Maschinensprache:<br />
• OP-Code im Maschinencode (binär bzw. sedezimale Abkürzung)<br />
• Adresse als Maschinenadresse (binär bzw. sedezimale Abkürzung)<br />
<strong>Assembler</strong>sprache:<br />
• Festlegung symbolischer Bezeichnungen, die vom <strong>Assembler</strong>-Programm erkannt und<br />
verarbeitet werden.<br />
• OP-Code: mnemonische Bezeichnung (Mnemonics)<br />
• Adresse: symbolische Bezeichnung (Name, Marke (Label))<br />
Allgemeiner Aufbau eines <strong>Assembler</strong>befehls:<br />
Mikrocomputertechnik<br />
Marke OP-Code Operand/Adresse Kommentar<br />
Indizierte Adressierung (Indexed Addressing) 52
Beispiel:<br />
START LDAA DAT1 ; Zähler initialisieren<br />
• Op-Code muß immer vorhanden sein<br />
• Operand/Adresse, falls der Befehl es verlangt<br />
• Marke und Kommentar sind optional<br />
• Trennzeichen zwischen den einzelnen Feldern: Leerzeichen<br />
Marken-Feld: (optional)<br />
Das Feld beginnt in Spalte 1 (also ganz vorne). Die Marke besteht aus Buchstaben, Ziffern<br />
und Sonderzeichen (".", "_", "@") und beginnt mit einem Buchstaben. Die Länge ist auf 31<br />
Zeichen begrenzt. Die Marke kann durch einen ":" abgeschlossen werden, dieser wird vom<br />
<strong>Assembler</strong> ignoriert. Es wird bei manchen <strong>Assembler</strong>n - wie beispielsweise auch in C -<br />
zwischen Groß- und Kleinschreibung unterschieden. Registernamen (A, B, C, D, X, Y, S) sind<br />
reserviert und dürfen nicht verwendet werden. Marken bezeichnen Konstante oder<br />
Speicheradressen.<br />
OP-Code-Feld: (muß vorhanden sein)<br />
Falls keine Marke vorhanden, muß wenigstens ein Leerzeichen davor stehen. Sinnvoller ist es<br />
jedoch, die Opcodes in einer Spalte untereindander zu schreiben. Die Befehle werden durch<br />
Mnemonics aus zwei bis vier Buchstaben dargestellt. Bei einigen Befehlen ist eine<br />
Registerangabe direkt an das Mnemonic anzuhängen (z. B. ADDA, ADDB, ADDD). In<br />
diesem Feld kann auch eine <strong>Assembler</strong>-Direktive (Pseudobefehl) stehen Anweisung für<br />
den <strong>Assembler</strong>, Genaueres später.<br />
Operanden/Adreß-Feld: (abhängig vom OP-Code)<br />
Dieses Feld enthält den Operanden des Befehls, meist eine Adresse oder eine Konstante.<br />
Aufbau hängt von der Adressierungsart ab. Falls eine Adressierungsart mehrere Operanden<br />
verlangt (z. B. Register + Offset) erfolgt Trennung der Operanden mit Komma.<br />
Bei vielen <strong>Assembler</strong>n sind arithmetische und logische Ausdrücke aus Konstanten möglich.<br />
Die Adreßangabe (Offset) kann erfolgen als:<br />
◊ Bezeichner, z. B. MAXIMUM<br />
◊ Dezimalzahl (ohne Kennzeichnung), z. B. 72<br />
◊ Sedezimalzahl (Vorsatz $), z. B. $48<br />
◊ Dualzahl (Vorsatz %), z. B. %01001000<br />
◊ ASCII-Zeichen(-folge), z. B. 'Hallo' oder "Hallo"<br />
◊ als Offset vom "Location Counter" (Vorsatz *), z. B. *+5<br />
Im Operandenfeld kann auch mit den vier Grundrechenarten (+ - * /) und Klammern<br />
gearbeitet werden. Beachten Sie, daß die Ausdrücke zur Assemblierungszeit ausgewertet<br />
werden - nicht zur Laufzeit des Programms! Es sollte sich also immer um "konstante"<br />
Ausdrücke handeln, z. B.<br />
BOTTOM EQU TOP + 10<br />
Kommentar-Feld: (optional)<br />
Das Kommentarfeld wird durch den Strichpunkt oder zwei Schrägstriche eingeleitet. Es<br />
enthält beliebige Zeichenfolgen und wird vom <strong>Assembler</strong> ignoriert.<br />
Zusätzlich sind auch reine Kommentarzeilen möglich, die mit einem "*" in Spalte 1 beginnen.<br />
Der <strong>Assembler</strong> hat zwei Durchläufe:<br />
Beispiel:<br />
Mikrocomputertechnik<br />
1. Durchlauf (pass one): Syntaxprüfung und Aufbau des Adreßbuchs.<br />
2. Durchlauf (pass two): Vollständigkeitsprüfung und Aufbau des Zielprogramms.<br />
3.3 <strong>Assembler</strong>-Befehlsaufbau 53
1. Quellcode<br />
Die Felder für Adresse und Code sind hier noch leer, sie werden vom <strong>Assembler</strong> gefüllt. Es gibt zwei<br />
Pseudobefehle, die weiter unten genauer behandelt werden: ORG legt die Startadresse des erzeugten<br />
Codes fest und END beendet den Quellcode.<br />
Adresse Inhalt Marke Befehl Operand Kommentar<br />
ORG $8000 In den Speicher ab $8000<br />
MAIN BRA MARKE relativer Vorwärtssprung<br />
JMP MARKE absoluter Vorwärtssprung<br />
BRA MAIN relativer Rückwärtssprung<br />
MARKE JMP MAIN absoluter Rückwärtssprung<br />
END<br />
2. Erster <strong>Assembler</strong>lauf: Adresspegel und Code eintragen<br />
Im ersten Durchlauf werden die Befehle übersetzt. Damit liegt die Adresse eines jeden Befehls fest<br />
(weil die Länge eines Befehls ja bekannt ist). Jedoch können die Sprungadressen noch nicht<br />
eingetragen werden, weil bei Vorwärtssprüngen diese beim Übersetzen des jeweiligen Befehls noch<br />
nicht bekannt sind.<br />
Adresse Inhalt Marke Befehl Operand Kommentar<br />
ORG $8000 In den Speicher ab $8000<br />
8000 20 ?? MAIN BRA MARKE relativer Vorwärtssprung<br />
8002 7E ?? ?? JMP MARKE absoluter Vorwärtssprung<br />
8005 20 ?? BRA MAIN relativer Rückwärtssprung<br />
8007 7E ?? ?? MARKE JMP MAIN absoluter Rückwärtssprung<br />
END<br />
Mikrocomputertechnik<br />
3. Zweiter <strong>Assembler</strong>lauf: Adressen absättigen<br />
Beim ersten Durchlauf hat der <strong>Assembler</strong> parallel zur Übersetzung noch eine Symboltabelle angelegt,<br />
welche die Zuordnung zwischen Marke (Name) und Adresse enthält. Nun können mit Hilfe dieser<br />
Tabelle im zweiten Durchlauf die Adressen eingetragen werden.<br />
Adresse Inhalt Marke Befehl Operand Kommentar<br />
ORG $8000 In den Speicher ab $8000<br />
8000 20 05 MAIN BRA MARKE relativer Vorwärtssprung<br />
8002 7E 80 07 JMP MARKE absoluter Vorwärtssprung<br />
8005 20 F9 BRA MAIN relativer Rückwärtssprung<br />
8007 7E 80 00 MARKE JMP MAIN absoluter Rückwärtssprung<br />
END<br />
Die Symboltabelle nimm neben den Sprungadressen auch alle Namen von Konstanten und Variablen<br />
auf. Im zweiten Lauf werden dann auch diese Namen durch die ermittelten Werte ersetzt.<br />
1. Quellcode 54
3.4 Pseudobefehle (<strong>Assembler</strong>-<strong>Direktiven</strong>)<br />
Pseudobefehle erzeugen keine Maschinenbefehle sondern<br />
• erzeugen Konstanten und Variablen (bytes, words, longwords, strings)<br />
• beeinflussen den Adresspegel<br />
• führen zu Einträgen in der Symboltabelle<br />
• steuern den Übersetzungsvorgang<br />
Der <strong>Assembler</strong> führt einen Zähler, der Auskunft über den aktuellen Adreßpegel gibt. Dieser 'Location<br />
Counter' dient beispielsweise zum Berechnen von Sprungadressen. Er entspricht im Prinzip dem<br />
'Program Counter' im realen Prozessor. Die Pseudobefehle werden im OP-Code-Feld einer<br />
<strong>Assembler</strong>zeile angegeben. Unser <strong>Assembler</strong> kennt folgende <strong>Direktiven</strong>:<br />
ORG Origin<br />
Der Location Counter wird auf die im Operandenfeld angegebene Adresse<br />
gesetzt. Er legt damit die Adresse fest, an der der Code später im Speicher des<br />
Controllers abgelegt wird, z. B.:<br />
ORG $8000<br />
EQU Equate<br />
Definition eines Namens (Konstante, Marke). Der im Operandenfeld<br />
angegebene Wert wird dem im Markenfeld angegebenen Namen gleichgesetzt,<br />
z. B.:<br />
ETX EQU 3<br />
CR EQU $D<br />
LF EQU $A<br />
PUFL EQU $100<br />
DC.B Define Constant Byte<br />
Reservierung von Speicherplatz und Belegung mit den im Operandenfeld<br />
angegebenen konstanten Byte-Werten. Mehrere Operanden durch Komma<br />
trennen! Z. B.:<br />
TAB DC.B $0D,$0A,$03<br />
Neben einfachen Konstanten sind in (einfache oder doppelte) Hochkomma<br />
eingeschlossene Zeichenketten möglich. Die Hochkommas gehören dabei<br />
nicht zur Zeichenkette. In den Zeichenketten sind folgende Sonderzeichen<br />
erlaubt:<br />
Z. B.:<br />
• \a Bell ($07)<br />
• \f Formfeed ($0C)<br />
• \n Newline ($0A)<br />
• \r Carriage Return ($0D)<br />
• \t Tabulator ($09)<br />
• \\ \<br />
TEXT DC.B "Hello World!\n\r"<br />
Mikrocomputertechnik<br />
Bei manchen <strong>Assembler</strong>n wird anstelle von DC.B das Kürzel FCB (Form<br />
Constant Byte) verwendet (bei unserem geht beides).<br />
3.4 Pseudobefehle (<strong>Assembler</strong>-<strong>Direktiven</strong>) 55
DC.W Define Constant Word<br />
Reservierung von Speicherplatz und Belegung mit den im Operandenfeld<br />
angegebenen konstanten 16-Bit-Werten. Mehrere Operanden durch Komma<br />
trennen, z. B.:<br />
ATAB DC.W $FF30,$FF45,$FFA0<br />
Bei manchen <strong>Assembler</strong>n (auch unserem) wird anstelle von DC.W das Kürzel<br />
FDB (Form Double Byte) verwendet.<br />
DC.L Define Constant Longword<br />
Reservierung von Speicherplatz und Belegung mit den im Operandenfeld<br />
angegebenen konstanten 32-Bit-Werten. Mehrere Operanden durch Komma<br />
trennen, z. B.:<br />
DS.B<br />
DS.W<br />
DS.L<br />
XTAB DC.L $FF30FF45,$F000FFA0<br />
Define Storage Bytes/Words/Longwords<br />
Reservieren von Speicherbytes, Speicherworten (16 Bit) oder Langworten (32<br />
Bit) ohne Vorbelegung. Der Operand gibt die Anzahl der zu reservierenden<br />
Elemente (Bytes, Worte oder Langworte) an, z. B.:<br />
PUFFER DS.B 100<br />
ADRTAB DS.W 23<br />
Der Reservierungsvorgang hat eher informatorischen Charakter. Es findet<br />
seitens des <strong>Assembler</strong>s keinerlei Adress- oder Bereichsüberprüfung statt! Bei<br />
manchen <strong>Assembler</strong> wird stattdessen nur eine Reservierung in Bytes mit dem<br />
Befehl RMB (Reserve Memory Byte) vorgenommen.<br />
INCLUDE Einfügen einer Quelldatei an der entsprechenden Stelle. Der Dateiname wird<br />
entweder in < ... > (voreingestelltes Include-Verzeichnis) oder " ... "<br />
(beliebiger Dateipfad) eingeschlossen, z. B.:<br />
INCLUDE "definitionen.a"<br />
INCLUDE <br />
Mikrocomputertechnik<br />
NOLIST Unterdrücken der Erzeugung eines Programmlistings bis zum nächsten<br />
LIST-Befehl.<br />
LIST Fortsetzen des Listings nach einem vorher platzierten NOLIST-Befehl.<br />
END Ende des <strong>Assembler</strong>programms. Optionaler Befehl am Programmende. Wird<br />
aus Gründen der Kompatibilität vom <strong>Assembler</strong> akzeptiert, kann aber<br />
weggelassen werden. Text nach diesem Befehl wird vom <strong>Assembler</strong> ignoriert.<br />
Speicher-Organisation<br />
Mit Hilfe der ORG-Anweisung kann der Programmierer verschiedene Programmteile oder<br />
Datenbereiche an beliebigen Stellen im gesamten Adreßraum ablegen. Eine sinnvolle<br />
Speicheraufteilung hat jedoch verschiedene Randbedingungen zu berücksichtigen.<br />
Von der Hardwareseite her sind z.B. RAM- und ROM-Bereiche verschiedener Größe gegeben, denn<br />
Programme sollen häufig im ROM liegen während variable Datenbereiche natürlich nur im RAM sein<br />
können. Eine effiziente Nutzung der physikalisch vorhandenen Speicher verlangt auch die Definition<br />
von lückenlos zusammenhängenden Teilbereichen sowohl von Programmteilen (Hauptprogramm,<br />
Unterprogramme, Interrupt-Service-Routinen) als auch von Datenbereichen (Datenpuffer,<br />
Ausgabetexte, Zustandsvariablen, Stacks, Peripherie-Baustein-Register etc).<br />
Speicher-Organisation 56
Als Grundregel gilt: Je eine ORG-Anweisung für den Daten- und den Programmbereich genügt, denn<br />
dann sind beide Bereiche jeweils zusammenhängend. Es ist nicht nötig, z.B. für jedes Unterprogramm<br />
oder jede Interrupt-Service-Routine ein neues ORG zu setzen. Jede weitere ORG-Anweisung steigert<br />
nur die Gefahr von Fehlern (z.B. überlappende Bereiche) bzw. Speicherverschwendung durch<br />
unnötige Lücken. Bedenken Sie, dass Sie vom <strong>Assembler</strong> nicht gewarnt werden, wenn sich<br />
Speicherbereiche überlappen oder Sie Bereiche wählen, an denen kein realer Speicher vorhanden ist.<br />
Ganz auf die ORG-Anweisung zu verzichten ist zwar möglich (Programm- und Datenbereich hängen<br />
dann zusammen und beginnen bei Null), aber nicht zu empfehlen. Durch kommentierte<br />
ORG-Anweisungen zeigt man, das diese wohlüberlegt gewählt wurden; also besser ORG $0000<br />
angeben als einfach weglassen.<br />
Anmerkung: Da bei einem Mikrocontroller ja zwischen ROM- bzw. EEPROM-Speicher und RAM<br />
unterschieden werden muß, ist auch die Reservierung von Speicher von dieser Unterscheidung<br />
betroffen. Mit DC.B, DC.W oder DC.L vordefinierte Konstante liegen im ROM/EEPROM-Bereich,<br />
mit DS.B, DS.W oder DS.L reservierter Speicher im RAM-Bereich.<br />
Merkregeln für die Verwendung von EQU, DS.B/DS.W/DS.L und DC.B/DC.W/DC.L<br />
• EQU nur für Konstanten, die mit symbolischen Namen versehen werden sollen. Sollen solche<br />
Werte später doch geändert werden, so muss das Quellprogramm geändert und neu<br />
assembliert werden.<br />
• DS.B/DS.W/DS.L nur zum Bereitstellen von RAM-Speicherplatz für Daten, die vom<br />
Programm erst dorthin geschrieben werden, z.B. eingelesene Messwerte, etc.<br />
• DC.B/DC.W/DC.L zum Vorbelegen von Datenbereichen im ROM/EEPROM mit konstanten<br />
Werten, Umrechnungstabellen, Texten etc.<br />
Grundsätzlicher Aufbau eines 68HC11-<strong>Assembler</strong>programms<br />
1. Konstantendefinitionen<br />
Hier werden alle Definitionen für Werte und Adressen (EQU-Anweisung) vorgenommen. Diese<br />
"Namensdefinitionen" belegen keinen Speicherplatz, sondern dienen nur der besseren Lesbarkeit und<br />
Wartbarkeit des Programms. Zum Beispiel:<br />
STACK EQU $7FFF Stackbereich<br />
PROG EQU $8000 Programmbereich<br />
DATA EQU $2000 Datenbereich (auch Adr. 0 möglich)<br />
RVECT EQU $FFFE Reset-Vektor<br />
SCCR1 EQU $102C<br />
SCCR2 EQU $102D<br />
CR EQU 13 Carriage-Return-Zeichen<br />
LF EQU 10 Linefeed-Zeichen<br />
ETX EQU 3 Textende<br />
MAXDATA EQU 100<br />
Wichtig sind die ersten fünf Zeilen, die bei keinem Programm fehlen dürfen. Sie legen die<br />
Adressbereiche für RAM und EEPROM fest und definieren die Adressen der beiden Vektoren, die<br />
immer gesetzt werden müssen.<br />
2. Variablendefinitionen<br />
Mikrocomputertechnik<br />
Hier werden alle Daten definiert, die Speicherplatz belegen. Es ist ratsam, den Datenbereich durch<br />
eine eigene ORG-Anweisung einzuleiten, um die Daten an definierter Stelle im Speicher abzulegen.<br />
Bei einem Steuerungsrechner muß auf jeden Fall in Datenbereich (RAM) und Programmbereich<br />
Speicher-Organisation 57
(PROM) unterschieden werden. Man kann die Variablen auch nach dem Programmcode ablegen. Zum<br />
Beispiel:<br />
ORG DATA Datenbereich z.B. ab Adresse $2000<br />
COUNT DC.B 0 Wert mit Null vorbelegen<br />
PUFFER DS.B 80 80 Byte Pufferbereich reservieren<br />
TEXT DC.B 'Hello World' Text, abgeschlossen durch Zeilen-<br />
DC.B CR, LF, ETX wechsel und Nullbyte<br />
3. Programmbereich<br />
Nun folgt das eigentliche Programm. Es wird immer mit einer ORG-Anweisung an eine definierte<br />
Adresse gelegt. Diese Adresse ist auch Startadresse des Programms.<br />
Achtung: Der <strong>Assembler</strong> kümmert sich nicht um die Adreßlage des Programms, auch Überlappungen<br />
mit dem Datenbereich werden nicht als Fehler gemeldet aufpassen.<br />
Es gibt zwei Möglichkeiten der Anordnung von Haupt- und Unterprogrammen. Üblich ist es, das<br />
Hauptprogramm am Anfang zu postieren und dann die Unterprogramme folgen zu lassen. Wer lieber<br />
die UP zuerst stehen hat, muß das HP mit einer Marke versehen (z. B. "MAIN") und nach der<br />
ORG-Anweisung als erste Anweisung einen Sprung zum HP eintragen, z. B.:<br />
....... Definitionen (1. und 2.)<br />
ORG PROG Programmbereich, z. B. $8000<br />
JMP MAIN<br />
....... Unterprogramme<br />
Mikrocomputertechnik<br />
MAIN LDS #STACK Stackpointer setzen, sonst geht nichts<br />
.<br />
.<br />
.<br />
.<br />
ORG RVECT<br />
DC.W MAIN Reset-Vektor auf Programmanfang setzen<br />
END<br />
Häufiger ist jedoch die Variante mit vorangestelltem Hauptprogramm anzutreffen. Beim folgenden<br />
Rumpfprogramm sind auch noch einige weitere Besonderheiten berücksichtigt:<br />
stak equ $7FFF ; Stackbereich ab $7FFF (RAM, abwaerts)<br />
prog equ $8000 ; Programmbereich ab $8000 (EEPROM)<br />
data equ $2000 ; Datenbereich ab $2000 (RAM)<br />
rvec equ $FFFE ; Reset-Vektor<br />
. ; ggf. weitere Vektoren<br />
org data ; Beginn Datenbereich<br />
. ; Variablen-Definitionen<br />
.<br />
org prog ; Beginn Programmbereich<br />
main lds #stak ; Stackpointer setzen<br />
.<br />
. ; alle Initialisierungen<br />
.<br />
loop . ; Befehle des Programms<br />
.<br />
.<br />
jmp loop<br />
Grundsätzlicher Aufbau eines 68HC11-<strong>Assembler</strong>programms 58
. ; ggf. fixe Tabellen dahinter<br />
.<br />
. ; ggf. Setzen der Interrupt-Vektoren<br />
. ; (Reihenfolge der Adressen beachten!)<br />
org rvec ; Setzen des Reset-Vektors<br />
fdb main<br />
end<br />
Beim Programmieren einer Controller-Anwendung ist u. a. auch zu berücksichtigen, dass<br />
RAM-Inhalte nach dem Ausschalten und späteren Wiedereinschalten verloren gehen. Das bedeutet,<br />
dass feste Werte wie Ausgabestrings, Anfangswerte von Variablen usw. nicht im RAM<br />
(Datenspeicher), sondern im EEPROM (Programmspeicher) abgelegt werden müssen. Das hat aber<br />
Konsequenzen:<br />
• Daten im Programmspeicher können nicht geändert werden (EEPROM!)<br />
• Braucht man Anfangswerte für Variablen, müssen diese im Programmspeicher abgelegt und<br />
in der Initialisierungsphase in Variablen im RAM kopiert werden.<br />
Hinweis: Die im Datenbereich abgelegten konstanten Werte (mittels DC.B etc.) werden nur einmal<br />
beim Herunterladen des Programms ins Zielsystem im Speicher eingetragen, danach nie wieder.<br />
Schon das Drücken der Reset-Taste kann zu "seltsamen" Verhaltenformen des Programms führen.<br />
3.5 CPU-Befehle<br />
Bei der folgenden Beschreibung der Befehle werden einige Standardnamen verwendet:<br />
• Mit A, B und D werden die Akkumulatoren bezeichnet<br />
• Mit X, Y und S werden die Indexregister und der Stackpointer bezeichnet<br />
• "adr." bezeichnet den Inhalt eines beliebigen Speicherbytes oder eine Konstante<br />
• (A) oder (adr.) bezeichnet den Inhalt von Akku A bzw. den Inhalt der Speicheradresse "adr.".<br />
Transport-Befehle<br />
Ladebefehle:<br />
Load Register from Memory or Constant<br />
Mikrocomputertechnik<br />
• anwendbar auf A, B (8 Bit) oder D, S, X, Y (16 Bit)<br />
3.5 CPU-Befehle 59
• bei 8-Bit-Register:<br />
LDAA adr.<br />
LDAB adr.<br />
• bei 16-Bit-Register: LDD adr<br />
LDS adr<br />
LDX adr<br />
LDY adr<br />
in (adr) steht das MSB in (adr+1) das LSB<br />
• Beeinflusst: N, V, Z<br />
• Flags<br />
CLR Clear Akkumulator: 0 Akkumulator-Register<br />
• CLRA<br />
CLRB<br />
• schneller als LDAA #0<br />
Speicherbefehle:<br />
Store Register into Memory (8 Bit/16 Bit)<br />
• STAA, STAB (8 Bit): (Reg) adr.<br />
• STD, STS, STX, STY (16 Bit): (Reg) adr., adr+1<br />
Clear Memory<br />
• CLR adr.<br />
Transport zwischen Registern:<br />
Kopie des Inhalts eines Registers in ein anderes (transfer)<br />
• TAB (A) B<br />
• TAP (A) Statusregister<br />
• TBA (B) A<br />
• TPA (Statusregister) A<br />
• TSX (S) X<br />
• TSY (S) Y<br />
Mikrocomputertechnik<br />
Transport-Befehle 60
• TXS (X) S<br />
• TYS (Y) S<br />
Bit X im Statusregister kann mittels TAP nicht gesetzt werden.<br />
Austausch von Registerinhalten (exchange)<br />
• XGDX D X<br />
• XGDY D Y<br />
• Zweck: Adreßrechnung in D, Adressierung dann über X oder Y.<br />
Beispiel: Tausch A B<br />
Benötigt wird eine Hilfsvariable im Daten-Speicherbereich<br />
STAA HILF<br />
TBA<br />
LDAB HILF<br />
Beispiel: Tausch X Y<br />
* Beispielbelegung X Y D<br />
* 1 2 3<br />
XGDX 3 2 1<br />
XGDY 3 1 2<br />
XGDX 2 1 3<br />
Beispiel: Unterprogramm zum Kopieren eines Speicherbereichs (nullterminierte Zeichenkette). Die<br />
Adresse des Quellstrings steht im X-Register, die Adresse des Zielbereichs im Y-Register:<br />
strcpy ldaa 0,x ; lade ein Zeichen aus der Quelle<br />
staa 0,y ; ablegen im Zielbereich<br />
beq strc_e ; wenn Nullbyte, dann fertig<br />
inx ; beide Zeiger inkementieren<br />
iny<br />
bra strcpy ; und naechstes Zeichen<br />
strc_e rts<br />
Soll ein beliebiger Speicherbereich kopiert werden, müsste noch ein Blocklängenzähler<br />
implementiert werden.<br />
Arithmetische Befehle<br />
Dies sind Befehle, die arithmetische Operationen bewirken. Im allgemeinen steht ein Operand in<br />
einem Akku und das Ergebnis wieder im gleichen Akku.<br />
Additionsbefehle:<br />
Addieren (add)<br />
Mikrocomputertechnik<br />
Arithmetische Befehle 61
• ADDA adr. (A) + (adr.) A<br />
• ADDB adr. (B) + (adr.) B<br />
• ADDD adr. (D) + (adr., adr+1) D (16-Bit-Addition)<br />
• ABA (A) + (B) A<br />
• ABX (X) + (B) X (Adreßrechnung), B als vorzeichenlose Zahl aufgefaßt<br />
• ABY (Y) + (B) Y (Adreßrechnung), B als vorzeichenlose Zahl aufgefaßt<br />
Addieren mit Übertrag (add with carry)<br />
• ADCA adr. (A) + (adr.) + C A<br />
• ADCB adr. (B) + (adr.) + C B<br />
• Anwendung: Mehrbyte-Addition<br />
Beispiel: Addition zweier 4-Byte-Zahlen<br />
1. Operand: Adresse $41 - $44<br />
2. Operand: Adresse $45 - $48<br />
Ergebnis: Adresse $49 - $4C<br />
LDAA $44 Niederwertiges Byte addieren<br />
ADDA $48<br />
STAA $4C<br />
LDAA $43 Zweites Byte addieren<br />
ADCA $47<br />
STAA $4B<br />
LDAA $42 Drittes Byte addieren<br />
ADCA $46<br />
STAA $4A<br />
LDAA $41 Höchstwertiges Byte addieren<br />
ADCA $45<br />
STAA $49<br />
Erhöhen (increment)<br />
Mikrocomputertechnik<br />
• Sonderfall: Addition von 1<br />
• C-Flag wird nicht beeinflusst (Addition mod 256)<br />
• Für z. B. Schleifenzähler<br />
• INCA (A) + 1 A<br />
• INCB (B) + 1 B<br />
• INS (S) + 1 S (kein Flag beeinflußt)<br />
• INX (X) + 1 X (nur Z-Flag beeinflußt)<br />
• INY (Y) + 1 Y (nur Z-Flag beeinflußt)<br />
Arithmetische Befehle 62
• INC adr. (adr.) + 1 adr. (Increment eines Speicherbytes)<br />
Subtraktionsbefehle:<br />
Subtraktion (subtract) = Addition des Zweierkomplements<br />
• SUBA adr. (A) - (adr.) A<br />
• SUBB adr. (B) - (adr.) B<br />
• SUBD: 16-Bit-Subtraktion, Operand in zwei aufeinanderfolgenden Speicherzellen<br />
Subtraktion mit Übertrag (subtract with carry)<br />
• SBCA adr. (A) - (adr.) + C A<br />
• SBCB adr. (B) - (adr.) + C B<br />
• Anwendung: Mehrbyte-Subtraktion<br />
Erniedrigen (decrement)<br />
• Sonderfall: Subtraktion von 1<br />
• C-Flag wird nicht beeinflusst (Subtraktion mod 256)<br />
• Für z. B. Schleifenzähler<br />
• DECA (A) - 1 A<br />
• DECB (B) - 1 B<br />
• DES (S) - 1 S (kein Flag beeinflußt)<br />
• DEX (X) - 1 X (nur Z-Flag beeinflußt)<br />
• DEY (Y) - 1 Y (nur Z-Flag beeinflußt)<br />
• DEC adr. (adr.) - 1 adr. (Decrement eines Speicherbytes)<br />
Vorzeichenwechsel (negate)<br />
• Sonderfall: 0 - (Akku), Bildung des Zweierkomplements<br />
• NEGA A komplementieren<br />
• NEGB B komplementieren<br />
• NEG adr. adr. komplementieren<br />
Multiplikation und Division:<br />
Multiplizieren (multiply)<br />
• MUL Vorzeichenlose Multiplikation (A) * (B) D<br />
• Z-Flag = 1, wenn Ergebnis = 0 ist, sonst Z = 0<br />
• C-Flag = Bit 7 von B<br />
Dividieren (divide)<br />
Beispiele:<br />
• IDIV Vorzeichenlose Division, ganzzahliger Anteil (integer divide)<br />
für D > X: (D) / (X) X, Rest in D<br />
• FDIV Vorzeichenlose Division, Quotient echter Bruch (fractional divide)<br />
für D < X: (D) / (X) X, Rest in D<br />
IDIV: FDIV:<br />
Mikrocomputertechnik<br />
$8421 : $0004 = $2108 R $0001 $1000 : $2000 = $.8000 R $0000<br />
Arithmetische Befehle 63
$0001 : $FFFF = $0000 R $0001 $0001 : $FFFF = $.0001 R $0001<br />
$FFFF : $0001 = $FFFF R $0000 $FFFF : $0001 = unzulässig, V=1<br />
Weitere arithmetische Befehle:<br />
DAA Decimal Adjust A<br />
• Dezimalkorrektur von Akku A für BCD-Arithmetik<br />
• Jedes Halbbyte (Nibble) entspr. 1 Dezimalziffer<br />
• Anwendung nach Addition im Akku<br />
• Korrekturaddition, wenn Pseudotetrade auftritt<br />
Akku enthält zwei BCD-Ziffern<br />
• Nach DAA enthält C-Flag den Übertrag in die nächste Stelle<br />
• NUR (!) nach dem Befehlen ABA, ADDA und ADCA wirksam (nicht beim INC-Befehl)<br />
• Bei der Subtraktion gilt Zehnerkomplement. -1 wird also nicht als $FF, sondern als $99<br />
dargestellt (-2 $98, -3 $97, usw.).<br />
Beispiel: Addition zweier 4-stelligen BCD-Zahlen<br />
1. Zahl: Adr. $31-$32<br />
2. Zahl: Adr. $33-$34<br />
Ergebnis: Adr. $35-$36<br />
LDAA $32 niederwertige 2 Ziffern<br />
ADDA $34 binär addieren<br />
DAA BCD-Justage<br />
STAA $36<br />
LDAA $31 höherwertige 2 Ziffern<br />
ADCA $34 binär addieren mit Carry!<br />
DAA BCD-Justage<br />
STAA $35<br />
Logische Befehle<br />
Bei logischen Befehlen erfolgt die bitweise logische Verknüpfung eines Akku-Inhalts mit einem<br />
Operanden (Speicherinhalt oder Konstante). Logische Befehle spielen vor allem beim Zugriff auf<br />
E/A-Komponenten eine Rolle, weil bei E/A-Operationen häufig einzelne Bits eines Datenworts<br />
gesetzt, gelöscht oder invertiert werden müssen.<br />
Und-Verknüpfung (and)<br />
Beispiele:<br />
Mikrocomputertechnik<br />
• ANDA adr. (A) and (adr.) A<br />
• ANDB adr. (B) and (adr.) B<br />
• Anwendung: Löschen einzelner Bits in einem Wort<br />
Arithmetische Befehle 64
1) Löschen der 4 höherwertigen Bits von Akku A<br />
ANDA #$0F<br />
2) Rücksetzen des 5. Bits<br />
ANDA #%11101111<br />
3) Rücksetzen des 4. Bits einer Variablen namens FLAG<br />
LDAA FLAG<br />
ANDA #%11110111<br />
STAA FLAG<br />
Oder-Verknüpfung (or)<br />
Beispiele:<br />
• ORAA adr. (A) or (adr.) A<br />
• ORAB adr. (B) or (adr.) B<br />
• Anwendung: Setzen einzelner Bits in einem Wort<br />
1) Setzen der 4 höherwertigen Bits von Akku A<br />
ORA #$F0<br />
2) Setzen des 5. Bits<br />
ORAA #%00010000<br />
3) Setzen des 4. Bits einer Variablen namens FLAG<br />
LDAA FLAG<br />
ORAA #%00001000<br />
STAA FLAG<br />
Exklusiv Oder (exor)<br />
Beispiele:<br />
• EORA adr. (A) exor (adr.) A<br />
• EORB adr. (B) exor (adr.) B<br />
• Anwendung: Invertieren einzelner Bits<br />
Maskenbit=1: Bit wird invertiert<br />
Maskenbit=0: Bit unverändert<br />
1) Invertieren der 4 höherwertigen Bits von Akku A<br />
EORA #%11110000<br />
2) Invertieren der Bits 0 und 3 einer Variablen namens FLAG<br />
LDAA FLAG<br />
EORA #%00000101<br />
STAA FLAG<br />
Bit prüfen (bit test)<br />
Mikrocomputertechnik<br />
Diese Befehle haben Bedeutung in Zusammenhang mit den weiter unten behandelten<br />
Sprungbefehlen. Sie erlauben den Test eines Akkumulators auf Null bzw. Vorzeichen, ohne dessen<br />
Inhalt zu ändern.<br />
Logische Befehle 65
• BITA adr. (A) and (adr.) Nur Flags neu setzen, A bleibt unverändert<br />
• BITB adr. (B) and (adr.) Nur Flags neu setzen, B bleibt unverändert<br />
Invertieren (complement)<br />
1-Komplement Invertieren aller Bits.<br />
Auch auf Speicherbytes anwendbar.<br />
• COMA adr. not (A) A<br />
• COMB adr. not (B) B<br />
• COM adr. not (adr.) adr.<br />
Beispiel: Verwendung des Speicher-Bytes $41 als Software-Flip-Flop. Zu Beginn des Programms<br />
muß der Inhalt von $41 gelöscht werden!<br />
COM $41 Inhalt wird $FF<br />
.<br />
.<br />
COM $41 Inhalt wird wieder 0<br />
.<br />
.<br />
usw.<br />
Schiebe- und Rotationsbefehle<br />
Die Schiebebefehle bewirken das Verschieben eines Akku- oder Speicherinhalts um eine Stelle<br />
nach rechts oder links. Bei den Rotationsbefehlen erfolgt die Ringverschiebung eines Akku- oder<br />
Speicherinhalts unter Einbeziehung des C-Flags nach links oder rechts. Die Befehle sind auf A, B,<br />
D oder einen Speicherinhalt anwendbar. Die Realisierung auf Speicherinhalt erfolgt durch: Laden in<br />
Rechenregister, Schiebeoperation im Rechenregister, Zurückspeichern des Register-Inhalts).<br />
Logische Verschiebung:<br />
LSRx Logical Shift Right:<br />
von links wird 0 nachgeschoben: 0 MSB<br />
LSB C-Flag<br />
Mikrocomputertechnik<br />
• LSRA Akku A nach rechts schieben<br />
Logische Befehle 66
• LSRB Akku B nach rechts schieben<br />
• LSRD Akku D nach rechts schieben<br />
• LSR adr. Speicherwort adr. nach rechts schieben<br />
LSLx Logical Shift Left:<br />
von rechts wird 0 nachgeschoben: 0 LSB<br />
MSB C-Flag<br />
• LSLA Akku A nach links schieben<br />
• LSLB Akku B nach links schieben<br />
• LSLD Akku D nach links schieben<br />
• LSL adr. Speicherwort adr. nach links schieben<br />
Arithmetische Verschiebung:<br />
ASRx Arithmetic Shift Right:<br />
Entspricht Division durch 2<br />
MSB MSB (Vorzeichen bleibt erhalten), LSB C-Flag<br />
• ASRA Akku A nach rechts schieben<br />
• ASRB Akku B nach rechts schieben<br />
• ASR adr. Speicherwort adr. nach rechts schieben<br />
ASLx Arithmetic Shift Left:<br />
von rechts wird 0 nachgeschoben: 0 LSB<br />
MSB C-Flag<br />
Identisch mit LSL!<br />
• ASLA Akku A nach links schieben<br />
• ASLB Akku B nach links schieben<br />
• ASLD Akku D nach links schieben<br />
• ASL adr. Speicherwort adr. nach links schieben<br />
Rotationsbefehle:<br />
Hin- und Herschieben des Akku- oder Speicherinhalts ohne ihn zu zerstören (anschließend Test des<br />
C-Flags). Vorzeichenlose duale Multiplikation und Division.<br />
ROLx Rotate Left<br />
C-Flag LSB<br />
MSB C-Flag<br />
• ROLA Akku A linksrotieren<br />
• ROLB Akku B linksrotieren<br />
• ROL adr. Speicherwort adr. linksrotieren<br />
RORx Rotate Right<br />
C-Flag MSB<br />
LSB C-Flag<br />
Mikrocomputertechnik<br />
• RORA Akku A rechtsrotieren<br />
• RORB Akku B rechtsrotieren<br />
• ROR adr. Speicherwort adr. rechtsrotieren<br />
Schiebe- und Rotationsbefehle 67
Beispiele:<br />
1) Multiplikation von Akku A mit 10: (A) * 10 A<br />
ASLA (A)*2 A<br />
STAA $40 Erg. zwischenspeichern<br />
ASLA (A)*4 A<br />
ASLA (A)*8 A<br />
ADDA $40 (A)*8 + (A)*2 A<br />
2) Akku D nach links schieben:<br />
A C B<br />
ASLB MSB von B --> Carry +----------+__+-+__+----------+<br />
ROLA Carry --> LSB von A +----------+ +-+ +----------+<br />
3) Zerlegung eines Bytes in zwei Halbbytes:<br />
Die Halbbytes sind in getrennten Speicherzellen als niederwertiges Halbbyte<br />
zu speichern (höherwertiges Halbbyte ist auf 0 zu setzen).<br />
$70: zu zerlegendes Byte<br />
$71: höherwertiges Nibble<br />
$72: niederwetiges Nibble<br />
LDAA $70 Byte holen (binär: xxxxyyyy)<br />
ANDA #$0F niederwertiges Nibble maskieren<br />
STAA $72 speichern (binär: 0000yyyy)<br />
LDAA $70 Byte nochmal holen<br />
LSRA 4 x nach rechts schieben (0xxxxyyy)<br />
LSRA (00xxxxyy)<br />
LSRA (000xxxxy)<br />
LSRA (0000xxxx)<br />
STAA $71 höherwertiges Nibble speichern<br />
Test- und Statusregisterbefehle<br />
Sie dienen der Überprüfung von Datenwerten auf bestimmte Eigenschaften. Die Überprüfung<br />
erfolgt durch arithmetische und logische Operationen. Als Ergebnis werden bestimmte Flags des<br />
CC-Register beeinflusst, der Inhalt der Akkus bleibt unverändert. Die Flags können zur Steuerung<br />
bestimmter Sprungbefehle verwendet werden Programmfortsetzung abhängig von<br />
Dateneigenschaften Steuerbefehle. Beispiele bei den Sprungbefehlen.<br />
Test<br />
Die Befehle sind anwendbar auf A, B und den Speicher. Test auf Null und negativ.<br />
• Z-Flag = 1, wenn Akku- oder Speicherinhalt = 0 ist.<br />
• N-Flag = MSB von Akku- oder Speicherinhalt<br />
• TSTA Akku A = 0 ?<br />
• TSTB Akku B = 0 ?<br />
• TST adr. (adr.) = 0 ?<br />
Vergleich (compare)<br />
Mikrocomputertechnik<br />
("Gedachte Subtraktion")<br />
Die Befehle sind anwendbar auf A, B, D, X und Y. Es wird jeweils ein Registerinhalt mit einem<br />
Speicherinhalt oder einer Konstanten verglichen (Ausnahme: CBA). Der Vergleich erfolgt durch<br />
eine Subtraktion ohne Anfallen des Ergebnisses.<br />
• Z-Flag = 1, wenn beide Operanden gleich sind<br />
• N-Flag = 1, wenn (Reg) < Operand (konegative Zahl) und kein arith. Überlauf<br />
• C-Flag = 1, wenn (Reg) < Operand (natürliche Zahl)<br />
Test- und Statusregisterbefehle 68
• V-Flag = 1, wenn arithm. Überlauf auftrat<br />
• CMPA #0 und TSTA sind von der Funktion her identisch<br />
Der Vergleich auf Null und "negativ" ermöglicht alle Vergleiche von Werten. Mathematisch<br />
gesehen werden die links stehenden Ungleichungen in die rechts stehenden umgesetzt:<br />
X 1 = X 2 X 1 - X 2 = 0<br />
X 1 < X 2 X 1 - X 2 < 0<br />
X 1 > X 2 X 1 - X 2 > 0<br />
Durch bedingte Sprungbefehle kann dann abhängig vom Ergebnis im Programm verzweigt werden.<br />
Es gibt 8-Bit- und 16-Bit-Vergleiche (je nach Wortbreite des Registers).<br />
• CMPA adr. (A) - (adr.) Flags<br />
• CMPB adr. (B) - (adr.) Flags<br />
• CPD adr. (D) - (adr., adr.+1) Flags<br />
• CPX adr. (X) - (adr., adr.+1) Flags<br />
• CPY adr. (Y) - (adr., adr.+1) Flags<br />
• CBA (A) - (B) Flags<br />
Bitorientierte Befehle<br />
Bitbefehle Statusregister<br />
Diese Befehle erlauben das komfortable Setzen und Rücksetzen einiger Bits des Statusregisters.<br />
clear carry flag X X X X X X X 0<br />
• CLC<br />
clear interrupt flag X X X 0 X X X X<br />
• CLI<br />
clear overflow flag X X X X X X 0 X<br />
• CLV<br />
set carry flag X X X X X X X 1<br />
• SEC<br />
set interrupt flag X X X 1 X X X X<br />
• SEI<br />
set overflow flag X X X X X X 1 X<br />
• SEV<br />
Bitbefehle Speicher<br />
Diese Befehle erlauben das Setzen oder Löschen einzelner Bits in Speicherworten. Als einzige<br />
Befehle haben sie zwei Operanden, die Adresse des zu ändernden Speicherbytes und eine konstante<br />
Maske. Da die Maske immer konstant sein muß, entfällt hier auch das "#"-Zeichen. Für jedes 1-Bit<br />
in der Maske wird das entsprechende Speicherbit gesetzt (BSET) oder gelöscht (BCLR).<br />
•<br />
BSET adr. mask<br />
Nachbildung:<br />
LDAA #mask<br />
ORAA adr.<br />
STAA adr.<br />
Mikrocomputertechnik<br />
Bitorientierte Befehle 69
•<br />
BCLR adr. mask<br />
Nachbildung:<br />
LDAA #mask<br />
COMA<br />
ANDA adr.<br />
STAA adr.<br />
Beeinflussung des Systemzustands<br />
Dies sind Befehle, welche die Programmausführung anhalten. Sie dienen der Synchronisation des<br />
Programmablaufs mit externen Ereignissen.<br />
Warte auf Interrupt (wait for interrupt)<br />
• WAI<br />
Ablage aller Register auf dem Stack, dann warten auf Interrupt.<br />
Stop<br />
• STOP<br />
Reaktion hängt ab von S-Flag im Statusregister:<br />
• S=1: next instruction (NOP)<br />
• S=0: halt clocks, enter standby mode, wait for XIRQ or IRQ<br />
Freigabe des STOP-Befehls:<br />
XIRQ & X=1: next instruction<br />
XIRQ & X=0: service interrupt<br />
IRQ & I=1: no activity<br />
IRQ & I=0: service interrupt<br />
TPA Statusreg. nach Akku A<br />
ANDA #$7F Freigabe (S-Flag auf 0)<br />
TAP Akku A nach Statusreg.<br />
Für den Fall S=0 und X=1 wird beim Aktivieren des XIRQ-Eingangs der Prozessor nach einem<br />
STOP-Befehl "aufgeweckt" und er macht im Programm ganz normal weiter.<br />
Sprungbefehle<br />
Mikrocomputertechnik<br />
Alle Sprungbefehle verändern den PC-Inhalt Programmausführung wird an anderer Stelle<br />
fortgesetzt. Das Statusregister wird nicht beeinflußt. Einige Befehle speichern Registerinhalte auf<br />
dem Stack oder holen Registerinhalte von dort wieder zurück.<br />
Beeinflussung des Systemzustands 70
Unbedingte Sprungbefehle (jump, branch)<br />
JMP adr. adr. PC<br />
Bei JMP erfolgt die Zielangabe mit vollständiger absoluter Adressierung (extended direct) oder<br />
indizierter Adressierung (mit X oder Y). Es ist ein Sprung im gesamten Adressraum möglich, denn<br />
der Operand ist ein 16-Bit-Wert.<br />
Der Sprungbefehl hat im <strong>Assembler</strong>programm normalerweise eine so genannte Marke als Operand.<br />
Diese Marke steht am Sprungziel, wie Sie da schon eingangs des Kapitels bei der Erklärung der<br />
beiden <strong>Assembler</strong>durchläufe sehen konnten. Der <strong>Assembler</strong> entnimmt die Adresse dieser Marke aus<br />
der Symboltabelle und fügt sie dem JMP-Befehl als Operand hinzu. Der Programmierer kann daher<br />
immer mit symbolischen Adressen arbeiten.<br />
BRA dest.<br />
Mikrocomputertechnik<br />
Hier wird keine absolute Adresse, sondern ein Offset relativ zum Program Counter angegeben (-128<br />
... +127). Hier berechnet der <strong>Assembler</strong> die Distanz zwischen BRA-Befehl und Sprungmarke und<br />
trägt als Offset eine 8-Bit-Zahl in Komplementntdarstellung ein.<br />
Bedingte Sprungbefehle ("Verzeigungsbefehle")<br />
Hier gibt es nur PC-relative Adressierung (branch conditionally). Es gibt acht Paare von zueinander<br />
komplementären Befehlen. Die Unterscheidung erfolgt in der jeweiligen Verzweigungsbedingung.<br />
Als Verzweigungsbedingung dienen (ein oder mehr) Bits des Statusregisters Verzweigung<br />
abhängig vom Ergebnis der vorhergehenden Operation ist die Bedingung erfüllt, erfolgt ein<br />
Sprung; im anderen Fall wird die Programmausführung beim nächsten Befehl fortgesetzt. Der<br />
<strong>Assembler</strong> übernimmt die Offset-Berechnung.<br />
Vergleich von Hochsprache und <strong>Assembler</strong>-Programmierung:<br />
Sprungbefehle 71
Die folgende Tabelle fasst alle bedingten Sprünge zusammen. Die erste Gruppe springt abhängig<br />
vom Wert bestimmter Flags des Condition Code Registers. Weitere Gruppen bilden die<br />
Sprungbefehle, die von arithmetischen Vergleichen abhängen.<br />
Achtung: Die Flags werden nicht nur bei arithmetischen Operationen oder Vergleichen<br />
(Compare-Befehl) gesetzt, sondern bei fast jedem Befehl (z. B. Ladebefehle, logische Operationen).<br />
Befehl Bedeutung Sprungbedingung<br />
BCC dest. carry clear C=0<br />
BCS dest. carry set C=1<br />
BVC dest. overflow clear V=0<br />
BVS dest. overflow set V=1<br />
BNE dest. result not equal<br />
zero<br />
Mikrocomputertechnik<br />
einfach (simple)<br />
Z=0 (BZC)<br />
BEQ dest. result equal zero Z=1 (BZS)<br />
BPL dest. result plus N=0 (BNC)<br />
BMI dest. result minus N=1 (BNS)<br />
natürlich (unsigned)<br />
BHI dest. higher Op1 > Op2<br />
BLS dest. lower or same Op1 = Op2<br />
konegativ (signed)<br />
Sprungbefehle 72
BGT dest. greater than Op1 > Op2<br />
BLE dest. less or equal Op1 = Op2<br />
bitabhängig<br />
BRCLR adr. mask dest springe, wenn die in der Maske mit "1" markierten Bits<br />
alle "0" sind alle Bits des Speicherbytes adr. werden<br />
mit der Maske UND-verknüpft und wenn das Ergebnis<br />
0 ist, wird gesprungen.<br />
BRSET adr. mask dest springe, wenn die in der Maske mit "1" markierten Bits<br />
alle "1" sind alle Bits des Speicherbytes adr. werden<br />
mit der Maske UND-verknüpft und wenn das Ergebnis<br />
gleich der Maske ist, wird gesprungen.<br />
Der Vergleich bei natürlichen Zahlen und konegativen Zahlen kann zu unterschiedlichen<br />
Ergebnissen führen. Betrachten Sie dazu die beiden folgenden Befehle:<br />
LDAA #$F8<br />
CMPA #$12<br />
Beim "unsigned"-Vergleich ist $F8 > $12, der Sprungbefehl BHI würde also ausgeführt. Betrachtet<br />
man die Zahlen jedoch als ganze (konegative) Zahlen, handelt es sich um die Zahl -8 dez. , die<br />
natürlich kleiner als $12 (18 dez. ) ist. Der Befehl BGT würde daher nicht ausgeführt.<br />
Betrachten Sie folgende Beispiele für die Anwendung von Sprungbefehlen, die Berechnen der<br />
Summe über ein Feld von Messwerten:<br />
FLENG EQU 100 ;Symbolische Konstante Feldlaenge vereinbaren<br />
FELD RMB FLENG ; Symbolischer Name und Speicherplatz<br />
; fuer ein Feld von 100 Bytes reservieren<br />
SUMME RMB 1 ; Symbolischer Name und Speicherplatz<br />
; fuer 1 Byte reservieren<br />
; das Indexregister X dient als Pointer!<br />
LDX #FELD ; symbolische Adresse des Feldanfangs ' X<br />
LDAB #FLENG ; Zaehler für die Feldlaenge initialisieren<br />
CLRA ; Summe in Akku A bilden, -> erst loeschen<br />
LOOP ADDA 0,X ; Feldelemente indiziert adressieren<br />
DECB ; Zaehler um eins vermindern<br />
; Feld abgearbeitet (bei 0 angekommen)?<br />
BEQ FERTIG ; wenn ja (Zaehler = 0): fertig<br />
INX ; sonst: Indexregister (Zeiger!) erhoehen<br />
BRA LOOP ; und weitermachen in der Schleife<br />
FERTIG STAA SUMME ; Ergebnis abspeichern<br />
In der Sprache C könnte das etwa folgendermaßen aussehen, wobei feld als Array der Größe<br />
fleng vereinbart ist.<br />
feldptr = &feld[0];<br />
summe = 0;<br />
Mikrocomputertechnik<br />
Sprungbefehle 73
i = fleng;<br />
do<br />
{<br />
summe = summe + *feldptr;<br />
feldptr++;<br />
i--;<br />
} while(i>0);<br />
Unterprogrammsprünge (jump/branch to subroutine)<br />
Die Unterprogrammtechnik ist ein wertvolles Hilfsmittel zur modularen Programmierung in<br />
<strong>Assembler</strong>. Darüber hinaus wird bei Verwendung von Unterprogrammen (UP) Speicherplatz für<br />
Programme gespart, wenn sie in einem Programm mehrfach verwendet (aufgerufen) werden.<br />
Gleiche oder sehr ähnliche Befehlssequenzen in einem Programm sollten deshalb immer zu<br />
Unterprogrammen zusammengefasst werden, wie eine Funktion in C. Ein weiterer Nutzen: Die<br />
Programme werden dadurch leichter zu lesen. Voraussetzung sind natürlich aussagekräftige Namen<br />
für die Unterprogramme und eine möglichst gute Kommentierung, auch im Programmkopf.<br />
Unterprogramme können außerdem geschachtelt, das heißt, von Unterprogrammen aufgerufen<br />
werden.<br />
UP können innerhalb der Programme, die diese verwenden, oder außerhalb derselben in<br />
UP-Bibliotheken definiert sein. Sie sollen möglichst universell programmiert und damit für<br />
wechselnde Datenwerte geeignet sein. Folglich müssen Eingabe- und Ausgabeparameter übergeben<br />
werden. Unterprogramme müssen auch an beliebiger Stelle des Hauptprogramms aufgerufen<br />
werden können (und damit auch an mehreren Stellen), sie sollten daher den Inhalt derjenigen<br />
Register sichern (z. B. auf dem Stack), die innerhalb des UP verändert werden. Das aufrufende<br />
Programm muss die Initialisierung des Stackpointers vornehmen, beim Aufruf des UP die<br />
Eingabeparameter an vereinbarter Stelle bereitstellen und eventuell Platz für Ausgabeparameter<br />
reservieren.<br />
Es wird allerdings ein Mechanismus notwendig, der die Rückkehr aus dem Unterprogramm zum<br />
Befehl nach dem Unterprogramm-Aufruf sicherstellt. Der Einsprung in ein Unterprogramm erfolgt<br />
deshalb mit einem speziellen Sprungbefehl, der automatisch den aktuellen Befehlszählerstand<br />
(Rücksprungadresse) auf den Systemstack rettet, bevor er mit der Sprungziel-Adresse überschrieben<br />
wird. Der Rücksprung nach Beendigung des Unterprogramms zurück ins aufrufende Programm<br />
besteht dann nur aus einem Zurückschreiben der beiden obersten Stack-Bytes in den Befehlszähler.<br />
Der "Jump to Subroutine" dient zum Sprung zu einem Unterprogramm (Function, Procedure in<br />
höheren Programmiersprachen). Der Unterschied zum "normalen" Sprung besteht darin, dass am<br />
Ende des Unterprogramms mit einem "Return from Subroutine" (RTS) an die Stelle des "Aufrufs"<br />
(Absprungs) zurückgekehrt werden muss.<br />
JSR adr.<br />
Mikrocomputertechnik<br />
• absolute Adressierung<br />
• wie JMP adr., aber zusätzlich Ablage des PC (der die Adresse des nächsten Befehls<br />
enthält) auf dem Stack Möglichkeit der Rückkehr<br />
Beim JSR wird also vor dem Überschreiben des PC der aktuelle PC-Stand auf den Stack gerettet,<br />
Unterprogrammsprünge (jump/branch to subroutine) 74
d.h. der Stack wächst dabei um 2 Bytes! So kann der RTS-Befehl auf dem Stack den ursprünglichen<br />
PC-Stand wiederfinden (Rücksprung aus dem Unterprogramm zurück in das aufrufende<br />
Programm).<br />
BSR dest.<br />
• Offset wird immer PC-relativ angegeben (-128 ... +127)<br />
• <strong>Assembler</strong> übernimmt Offset-Berechnung<br />
RTS (return from subroutine)<br />
Der RTS-Befehl dient dazu, aus einem Unterprogramm in das "aufrufende" Programm<br />
zurückzukehren. Notwendige Voraussetzung ist, dass vom aufrufenden Programm per JSR- oder<br />
BSRBefehl in das Unterprogramm gesprungen wurde, denn nur diese Befehle retten vor dem<br />
Sprung den Inhalt des PC auf den Stack.<br />
• Rücksprung aus Unterprogramm<br />
• Die Rücksprungadresse wird vom Stack geholt<br />
• letzter Befehl eines Unterprogramms<br />
• PULX<br />
JMP 0,X<br />
Unterprogramme lassen sich beliebig schachteln.<br />
Typische Anfängerfehler:<br />
Mikrocomputertechnik<br />
• Ein mit RTS logisch abgeschlossenes Unterprogramm wird mit JMP, BRA oder bedingtem<br />
Branch angesprungen! (Was geschieht?).<br />
• Ein mit JSR oder BSR angesprungenes Unterprogramm wird mit einem JMP, BRA oder<br />
bedingten Branch verlassen! (Was geschieht?)<br />
Unterprogrammsprünge (jump/branch to subroutine) 75
Programmunterbrechungsbefehle<br />
SWI (software interrupt)<br />
• Sprung in eine Interrupt-Service-Routine (ISR)<br />
• Startadresse ist Interruptvektor (steht in HW-mäßig festgelegter Speicherzelle)<br />
• vorher Ablage aller Register auf dem Stack<br />
• Anwendung:<br />
z. B. positionsunabhängiger Aufruf von BS-Routinen; Parameter in Registern oder auf dem<br />
U-Stack<br />
RTI (return from interrupt)<br />
• Rücksprung aus einer ISR<br />
• Rückladen der Register vom Stack<br />
• letzter Befehl der ISR<br />
Reine Verzögerungsbefehle<br />
• NOP No Operation<br />
• BRN Branch Never<br />
Anwendungen:<br />
• Zeitverzögerung (z. B. Laufzeitangleichung)<br />
• Platzhalter für spätere Programmverzeigungen (bei der Programmentwicklung)<br />
• Platz für Label<br />
• "Patchen" von Programmen (Ändern des Maschinencodes)<br />
3.6 Stapelspeicher (Stack)<br />
Mikrocomputertechnik<br />
Zum Zwischenspeichern von Information ist ein Register(-satz) prinzipiell sehr gut geeignet. Das<br />
Problem ist nur seine sehr begrenzte Kapazität. Legt man temporäre Zwischenspeicher im<br />
Arbeitsspeicher an, so muss man Geschwindigkeitseinbußen in Kauf nehmen aber vor allem ist die<br />
Verwaltung derartiger "Hilfszellen" umständlich und zeitraubend. Eine Lösung dieses Problems<br />
bietet ein Stapelspeicher (Stack). Dies ist ein wortorganisierter Speicher mit implizitem Zugriff<br />
LIFO-Speicher (Last In First Out). Die Realisierung beim 68HC11 erfolgt als externer Stack<br />
(Software-Stack). Er ist Teil des Arbeitsspeichers, Die automatische Adressierung erfolgt über den<br />
Stapelzeiger (Stackpointer, S). Der Stackpointer ist ein 16-Bit-Register und zeigt immer auf die<br />
nächste freie Zelle. Der Stack wächst zu kleiner werdenden Adressen ("nach unten").<br />
Am Programmanfang muß der Stack mit einem sinnvollen Wert besetzt werden.<br />
Die Vorteile des SW-Stacks mit Stackpointer-Adressierung sind unter anderem:<br />
• Kapazität des Stacks ist der jeweiligen Anwendung anpaßbar<br />
• keine Vereinbarung von Hilfszellen erforderlich<br />
Programmunterbrechungsbefehle 76
• keine Adreßangabe bei Verwendung des Stacks nötig<br />
Befehle für den Stack-Zugriff<br />
• Stack dient zum schnellen Ablegen von Registerinhalten<br />
• Befehle zum Schreiben in den Stack: PSHx ("Push")<br />
• Befehle zum Lesen aus dem Stack: PULx ("Pull")<br />
• Beim PSH-Befehl wird der SP nach dem Ablegen eines Register-Inhalts decrementiert<br />
• Beim PUL-Befehl wird der SP vor dem Holen eines Register-Inhalts incrementiert<br />
• Bei 16-Bit-Registern wird das LSB zuerst abgelegt (höhere Adr.),dann das MSB (niedrigere<br />
Adr.) MSB wird beim PUL zuerst geladen<br />
Schreiben in den Stack:<br />
♦ PSHA Register A Stack<br />
♦ PSHB Register B Stack<br />
♦ PSHX Register X Stack<br />
♦ PSHY Register Y Stack<br />
Lesen aus dem Stack:<br />
♦ PULA Stack Register A<br />
♦ PULB Stack Register B<br />
♦ PULX Stack Register X<br />
♦ PULY Stack Register Y<br />
Man kann normalerweise nur immer das "oberste" Stackelement lesen. Die Stack-"Verwaltung"<br />
muss sehr sorgfältig geschehen, damit jederzeit klar ist, welche Information gerade "oben" liegt<br />
oder - besser ausgedrückt - wo der Stackpointer gerade hinzeigt. Unsauberer Umgang mit dem<br />
Stack führt fast unweigerlich zu unverständlichen Programmabstürzen!<br />
Anwendung des Stack<br />
Mikrocomputertechnik<br />
Der Stack dient dem Zwischenspeichern von Registerinhalten um:<br />
• Register anderweit verwenden zu können<br />
• Parameterübergabe bei Unterprogrammen (siehe später)<br />
• "Retten" von Registerinhalten beim Unterprogrammaufruf: Zu Beginn des UP werden die<br />
verwendeten Register auf dem Stack abgelegt und vor Rückkehr zum Hautprogramm<br />
wieder restauriert<br />
• Speicherung der Rücksprungadresse bei Unterprogrammsprüngen: Die Abspeicherung<br />
erfolgt automatisch auf dem Stack bei JSR und BSR. Bei RTS wird die Rücksprungadresse<br />
automatisch vom Stack geladen.<br />
• Ablage des Programmstatus bei Interrupts durch CPU auf dem Stack. Automatisches Laden<br />
des Programmstatus bei RTI.<br />
3.6 Stapelspeicher (Stack) 77
Wichtig ist der sorgfältige und überlegte Umgang mit Stack- und SP-Operationen. Damit kein<br />
Stack-Überlauf(-Unterlauf) auftritt:<br />
• gleichviele PSH- und PUL-Befehle<br />
• PSH- und PUL-Befehle "symmetrisch", z. B.:<br />
•<br />
PSHA<br />
PSHB<br />
.<br />
.<br />
.<br />
PULB<br />
PULA<br />
eventuell Dekrementieren oder Incrementieren des SP nötig<br />
3.7 Unterprogramme (Subroutines)<br />
Unterprogramme sind Programmteile (=Befehlsfolgen), die mit einem Namen versehen sind und<br />
unter diesem Namen aufgerufen werden. UP können in den Programmen, die diese verwenden, oder<br />
außerhalb derselben definiert sein UP-Bibliotheken. Sie sollen möglichst universell<br />
programmiert (und damit für wechselnde Datenwerte) sein Parameter müssen übergeben werden<br />
(Eingabe- und Ausgabeparameter). UP müssen an beliebiger Stelle des Hauptprogramms<br />
aufgerufen werden können (und damit auch an mehreren Stellen), sie sollten daher den Inhalt<br />
derjenigen Register sichern (z. B. auf dem Stack), die innerhalb des UP verändert werden. Typische<br />
Anwendungen der UP-Technik sind:<br />
• Verwendung gleicher Programmteile an mehreren Programmstellen<br />
• Rückgriff auf Programmbibliotheken<br />
• Übersichtlicher Aufbau von Programmen (modular + strukturiert) Programmerstellung<br />
durch mehrere Programmierer möglich<br />
Programme mit UP dauern etwas länger als ohne (meist überwiegen jedoch die Vorteile der UP).<br />
Anmerkungen zur Dokumentation:<br />
• Dokumentation ist wichtig für problemlose und fehlerfreie Verwendung von UP (besonders<br />
von fremden UP)<br />
• Die innere Struktur der UP muß für deren Anwendung nicht unbedingt bekannt sein<br />
• Folgende Informationen sind notwendig:<br />
♦ Zweck (Beschreibung der Aufgabe) des UP<br />
♦ Beschreibung der Ein- und Ausgabeparameter<br />
♦ Angabe der veränderten Register und Speicherplätze<br />
♦ Anwendungs-(Aufruf-) Beispiel<br />
• Dokumentation soll bereits im Programmlisting durch entsprechende Kommentare<br />
vorgenommen werden<br />
Aufgaben des aufrufenden Programms:<br />
Mikrocomputertechnik<br />
• Initialisierung des/der Stackpointer (Hauptprogramm)<br />
• Bereitstellen der Eingabeparameter an vereinbarter Stelle<br />
• eventuell Platzreservierung für Ausgabeparameter<br />
• Aufruf des UP<br />
• falls erforderlich, Wegspeichern der Ausgabeparameter<br />
Anwendung des Stack 78
Unterprogramm-Sprungbefehle<br />
sind spezielle Sprungbefehle, die vor dem Sprung die Rücksprungadresse auf dem Stack sichern.<br />
Beim Rücksprung wird diese Adresse automatisch geladen.<br />
Sprung in das UP: JSR, BSR<br />
Unterscheidung in der Adressierungsart. Wirkung:<br />
• Speichern des PC auf dem Stack (da der Sprungbefehl bereits geholt und dekodiert wurde,<br />
zeigt der PC auf den nächsten Befehl (= Rücksprungadresse)). Zuerst Speicherung des<br />
PC-LSB, dann PC-MSB.<br />
• Laden des PC mit der Startadresse des UP<br />
Rücksprung aus dem UP: RTS<br />
Letzter Befehl des UP, Wirkung:<br />
• Laden der Rücksprungadresse vom Stack in den PC<br />
Achtung: Vor dem Rücksprung muß der Stackpointer i. a. auf die gleiche Adresse zeigen, wie nach<br />
dem Ansprung des UP Sorgfalt bei Stackoperationen notwendig! Beim UP-Sprung (und<br />
Rücksprung) wird nur der PC-Inhalt geändert, der Inhalt aller anderen Register bleibt erhalten.<br />
Register können zur Parameterübergabe verwendet werden<br />
Im UP verwendete Register müssen gegebenenfalls gesichert werden<br />
Vorteil der Speicherung der Rücksprungadresse auf dem Stack:<br />
• Aufruf weiterer UP durch ein UP möglich verschachtelte UP<br />
• Rückkehradresse immer am Stack-Ende<br />
• Schachtelungstiefe nur durch Stackgröße begrenzt<br />
Parameter-Übergabe<br />
Eingabeparameter: Werte UP<br />
Ausgabeparameter: Werte UP<br />
Möglichkeiten der Parameterübergabe:<br />
• Direkte Übergabe in Registern Elegante Methode, jedoch durch Registerzahl begrenzt<br />
• Über festen Speicherbereich inflexibel (manchmal bei BS-Aufrufen)<br />
• Über variablen Speicherbereich (Parameterblock) Anfangsadresse des Parameterblocks<br />
wird in einem Register übergeben indirekte Parameterübergabe<br />
• Über den Stack Ablage im aufrufenden Programm mittels PSHx. Da die Parameter vor dem<br />
UP-Sprung abgelegt wurden (und somit der PC-Stand der letzte Wert auf dem Stack ist),<br />
sind sie mit PULx nicht ohne weiteres erreichbar (außer Rücksprungadresse wird<br />
zwischengespeichert). Der Zugriff ist daher komplizierter. Vom HP kann vor UP-Aufruf<br />
Stackplatz für Ausgabeparameter freigehalten werden (Nach Rückkehr Bereinigung des<br />
Stack nötig).<br />
Beispiel: Verzögerungsroutine<br />
Mikrocomputertechnik<br />
Es soll eine Verzögerung von 1 ms erreicht werden. Das Prinzip der Routine ist recht einfach: Ein<br />
Akkumulator wird mit einem Anfangswert besetzt und dann in einer Schleife solange<br />
Unterprogramm-Sprungbefehle 79
dekrementiert, bis sein Wert Null geworden ist.<br />
ORG PROG Programm soll bei Adresse PROG beginnen<br />
MAIN BSR VERZ Aufruf Unterprogramm<br />
STOP BRA STOP Endlosschleife, stoppt Programm<br />
("Wiederbeleben" des Computers mit Reset)<br />
* Verzögerungs-Unterprogramm<br />
* Verzögerungszeit: 1 ms<br />
* Keine Parameter<br />
*<br />
VERZ LDAA #221 Anfangswert (Konstante) laden (siehe unten)<br />
VZ NOP No Operation (Zeitverzoegerung)<br />
NOP No Operation (Zeitverzoegerung)<br />
DECA A runterzählen bis 0<br />
BNE VZ solange A != 0, weiterer Durchlauf<br />
RTS Verzögerung erreicht (A = 0)<br />
END<br />
Berechnung der Verzögerungszeit: Aus der Befehlstabelle kann man die Anzahl der Taktzyklen für<br />
jeden Befehl entnehmen. Wenn man nun noch die Taktfrequenz weiß, kann man die Ablaufzeit<br />
eines Programms ausrechnen. Wir müssen vier Zeiten wissen:<br />
tl Ausführungszeit LDAA 2 Taktzyklen<br />
td -"- DECA + 2 NOP 6 -"-<br />
tb -"- BNE 3 -"-<br />
tr -"- RTS 5 -"-<br />
Bei unserem Praktikumsrecher dauert ein Taktzyklus 0,5 Mikrosekunden. Die Gesamtzeit tg ergibt<br />
sich zu:<br />
tg = 0,5 * n * (td + tb) + tl + tr<br />
= 0,5 * n * (6 + 3 ) + 2 + 5<br />
= 0,5 * (n * 9 + 7)<br />
Da tg = 1 ms = 1000 Mikrosekunden sein soll, berechnet sich n zu<br />
n = (1000 - 3,5) / 4,5<br />
= 996,5 / 4,5<br />
= 221,44<br />
n = 221<br />
Es ergibt sich also ein kleiner Fehler; unsere Schleife ist einen knappen Taktzyklus zu langsam.<br />
Will man wirklich genaue Zeitintervalle, greift man auf den integrierten Timer zurück (siehe<br />
später).<br />
Im gezeigten Beispiel "Verzögerungsroutine" ist die maximale Verzögerungszeit durch die<br />
Wortbreite des Akku A (8 Bit 0..255) auf etwas mehr als 1 ms begrenzt.<br />
Für größere Verzögerungen:<br />
Mikrocomputertechnik<br />
• Verlängerung von ts durch zusätzliche Befehle (NOP, BRN)<br />
• Verwendung eines 16-Bit-Registers (z. B. D, X, Y)<br />
• Schachtelung von Schleifen<br />
• Durch Parameter erhält man UP mit variabler Verzögerungszeit<br />
Beispiel: Gegeben ist folgende Verzögerungsroutine mit 16-Bit-Register:<br />
Parameter-Übergabe 80
* Verzögerungs-Unterprogramm<br />
* Verzögerungszeit: 500 ms<br />
* Keine Parameter<br />
*<br />
; delay dauert 3 + 5 + 4 + 5 + $f000*16 cycl<br />
; = 8,5 + $f000*8 us = 491528,5 us<br />
delay pshx ; X retten, 4 cycl<br />
ldx #$f000 ; Anfangswert laden, 3 cycl<br />
delay1 nop ; Zeit verschwenden, 5 x nop = 10 cycl<br />
nop<br />
nop<br />
nop<br />
nop<br />
dex ; X run<br />
bne delay1 ; solange X != 0 weiter, 3 cycl<br />
pulx ; X restor, 5 c<br />
rts ; und w<br />
3.8 Interrupts (Programmunterbrechungen)<br />
HAlle modernen Mikroprozessoren besitzen deshalb mehr oder weniger ausgefeilte<br />
Hardware-Mechanismen zur Programmunterbrechung durch solche Ereignisse. Ein<br />
Hardware-Ereignis erzwingt einen "Unterprogrammsprung" zu einem vorbereiteten<br />
Bearbeitungs-Programm, der so genannten Interrupt-Service-Routine (ISR). Die Ähn-lichkeit des<br />
Interrupt mit einem Unterprogrammsprung (JSR) ist tatsächlich groß. Das Auftreten des<br />
Interrupt-Request-Signals auf dem Bus wird vom Mikroprogramm am Ende jedes Befehlszyklus<br />
geprüft und führt zu einem Sprung zum Beginn der ISR. Ein JSR zu einem bestimmten<br />
Unterprogramm kann an beliebigen Stellen im Programm vorkommen, der Rücksprung RTS sorgt<br />
für die Rückkehr an die richtige Stelle im aufrufenden Programm. Ein Interrupt dagegen kann<br />
prinzipiell nach jedem beliebigen Befehl des Programms wirksam werden, dementsprechend muss,<br />
wie beim JSR, der PC-Stand gerettet werden; auch das erledigt die Ablaufsteuerung bei der<br />
Annahme des Interrupt Request, genau wie beim JSR. Die Interrupt-Service-Routine wird mit<br />
einem ähnlichen Befehl wie ein Unterprogramm verlassen (RTI statt RTS), denn auch hier muss der<br />
Rücksprung wieder zur Unterbrechungsstelle zurückführen. Man unterscheidet beim 68HC11<br />
Interrupts, die von Hardwaresignalen ausgelöst werden (XIRQ, IRQ und RESET) und den internen<br />
Interruptquellen (interne Peripherie-bausteine bzw. "illegal Operation"). Außerdem gibt es einem<br />
Befehl (SWI), der ebenfalls einen Interrupt auslöst. Ein weiteres Unterscheidungskriterium ist die<br />
Maskierbarkeit. Der "normale" Interrupt ist nur dann wirksam, wenn das entsprechende Maskenbit<br />
im CC-Register gelöscht ist (gleich 0). Die Signale RESET und XIRQ sind nicht maskierbar, sie<br />
werden deshalb auch als "nicht maskierbare Interrupts" (NMI) bezeichnet. Der XIRQ weist dabei<br />
noch eine Besonderheit auf: er ist nach einem RESET so lange gesperrt (maskiert), bis er durch<br />
Nullsetzen von Bit 6 im CC-Register freigegeben wird. Danach ist er nicht mehr sperrbar!<br />
Anwendungen:<br />
Mikrocomputertechnik<br />
• Quasiparallele Ausführung mehrerer Programme (normalerweise nur Hauptprogramm und<br />
ISR) - Parallelarbeit von Programmen und externen Geräten (interruptgesteuerter<br />
3.8 Interrupts (Programmunterbrechungen) 81
E/A-Transfer)<br />
• Reaktion auf unvorhersehbare Ereignisse (z. B. Spannungsabfall)<br />
• Testen von Programmen mittels Breakpoints (SW-Interrupt)<br />
• Aufruf von Betriebssystemfunktionen (SW-Interrupt)<br />
Aufgaben der CPU bei einen Interrupt:<br />
1. Abspeichern von Registerinhalten (bei 68HC11 im Stack)<br />
2. Setzen der Interruptmaske zum Sperren weiterer Interrupts<br />
(Unter Berücksichtigung der Priorität)<br />
3. Laden der Startadresse (= Interrupt-Vektor) der ISR in den PC<br />
♦ Der Interruptvektor steht an einer hardwaremäßig vorgegebenen Adresse, die von<br />
der Art des Interrupts abhängt.<br />
♦ Je nach Interrupt-Art wird die entsprechende Interrupt-Vektor-Adresse auf den Bus<br />
gegeben.<br />
♦ In den so adressierten Speicherzellen steht dann die Startadresse der ISR (=<br />
Interrupt-Vektor), die in den PC gebracht wird Start der ISR<br />
4. Fortsetzung des unterbrochenen Programms nach der Interrupt-Bearbeitung: RTI-Befehl<br />
♦ weggespeicherte Register werden vom Stack geholt<br />
♦ PC erhält Adresse des nächsten Befehls des unterbrochenen Programms<br />
Im allgemeinen wird ein Hardware-IRQ erst am Ende eine Befehlszyklus bedient. Außer dem PC<br />
und dem Stackpointer werden keine Register beeinflußt. Interrupts können geschachtelt werden (3<br />
Ebenen).<br />
Interruptsystem des 68HC11:<br />
Signal RESET Unbedinger Abbruch und Neustart<br />
Signal XIRQ & (X-Bit = 0) Unbedingte Unterbrechung (non maskable interrupt)<br />
Signal IRQ & (I-Bit = 0)<br />
Mikrocomputertechnik<br />
Bedingte Unterbrechung (interrupt request)<br />
(kann auch interne Ursachen haben)<br />
I-Bit beeinflußbar durch die Befehle SEI/CLI<br />
Befehl SWI Befehlsgesteuerte Unterbrechung (software interrupt)<br />
Befehl Illegal Opcode Nicht implementierter Befehl<br />
Beim Auftreten eines Interrupts wird das I-Bit auf 1 gesetzt (Sperren IRQ), bei Reset und XIRQ<br />
auch das X-Bit. Beim RTI wird durch das Zurückschreiben des Statusregisters diese Sperre<br />
automatisch wieder aufgehoben. Das X-Bit kann nicht per Programm beeinflußt werden.<br />
Jedem dieser Interrupts ist eine eindeutige Interrupt-Vektor-Adresse (= Adresse, unter welcher der<br />
Interrupt-Vektor, also die Adresse der Interrupt-Serviceroutine, zu finden ist) zugeordnet:<br />
Interruptsystem des 68HC11: 82
Mikrocomputertechnik<br />
Zu jeder Interrupt-Art ist eine eigene ISR möglich. Zumindest der RESET-Vektor muß bei<br />
Einschalten vorhanden sein ROM im höchsten Adreßbereich nötig.<br />
Beispiel: Starten der Interrupt-Service-Routine für XIRQ<br />
Grundsätzlich gilt für Programme mit Interrupt-Serviceroutinen, daß vier Schritte für die<br />
Initialisierung (zu Beginn des Hauptprogramms) nötig sind:<br />
1. Setzen des System-Stackpointers<br />
Solange er nicht gesetzt ist, werden keine Interrupts entgegengenommen.<br />
2. Initialisierung der Hardware<br />
In der Regel werden Interrupts von E/A-Bausteinen ausgelöst. Diese müssen entsprechend<br />
programmiert werden.<br />
3. Setzen des Interruptvektors<br />
Siehe oben.<br />
4. Freigeben des Interrupts durch Setzen des entsprechenden I-Flags im CC-Register auf 0.<br />
Bei einer ISR für XIRQ entfällt dieser Punkt natürlich.<br />
Zum vorhergehenden Abschnitt Zum Inhaltsverzeichnis Zum nächsten Abschnitt<br />
Interruptsystem des 68HC11: 83
Copyright © FH München, FB 04, Prof. Jürgen Plate<br />
Letzte Aktualisierung: 02. Jul 2012<br />
Mikrocomputertechnik<br />
Mikrocomputertechnik<br />
Prof. Jürgen Plate<br />
Interruptsystem des 68HC11: 84
4. Bausteine des Systems M68HC11<br />
4.1 Mikroprozessor 68HC11<br />
Der Prozessor<br />
• ist zuständig für die sequentielle Instruktionsausführung (Instruktion entspricht einer<br />
Zustandsänderug im Speicher oder in einem Register).<br />
• Ausführung synchron durch internen Taktgenerator (dieser wird beim 68HC11 durch einen<br />
externen Quarz-Oszillator gesteuert).<br />
• Systemtakt des 68HC11: 2 MHz<br />
(entsprach zur Entwicklungszeit der maximalen Taktfrequenz eines externen EPROMs)<br />
• Systemtakt wird für externe Zwecke (an Pin E) zur Verfügung gestellt.<br />
• eine Instruktion benötigt beim 68HC11 mindestens 2 Takte = 1 Mikrosekunde<br />
• längste Operation: Division (FDIV) mindestens 41 Takte = 20,5 Mikrosekunden<br />
Beim 68HC11 gibt es diverse Varianten, die sich hauptsächlich im integrierten Speicher<br />
unterscheiden. Zusammenfassend ergeben sich folgende Eigenschaften:<br />
• CPU mit 8 Bit Daten und 16 Bit Adressen<br />
• 256 Byte RAM<br />
• 2 - 8 KByte ROM<br />
• 515 - 2048 Byte EEPROM<br />
• Asynchrone serielle Kommunikationsschnittstelle<br />
• Echtzeit-Interrupts<br />
• 38 digitale Ein- und Ausgänge, teils mit Handshake-Funktion<br />
• 2 Hardware-Interrupts<br />
• Impulszähler<br />
• 16-Bit-Timer-System mit 3 Zeitmeß-Eingängen und 4 PWM-Ausgängen<br />
• Analog-Digital-Wandler mit 8 gemultiplexten Eingängen<br />
• Synchrone serielle Schnittstelle<br />
Der Prozessor arbeitet mit einer Taktfrequenz von 2 MHz, die von einem 8-MHz-Quarz abgeleitet<br />
wird. Die Betriebsspannung beträgt 5 V, die Stromaufnahme etwa 15 mA, wobei jedoch bei<br />
Batteriebetrieb der Mikrocontroller in Arbeitspausen durch Software-Befehle in einen<br />
Stromsparzustand geschaltet werden kann.<br />
4. Bausteine des Systems M68HC11 85
Die wichtigsten Anschlußpins<br />
Name Anzahl Art Bedeutung<br />
Vss<br />
(GND)<br />
1 E Versorgungsspannung 0V<br />
VDD 1 E Versorgungsspannung 5V<br />
EXTAL 1 E Quarz (oder externer, CMOS-kompatiblerTaktgenerator)<br />
XTAL 1 A Quarz<br />
E 1 A Bus-Takt L: interne Aktivität H: externe Aktivität (Datenverkehr)<br />
RESET 1 E Rücksetzen des M68HC11 X-Bit und I-Bit = 1, (FFFE,FFFF)<br />
Befehlszähler<br />
MODA 1 E L: single chip mode (nur interne Komponenten) H: expanded mode<br />
(externe Komponenten möglich)<br />
MODB 1 E L: special variation (down load or test) H: normal variation (applications)<br />
XIRQ 1 E unbedingte Unterbrechung (non maskable interrupt) maskiert durch X-Bit<br />
im CCR<br />
IRQ 1 E bedingte Unterbrechung (interrupt request) maskiert durch I-Bit im CCR<br />
PA i<br />
3<br />
4<br />
1<br />
E<br />
A<br />
E/A<br />
Mikrocomputertechnik<br />
Port A: 3 Digitaleingänge, 4 Digitalausgänge, 1 Digitalein/ausgang oder<br />
Pulsakku-Eingang (unterbrechungsfähig)<br />
PB A15-8 8 A Port B: 8 Digitalausgänge oder 8 Adressleitungen<br />
PCAD7-0 8 E/A Port C: 8 Digitalein/ausgänge oder 8 Adress/Datenleitungen (gemultiplext)<br />
STRA AS 1 E/A Steuerleitung (Eingang, unterbrechungsfähig) oder<br />
Adress/Datenleitungs-Steuerung<br />
1 A Steuerleitung (Ausgang) oder Datenrichtung (read/write)<br />
Der Prozessor 86
STRB<br />
R/W<br />
PD 6 E/A Port D: 6 Digitalein/ausgänge oder 1 SCI und 1 SPI<br />
PE 8 E Port E: 8 Digitaleingänge oder 8 Analogeingänge für A/D-Wandler<br />
Vrefh 1 E Referenz-Spannung für A/D-Wandler<br />
Vrefl 1 E Referenz-Spannung für A/D-Wandler<br />
Reset<br />
Mikrocomputertechnik<br />
Der Reset-Eingang wird dazu benutzt, den Mikroprozessor in einen definierten Anfangszustand zu<br />
bringen. Da für einige der intern ablaufenden Vorgänge zwingend ein Oszillatortakt benötigt wird,<br />
sollte ein Reset-Signal erst nach Stabilisierung des Oszillator-Kreises gegeben werden. Sobald der<br />
Prozessor die Reset-Bedingung gültig erkennt, werden alle internen Schaltungsgruppen in einen<br />
definierten Anfangszustand versetzt:<br />
• Nach dem Reset-Signal lädt die CPU den Reset-Vektor aus dem der gewählten Betriebsart<br />
entsprechenden Adressbereich in den Programcounter. Dies ist ($FFFE, $FFFF) im<br />
Normalbetrieb oder ($BFFE, $BFFF) in den Betriebsarten "Special Test" und "Bootstrap".<br />
Der Stackpointer und die anderen Register der CPU sind nach dem Reset weiterhin<br />
undefiniert, nur das X- und das I-Bit im CCR-Register werden gesetzt, um undefinierte<br />
Interrupts zu verhindern.<br />
• Das INIT-Register wird beim Reset auf $01 gesetzt. Damit liegt das interne Prozessor-RAM<br />
im Adressbereich $0000 bis $OOFF, die Control-Register liegen auf den Adressen $1000 bis<br />
$103F. Der Prozessor-Reset hat keinen Einfluß auf das Mapping der ROM- und<br />
EEPROM-Bereiche, da die beiden Bits, die die Zugriffe auf diese Bereiche kontrollieren,<br />
EEPROM-Zellen des Config-Registers sind.<br />
• Durch das Reset-Signal wird das prozessorinterne Timer-System auf $0000 gesetzt, alle<br />
Prescaler-Bits werden gelöscht und sämtliche Output-Compare-Register erhalten den Wert<br />
$FFFF. Der Inhalt der Input-Capture-Register ist undefiniert. Damit keine undefinierten<br />
Signale an den E/A-Pins des Prozessors durch das Timer-Systern ausgegeben werden können,<br />
werden alle Output-Compare-Systeme so initialisiert, daß sie keinen Einfluß auf die logischen<br />
Zustände der zugeordneten E/A-Pins haben. Die Flankenerkennung der drei<br />
Input-Capture-Register wird durch das Reset-Signal ausgeschaltet, alle dem Timer-System<br />
zugeordnete Interrupt-Flags werden gelöscht und alle neun Timer-Interrupt-Quellen werden<br />
gesperrt.<br />
• Die Behandlung der E/A-Ports bei einem Reset-Signal ist von der eingestellten Betriebsart<br />
abhängig; in der Betriebsart "Extended" sind die 18 E/A-Pins des 68HC11 den verschiedenen<br />
Bussystemen zugeordnet. In der Betriebsart "Single-Chip", werden alle Interrupt-Quellen, die<br />
mit den E/A-Ports in Verbindung stehen, gelöscht. Dazu gehören die Bits STAF, STAI und<br />
HNDS im PIOC-Register. Die Betriebsart der E/A-Ports wird durch das gelöschte HNDS-Bit<br />
auf "Simple Strobed E/A" festgelegt.<br />
Port C ist nach dem Reset als Eingang definiert, sein Datenrichtungsregister demnach mit $00<br />
besetzt. Port B ist als Ausgang mit auf Null gesetzten Ausgangssignalen initialisiert. Der<br />
flankenempfindliche Eingang STRA reagiert auf die ansteigende Flanke eines Signals.<br />
• Nach einem Reset-Signal ist die Baud-Rate des seriellen Interfaces in jedem Fall undefiniert<br />
und muß durch das Anwenderprogramm festgelegt werden. Sämtliche Interrupt-Quellen der<br />
seriellen Schnittstelle sind deaktiviert und die Zuordnung der Empfangs- und Sendeleitungen<br />
zu den entsprechenden E/A-Pins ist aufgehoben, so daß diese Pins als normale E/A-Pins zur<br />
Verfügung stehen. Das Übertragungsformat der seriellen Schnittstelle ist auf 8 Bit eingestellt.<br />
Im Statusregister des seriellen Systems werden die TDRE- und TC-Bits gesetzt.<br />
• Das Puls-Akkumulator-System des 68HC11 ist nach einem Reset ausgeschaltet, der Eingang<br />
(PAI) ist als normaler E/A-Pin geschaltet.<br />
Die wichtigsten Anschlußpins 87
• Die interne Prozessorüberwachung (COP) verhält sich entsprechend dem NOCOP-Bit im<br />
Config-Register(NOCOP-Bit = 1: Überwachung aus, NOCOP-Bit = 0: Überwachung ein). In<br />
diesem Fall wird das Time-Out-Intervall des COP-Systems auf die kleinste verfügbare Zeit<br />
gesetzt.<br />
• Das serielle Peripherie-Interface (SPI) wird durch ein Reset-Signal ausgeschaltet. Die<br />
zugehörigen E/A-Leitungen stehen als normale E/A-Pins zur Verfügung.<br />
• Die Definition des A/D-Wandler-Systems ist undefiniert. Nur das ADPU-Bit wird gelöscht, so<br />
daß das A/D-System deaktiviert bleibt.<br />
• Sämtliche EEPROM-Steuerbits, die zur Programmierung benötigt werden, sind nach einem<br />
Reset gelöscht, so daß aus dem EEPROM nur gelesen werden kann.<br />
• Der externe Interrupt bekommt die höchste Interrupt-Priorität zugewiesen, das<br />
Interrupt-Signal wird auf pegelabhängig geschaltet, so daß ein Standard-Interruptsystem mit<br />
mehreren Quellen möglich ist.<br />
Als Reset-Quelle steht beim 68HC11 nicht nur der externe Reset-Eingang zur Verfügung. Es gibt drei<br />
weitere interne Reset-Quellen: Power-On-Reset (POR), Watchdog-Timer (COP), Taktüberwachung<br />
(CMR). Jeder dieser Reset-Quellen ist ein eigener Reset-Vektor zugeordnet, der auf das zugehörige<br />
Interrupt-Programm zeigt.<br />
Der Bus<br />
• Verbindung zwischen den Komponenten (speziell: Verbindung der CPU mit dem Speicher)<br />
Adreßbusbreite beim 68HC11: 16Bit = 216 •<br />
= 65536 verschiedenen Speicherplätze mit je 8-bit<br />
Datenwort (64 KByte)<br />
• Bus im Multiplexbetrieb = Daten und Adressen über gleiche Leitungen (Kontrolle über<br />
Steuerleitungen)<br />
• Steuerleitungen geben den Bus-Zustand an (Daten/Adressen, schreiben/lesen)<br />
• Zugriff auf E/A-Ports: speicherabbgebildet<br />
Der Speicher<br />
Mikrocomputertechnik<br />
Der Speicher nimmt Instruktionen und Daten auf (wie beim klassischen von-Neuman Rechner).<br />
Speicherarten:<br />
• RAM: schreiben und lesen, sehr schnell, Speicherinhalt flüchtig (evtl. mit Batterie puffern)<br />
• ROM: nicht flüchtig, Inhalt nicht änderbar<br />
• PROM: 1x änderbar, nicht flüchtig<br />
• EPROM: löschen durch UV-Licht<br />
• EEPROM: lesen und schreiben, langsam (ms, bei RAM ns), begrenzte Lebensdauer<br />
Als Speicher hat der MC68HC811 ein ROM, ein EEPROM und ein RAM an Board. Programme<br />
können in jeden dieser Speicherbereiche geladen und in jedem Bereich ausgeführt werden. Das ROM<br />
kann allerdings nur während des Herstellungsprozesses programmiert werden, so daß diese Variante<br />
erst bei Abnahme von mehreren tausend Stück interessant wird. Ein Teil des ROM ist jedoch stets<br />
vorhanden, da es das Bootloader-Programm enthält. Bei kleinen Stückzahlen oder Einzelstücken ist<br />
das EEPROM der bevorzugte Programmspeicher. Da Programme im RAM nicht dauerhaft gespeichert<br />
werden, dient dieses zur temporären Speicherung von Rücksprungadressen im Stack-Bereich oder von<br />
Zwischenergebnissen des Programmlaufs. Die folgende Liste zeigt eine Zusammenfassung der<br />
Prozessorvarianten:<br />
Reset 88
Innerhalb der Familie gibt es nur geringe Unterschiede in Speicher (Art, Menge) und Ports (Anzahl,<br />
Art). Bei allen Varianten ist der Befehlssatz gleich gleiche (Assenbler-)Programme.<br />
Belegung des Adressraums bei verschiedenen Prozessortypen<br />
Asynchrone serielle Schnittstelle<br />
Über die asynchrone serielle Schnittstelle (SCI) wird das Programm vom PC in den Mikrocontroller<br />
geladen. Sie dient unter anderem auch dazu, beim Testen des Programms Statuswerte oder<br />
Zwischenergebnisse am Bildschirm darzustellen. Die Anschlüsse der seriellen Schnittstelle sind PD0<br />
= RxD (Dateneingang) und PD1 = TxD (Datenausgang).<br />
Timer-System<br />
Mikrocomputertechnik<br />
Das Timer-System steuert solche Funktionen, die einen Bezug zur Realzeit benötigen, also<br />
unabhängig von Befehlsausführungszeiten sein sollen. Intern werden alle Funktionen von einem<br />
konstant durchlaufenden, nicht beeinflußbaren 16-Bit-Taktzähler abgeleitet:<br />
• Der Real-Time-Interrupt (Echtzeitunterbrechung) dient dem Zweck, in genau periodischen<br />
Zeitabständen einen bestimmten Vorgang auszulösen.<br />
• Die 3 Input-Capture-Funktionen (Zeiterfassungsfunktionen) IC1 bis IC3 dienen zur<br />
Zeitmessung von Eingangssignalen an den Eingängen PA0 bis PA2.<br />
Der Speicher 89
• Mit den 4 Output-Compare-Funktionen (Zeitvergleichsfunktionen) OC1 bis OC4 können bei<br />
bestimmten Timer-Zählerständen H-Pegel bzw. L-Pegel an den Anschlüssen PA3 bis PA6<br />
ausgegeben werden.<br />
• Der COP-Watchdog-Timer sorgt dafür, daß die Programmlaufüberwachung innerhalb einer<br />
überwachungsperiode rechtzeitig zurückgesetzt wird. Im Fehlerfall wird ein Reset (Neustart)<br />
des Rechners veranlaßt.<br />
Digitale Ein- und Ausgänge<br />
Je 8 Ein- bzw. Ausgänge sind in den Ports A, B, C und E zusammengefaßt. Die meisten dieser<br />
Anschlüsse haben mehrere Funktionen, die softwaremäßig festzulegen sind. Die jeweilige<br />
Pfeilrichtung im Blockschaltbild kennzeichnet den Anschluß als Eingang oder Ausgang. Der Zugriff<br />
erfolgt wie auf den Speicher. Eigenschaften der fünf Ports:<br />
• Port A: (verbunden mit 16-bit Zähler)<br />
3 Eingänge (sichern des aktuellen Zählerstandes in ein Register durch ein Eingangssignal)<br />
4 Ausgänge (Vergleichsausgänge des Zählers: sobald der Zähler den im zugehörigen Register<br />
gespeicherten Wert erreicht hat, wird hier eine 1-Signal erzeugt)<br />
1 Ein- und Ausgang (Impulszähler)<br />
• Port B und C: Funktion hängt von der Betriebsart der Microcontrollers ab. Der 68HC11 kennt<br />
vier Betriebmodi (einstellbar an den Pins MODA, MODB):<br />
single chip<br />
Mode<br />
expanded<br />
Mode<br />
Mikrocomputertechnik<br />
normal Nur der interne Speicher ist verfügbar, Port B: digitale<br />
Ausgabeschnittstelle, Port C: digitale Eingabe- oder<br />
Ausgabe-Schnittstelle, STRB,STRA beliebig verwendbar (digitale Einbzw.<br />
Ausgänge)<br />
special special bootstrap mode:<br />
In diesem Modus lädt die Firmware über die serielle Schnittstelle (Port<br />
D) ein 255 Bytes großes Grundprogramm, welches anschliesend<br />
ausgeführt wird.<br />
normal Dieser Mode dient zum Anschließen externer Peripherie und externer<br />
Speicher. Der 68HC11 stellt sich dann wie ein normaler<br />
Mikroprozessor dar:<br />
Port B: Buserweiterung<br />
Port C: Buserweiterung<br />
STRA, STR B: Steuerleitungen<br />
special spezieller Testmodus<br />
Timer-System 90
• Port D:<br />
zwei Ein- /Ausgänge (serielle Schnittstelle)<br />
vier Ein- /Ausgänge (für synchronen Datenaustausch mit anderen 68HC11)<br />
• Port E:<br />
8-Kanal A/D-Wandler (Genauigkeit: 8-bit)<br />
Impulszähler<br />
Der Impulszähler dient je nach Software-Vorgabe zur Zählung von Pulsen oder zur Bestimmung einer<br />
Pulsdauer, wobei er im letzteren Fall auf das Timer-System zugreift.<br />
Analog-Digital-Wandler<br />
Mikrocomputertechnik<br />
Die 8 Anschlüsse des Ports E können je nach Bedarf im Multiplexbetrieb auf einen<br />
Analog-Digital-Wandler geschaltet werden. Der Wandler arbeitet mit einer Auflösung von 8 Bit und<br />
beinhaltet eine Sample-and-Hold-Funktion, so daß auch zeitveränderliche Signale amplitudengetreu<br />
verarbeitet werden.<br />
Synchrone serielle Peripherieschnittstelle<br />
Die synchrone serielle Peripherieschnittstelle (SPI) dient zum Datenaustausch mit einem anderen<br />
Mikrocontroller oder speziell dafür entwickelten Peripheriebausteinen, die an PD2 bis PD5<br />
angeschlossen werden.<br />
Digitale Ein- und Ausgänge 91
Vereinfachtes Blockschaltbild des 68HC11<br />
Mikrocomputertechnik<br />
4.2 Typische Anwendungsschaltung<br />
Wie aus dem Stromlaufplan ersichtlich ist, besteht die gesamte Schaltung des Mikrocontrollers nur aus<br />
drei integrierten Bausteinen. Den Mittelpunkt bildet der Mikrocontroller 68HC811 (IC1). Sämtliche<br />
Anschlüsse sind durch Widerstandsnetzwerke abgeschlossen. Der Takterzeugung dient ein<br />
8-MHz-Quarz (Q1), der mit Hilfe der beiden Keramikkondensatoren C3, C4 und dem<br />
Parallelwiderstand R1 auf der Grundwelle schwingt. Für das Laden der Programme und für den<br />
Kontakt mit der Außenwelt wurde ein serieller Pegelwandler vom Typ MAX 232 verwendet. Seine<br />
externe Beschaltung beschränkt sich auf vier Tantalkondensatoren (C6 bis C9) für die internen<br />
Spannungswandler (+12V/-12V). Mit dem Schalter SW1 kann der Mikrocontroller in den Bootmodus<br />
geschaltet werden. Nur in dieser Betriebsart ist es möglich, Programme zu laden und abzuspeichern.<br />
Der Taster TA1 löst einen Reset aus und versetzt die gesamte Schaltung in einen definierten<br />
Anfangszustand.<br />
Die Spannungsversorgung erfolgt durch IC3, einen Festspannungsregler vom Typ 7805. Die von<br />
einem externen Steckernetzteil zugeführte Gleichspannung von etwa 9 V wird hier auf eine konstante<br />
Versorgungsspannung von 5 V geregelt.<br />
Synchrone serielle Peripherieschnittstelle 92
Mikrocomputertechnik<br />
Achtung: Diese Schaltung ist nicht mit der Schaltung des im Praktikum verwendeten "Zwerg 11"<br />
identisch.<br />
Stückliste für das Mikrocontroller-Board<br />
Bezeichnung Bauteil Wert<br />
IC1 Mikrocontroller MC 68HC811 E2 FN<br />
IC2 IC MAX 232<br />
IC3 Regler-IC 7805<br />
Q1 Quarz 8 MHz<br />
RN1 - RN5 Widerstandsnetzwerk 8 x 10 KOhm<br />
R1 Widerstand 10 MOhm<br />
R2 Widerstand 1 KOhm<br />
R3, R4 Widerstand 10 KOhm<br />
R5 Widerstand 4,7 KOhm<br />
C1, C12 Kondensator 100 nF keramik<br />
4.2 Typische Anwendungsschaltung 93
C3, C4 Kondensator 22 pF keramik<br />
C2, C5 Tantalelko 1 Mikrofarad / 35 V<br />
C6, C7, C8, C9 Tantalelko 10 Mikrofarad / 16 V<br />
C10 Elko 100 Mikrofarad / 16 V<br />
C11 Elko 100 Mikrofarad / 16 V<br />
ST1 - ST5 Steckerleiste 2 x 8-polig<br />
Bu1 - Bu5 Buchsenleiste 8-polig<br />
Fassung für IC1 IC-Fassung PLCC 52<br />
Fassung für IC2 IC-Fassung 16-polig<br />
13 Stück Lötstifte 1 mm<br />
4.3 Praktikumssystem PS11 mit M68HC11A0<br />
Blockschaltung<br />
(CONFIG = $0C)<br />
Mikrocomputertechnik<br />
Praktikumsrechner mit Experimetierboard<br />
Stückliste für das Mikrocontroller-Board 94
Der ZWERG11plus<br />
Mikrocomputertechnik<br />
Unter den ganz kleinen Karten ist der ZWERG11A von<br />
Elektronikladen Detmold ein ganz Großer. Mittlerweile<br />
vieltausendfach im Einsatz gab es aber immer wieder<br />
Applikationen, die das Speicherangebot des ZWERG11A<br />
überforderten.<br />
So wurde als Ergänzung zum "kleinen ZWERG" ein "großer ZWERG" geschaffen: der<br />
ZWERG11plus. Die Schwierigkeit, auf einer Platinenfläche von nur 51mm x 54mm einen "großen"<br />
Rechner zu entwerfen, läßt sich sicherlich nachvollziehen. Die Lösung für dieses Problem hieß:<br />
6-Lagen-Multilayer, mehr SMT-Bauteile und doppelseitige Bestückung.<br />
Zum ZWERG11plus gibt es ein Entwicklungspaket. Es besteht aus folgenden Komponenten:<br />
• ZWERG11plus Controllermodul<br />
• Benutzerhandbuch mit Diskette<br />
• RS232 Interface-Modul (IF-Modul)<br />
• Flachbandkabel für IF-Modul und Sub-D9 Anschlußkabel für PC/AT<br />
• Terminalprogramm zur Kommunikation zwischen PC und ZWERG11plus<br />
• Programmier- und Download-Utilities<br />
• Cross-<strong>Assembler</strong> AS11 und Hilfsprogramme<br />
Zur Softwareentwicklung für den ZWERG11plus können Sie, neben dem <strong>Assembler</strong> im<br />
Entwicklungspaket, die Integrierte Entwicklungsumgebung IDE11 einsetzen.<br />
Als C-Compiler stehen Produkte von Imagecraft (ICC11) und Cosmic zur Verfügung. Außerdem<br />
kann man das MOPS-Betriebssystem (<strong>Assembler</strong>/Basic/Pascal) mit dem ZWERG11plus verwenden.<br />
Praktikumsrechner mit Experimetierboard 95
Technische Daten:<br />
Mikrocomputertechnik<br />
• MC68HC11A1 8Bit Mikrocontroller Motorola<br />
• Versorgungsspannung 5V, Stromaufnahme typ. 20-30mA<br />
• Reset-Controller<br />
• 32KByte RAM<br />
• 32KByte EEPROM<br />
• Uhrenbaustein RTC4553 mit Batterie (Option)<br />
• Anschluß für serielle Interfacemodule (IF-Module)<br />
• SPI: Interface für ser. Peripherie Bausteine (parallel I/O, AD/DA-Wandler usw.)<br />
• Timersystem 16 Bit mit 5x Output-Compare, 3x Input-Capture<br />
• 8 Bit AD-Wandler mit 8 Kanälen<br />
• Port Replacement Unit (PRU) MC68HC24<br />
• bis zu 40 digitale Ein-/Ausgänge (abzgl. genutzter Sonderfkt.)<br />
• Steckverbinder für alphanumerische oder grafische LCDs<br />
• steckerkompatibel zu ZWERG11A<br />
Anschluß des "Zwerg 11" an den PC<br />
Belegung des Schnittstellenkabels und des Experimentierboards<br />
Der ZWERG11plus 96
Bootloader Firmware for MC68HC11A8 (essentials)<br />
pddr equ $08<br />
baud equ $2B<br />
sccr2 equ $2D<br />
scsr equ $2E<br />
scdr equ $2F<br />
*<br />
Mikrocomputertechnik<br />
Belegung des Schnittstellenkabels und des Experimentierboards 97
org $BF40<br />
*<br />
main ldx #$1000 init x for indexed access to hardware<br />
ldaa #$A2<br />
staa baud,x restart timer , set baudrate to 7812 Bd<br />
ldaa #$0C<br />
staa sccr2,x enable receiver and transmitter<br />
bset sccr2,x $01 send break to signal start of download to master<br />
wait brset pddr,x $01 wait wait for startbit from master<br />
bclr sccr2,x $01 clear break<br />
char brclr scsr,x $20 char wait for first character from master (RDRF)<br />
ldaa scdr,x read character<br />
bne goon<br />
jmp $B600 start program in internal EEPROM<br />
goon cmpa #$55 test mode ?<br />
beq strt yes, skip download<br />
cmpa #$FF baud rate ok ?<br />
beq bdok yes, goon<br />
bset baud,x $33 change to 1200 Bd<br />
bdok ldy #$000 init pointer<br />
loop brclr scsr,x $20 loop wait for RDRF<br />
ldaa scdr,x get character<br />
staa 0,y store character to RAM<br />
staa scdr,x echo character to master<br />
iny adjust pointer<br />
cpy #$0000 end of area ?<br />
bne loop no, next character<br />
*<br />
strt jmp $0000 start downloaded userprogram<br />
*<br />
org $BFFE<br />
dc.w main start main on RESET (MODA = MODB = 0)<br />
*<br />
end<br />
Zum vorhergehenden Abschnitt Zum Inhaltsverzeichnis Zum nächsten Abschnitt<br />
Copyright © FH München, FB 04, Prof. Jürgen Plate<br />
Mikrocomputertechnik<br />
Mikrocomputertechnik<br />
Prof. Jürgen Plate<br />
Bootloader Firmware for MC68HC11A8 (essentials) 98
5. Peripherie des Systems M68HC11<br />
5.1 Peripherie-Register<br />
Standardlage (default): $1000 - $103F, Verschiebung an jede 4KByte-Grenze möglich<br />
(INIT-Register)<br />
Adresse Register Funktion Adresse Register Funktion<br />
$1000 PORTA port A data $1020 TCTL1<br />
$1001 spare $1021 TCTL2<br />
$1002 PIOC parallel I/O control $1022 TMSK1<br />
$1003 PORTC port C data $1023 TFLG1<br />
$1004 PORTB port B data $1024 TMSK2 timer mask 2<br />
$1005 PORTCL port C latch $1025 TFLG2 timer flag 2<br />
$1006 spare $1026 PACTL pulse accu control<br />
$1007 DDRC port C direction $1027 PACNT pulse accu count<br />
$1008 PORTD port D data $1028 SPCR SPI control<br />
$1009 DDRD port D direction $1029 SPSR SPI status<br />
$100A PORTE port E data $102A spare<br />
$100B CFORC $102B BAUD SCI baud rate<br />
$100C OC1M $102C SCCR1 SCI control 1<br />
$100D OC1D $102D SCCR2 SCI control 2<br />
$100E TCNT timer count high $102E SCSR SCI status<br />
$100F timer count low $102F SCDR SCI data<br />
$1010 TIC1H $1030 ADCTL A/D control<br />
$1011 TIC1L $1031 spare<br />
$1012 TIC2H $1032 spare<br />
$1013 TIC2L $1033 spare<br />
$1014 TIC3H $1034 spare<br />
$1015 TIC3L $1035 spare<br />
$1016 TOC1H $1036 spare<br />
$1017 TOC1L $1037 spare<br />
$1018 TOC2H $1038 spare<br />
$1019 TOC2L $1039 OPTION<br />
$101A TOC3H $103A spare<br />
$101B TOC3L $103B PPROG<br />
$101C TOC4H $103C HPRIO<br />
$101D TOC4L $103D INIT<br />
$101E TOC5H $103E TEST1<br />
5. Peripherie des Systems M68HC11 99
$101F TOC5L $103F CONFIG<br />
Im Rahmen dieser Vorlesung wird nur ein ausgewählter Teil dieser Register und ihrer Funktionen<br />
besprochen. Im folgenden werden einzelne Ports und die zugehörigen Register zur Sprache kommen.<br />
5.2 Parallele Schnittstellen<br />
Beim Informationsaustausch des Controllers mit der "Außenwelt" müssen spezielle Eigenschaften der<br />
Peripheriegeräte berücksichtigt werden. Insbesondere sind die Peripherieeinheiten gegenüber der<br />
Prozessorgeschwindigkeit recht langsam Die Schnittstellen müssen die ein- oder ausgehenden<br />
Daten zwischenspeichern. Zum anderen laufen CPU und Peripherie oft zeitlich asynchron. Eine<br />
weitere Aufgabe von Schnittstellen ist auch die Parallel-seriell-Wandlung (siehe Abschnitt 5.3).<br />
Allgemein gilt für alle Schnittstellen:<br />
• der Datenverkehr zwischen CPU und Schnittstelle läuft meist programmgesteuert (per Polling<br />
oder per Interrupt)<br />
• die "Datenbreite" ist durch den internen Datenbus vorgegeben (8 Bit)<br />
• die Eigenschaften der Schnittstellen lassen sich per Programm einstellen Schnittstelle<br />
programmierbar Initialisierung notwendig<br />
• jeder Schnittstelle sind einige der oben aufgeführten Register zugeordnet. Dabei handelt es<br />
sich um<br />
♦ Register zur Einstellung der Eigenschaften<br />
♦ Register zur Ein- und Ausgabe<br />
Der 68HC11 besitzt fünf parallele Schnittstellen, die Ports A bis E, welche mit unterschiedlichen<br />
Hardware-Eigenschaften ausgestattet sind. Im "expanded Mode" stehen die Ports B und C nicht zur<br />
Verfügung, weil sie für Adreß- und Datenleitungen verwendet werden. Durch einen<br />
Port-Expander-Baustein lassen sie sich aber wieder ergänzen.<br />
Eine kurze Übersicht der Ports:<br />
Mikrocomputertechnik<br />
• Port A: besitzt drei Eingänge vier Ausgänge und eine bidirektionale Leitung. Zusätzlich<br />
verarbeitet er die Signale des Timer-Systems und des Pulse-Akkumulators.<br />
Die Ports B und C werden zusammen mit den Handshakeleitungen STRA und STRB als Einheit<br />
betrachtet.<br />
• Port B: besitzt acht Ausgangsleitungen. Lesen auf Port B liefert die letzten<br />
hineingeschriebenen Daten.<br />
• Port C: hat acht bidirektionale Leitungen. Über ein Datenrichtungsregister kann für jede<br />
Leitung festgelegt werden, ob sie Eingang oder Ausgang sein soll. Ein zusätzliches Latch<br />
speichert den Eingangszustand von Port C bei jeder aktiven Signalflanke auf dem Anschluß<br />
STRA.<br />
• Port D: besitzt sechs bidirektionale Leitungen, die wie bei Port C per Datenrichtungsregister<br />
eingestellt werden können. Die Bits 0 und 1 von Port D werden auch von der seriellen<br />
Schnittstelle verwendet.<br />
• Port E: besitzt acht Eingangsleitungen, die alternativ als analoge Eingänge des<br />
A/D-Wandler-Systems verwendet werden. Beim DIL-Ghäuse stehen sogar nur vier Leitungen<br />
zur Verfügung.<br />
Den fünf Ports sind insgesamt 16 Register zugeordnet (Einstellung und E/A). Die jeweiligen Register<br />
werden bei der Besprechung der einzelnen Ports behandelt.<br />
5.1 Peripherie-Register 100
Port A<br />
Mikrocomputertechnik<br />
Ein- und Ausgabeport mit fester und für ein Bit variabler Datenrichtung.<br />
Der Port kann auf zwei verschiedene Betriebsarten gesetzt werden:<br />
• Steuerbit PEAN = 0: "normale" parallele E/A (Betriebsart 1).<br />
• Steuerbit PEAN = 1: Impuls-Akkumulator (Betriebsart 2). Hier lassen sich entweder Impulse<br />
zählen (PMOD = 0) oder Impulsdauern messen (PMOD = 1).<br />
PAIF set by active edge on PAI, reset by writing a corresponding one to TFLG2<br />
PAOVF set by roll over of PACNT, reset by writing a corresponding one to TFLG2<br />
PAII set and reset by software, generate interrupt, if PAIF is set<br />
PAOVI set and reset by software, generate interrupt, if PAOVF is set<br />
Beim Event Counting Mode (PAMOD=0) werden am PAI Eingang (=PA7) eintreffende Impulse im<br />
pulse accu gezählt.<br />
Beim Gated Time Mode (PAMOD=1) wird die Zeit "gemessen", wie lange der PAI-Eingang im<br />
aktiven Zustand ist. Die Messdauer ergibt sich aus der Anzahl der gezählten Impulse, die aus dem<br />
Port A 101
durch 64 geteilten Systemtakt abgeleitet sind, d.h. die zeitliche Auflösung beträgt 32 ms.<br />
Der Port A bietet mit seinem Pin PAI (= PA7) außerdem die Möglichkeit, Programmunterbrechungen<br />
(Interrupts) auszulösen.<br />
Port B und STRB<br />
Ausgabeport mit fester Datenrichtung<br />
Der Port kann auf zwei verschiedene Betriebsarten gesetzt werden:<br />
• Steuerbit HNDS = 0: "normale" parallele Ausgabe<br />
• Steuerbit HNDS = 1: full handshake mode<br />
Wird im Rahmen dieser Vorlesung nicht besprochen!<br />
Die Programmierung von Port B ist denkbar einfach. Jedes Schreiben auf die Adresse $2004 hat die<br />
Ausgabe des entsprechenden Bitmusters auf den Leitungen von Port B zur Folge.<br />
Port C und STRA<br />
Mikrocomputertechnik<br />
Ein/Ausgabeport mit bitweise wählbarer Datenrichtung. Das Datenrichtungs-"Register" DDRC<br />
(Adresse $1007) legt fest, ob die Bits von Port C Eingangs- oder Ausgangsbits sind (0 = Eingang, 1 =<br />
Ausgang). Daher ist eine Initia-lisierung des Ports durch belegen von DDRC notwendig. Die folgende<br />
Abbildung zeigt das Impulsdiagramm einer typischen Anwendung des STRA-Signals. In der<br />
Abbildung sind auch die Bedingungen beschrieben, die für die einzelnen Steuer- und Statusbits in<br />
PIOC gelten.<br />
Der Port kann auf zwei verschiedene Betriebsarten gesetzt werden:<br />
• Steuerbit HNDS = 0: "normale" parallele Ein- oder Ausgabe<br />
Port B und STRB 102
• Steuerbit HNDS = 1: full handshake mode<br />
Wird im Rahmen dieser Vorlesung nicht besprochen!<br />
Die Leitung STRA wird über die Bits STAI und EGA in PIOC gesteuert. STAI gibt den Interrupt für<br />
die Leitung STRA frei (wird weiter unten behandelt). EGA legt fest, ob STRA auf eine steigende oder<br />
fallende Flanke reagiert. Wird beispielsweise eine Taste an STRA angeschlossen, wird durch deren<br />
Betätigung das Bit STAF in PIOC gesetzt und falls STAI = 1 ist, ein Interrupt ausgelöst. Das Bit<br />
STAF wird durch das Lesen der Adressen PIOC und PORTCL (in dieser Reihenfolge) zurückgesetzt.<br />
Impulsdiagramm einer typischen Anwendung des STRA-Signals<br />
Port D<br />
Mikrocomputertechnik<br />
Ein/Ausgabeport mit bitweise wählbarer Datenrichtung.<br />
Der Port kann auf zwei verschiedene Betriebsarten gesetzt werden:<br />
• Steuerbits SPE = RE = TE = 0: "normale" parallele Ein- oder Ausgabe<br />
Port C und STRA 103
Port E<br />
• 2. Betriebsart: SPI = serial peripheral interface (synchronous) wenn SPE=1 ist oder SCI =<br />
serial communications interface (asynchronous) wenn RE=1 und/oder TE=1 sind.<br />
Wird unter 5.3 besprochen.<br />
Eingabeport mit fester Datenrichtung<br />
Der Port kann auf zwei verschiedene Betriebsarten gesetzt werden:<br />
• "normale" parallele Eingabe, kein Schreiben ins ADCTL-Register<br />
• A/D-Wandlung, Schreiben ins ADCTL-Register - siehe später.<br />
Programmbeispiele<br />
Beispiel 1<br />
Lesen 4 Bit linksbündig von Port C<br />
Ausgeben 4 Bit rechtsbündig auf Port C<br />
Ausgeben 4 Bit rechtsbündig auf Port B mit STRB (high pulse)<br />
Vereinbarungen:<br />
pcdr equ $1003<br />
pcdd equ $1007<br />
pbdr equ $1004<br />
pioc equ $1002<br />
Initialisierung<br />
init ldaa #$0F<br />
Mikrocomputertechnik<br />
Port D 104
Datenverkehr<br />
staa pcdd pc(3:0) = output<br />
ldaa #$01<br />
staa pioc STRB high active<br />
rts<br />
main ldaa pcdr<br />
lsra<br />
lsra<br />
lsra<br />
lsra<br />
staa pcdr<br />
staa pbdr<br />
bra main<br />
Beispiel 2<br />
Warten auf steigende Flanke am Eingang STRA<br />
Vereinbarungen:<br />
pioc equ $1002<br />
pcdl equ $1005<br />
Initialisierung<br />
init ldaa #$02<br />
staa pioc STRA rising edge expected<br />
rts<br />
Daten-Abfrage<br />
.<br />
.<br />
. Alternative<br />
wait ldaa pioc<br />
anda #$02 bita #$02<br />
beq wait beq wait<br />
ldaa pcdl clear STAF-flag<br />
.<br />
.<br />
.<br />
Beispiel 3<br />
Realisieren eines 8-Bit-Zählers auf Port B<br />
(Port B ist zwar ein reiner Ausgabeport, aber mit dem Befehl "inc pcdr" wird Port B erst gelesen und<br />
somit der vorherige Ausgabewert geliefert, dann der Wert erhöht und zurückgeschrieben).<br />
Vereinbarungen:<br />
pbdr equ $1004<br />
Programm:<br />
Mikrocomputertechnik<br />
init clr pbdr Port B = 0<br />
main inc pbdr Increment Port B<br />
ldx #$4000 Warteschleife<br />
delay dex X = X - 1<br />
bne delay solange X > 0 durchlaufe Schleife<br />
Programmbeispiele 105
Beispiel 4<br />
Vereinbarungen:<br />
bra main<br />
portc equ $1003<br />
pcdd equ $1007<br />
Programm:<br />
init ldaa #%11111111<br />
staa pcdd Port C auf Ausgabe setzen (0=in, 1=out)<br />
clra<br />
staa portc Port C = 0<br />
main inca<br />
staa portc hochzählen<br />
ldx #$4000 Warteschleife<br />
delay dex<br />
bne delay<br />
bra main<br />
Beispiel 5<br />
Lichtmuster ausgeben auf LEDs, die an Port C angeschlossen sind.<br />
Vereinbarungen:<br />
portc equ $1003<br />
pcdd equ $1007<br />
Programm:<br />
init ldaa #$FF<br />
staa pcdd Port C auf Ausgabe setzen (0=in, 1=out)<br />
top ldx #TABLE X verweist nun auf die Daten in TABLE<br />
loop ldaa 0,X Tabellenelement lesen<br />
beq top ist das Element 0 --> Tabellenende<br />
* wieder zum Tabellenanfang<br />
staa portc Tabellenelement ausgeben<br />
bsr delay Warteschleife aufrufen<br />
inx naechstes Tabellenelement<br />
bra loop usw.<br />
*<br />
delay ldx #$4000 Warteschleife, diesmal als Unterprogramm<br />
dela1 dex<br />
bne dela1<br />
rts<br />
*<br />
TABLE dc.b $01, $02, $04, $08, $10, $20, $40, $80<br />
dc.b $40, $20, $10, $08, $04, $02, $00<br />
Beispiel 6<br />
Lesen Port E, ausgeben auf Port B<br />
Vereinbarungen:<br />
pbdr equ $1004<br />
pedr equ $100A<br />
Mikrocomputertechnik<br />
Programmbeispiele 106
Programm:<br />
main ldaa pedr<br />
staa pbdr<br />
bra main<br />
5.3 Serielle Schnittstellen<br />
Die SCI-Schnittstelle (serial communication interface asynchronous) ist ein Port mit langsamer,<br />
asynchroner serieller Datenübertragung (bis etwa 100 kbit/s). Mit einem Pegelwandler kann sie als<br />
RS232-Schnittstelle verwendet werden. Sie entspricht in ihrer Funktion der seriellen Schnittstelle des<br />
PC.<br />
Die SPI-Schnittstelle ist eine synchrone serielle Peripherieschnittstelle (serial peripheral interface). Sie<br />
dient zum Datenaustausch mit einem anderen Mikrocontroller oder mit Peripheriebausteinen.<br />
Beide Schnittstellen verwenden einige Pins von Port D, die dann nicht mehr als Parallelport-Pins zur<br />
Verfügung stehen. Für eine allgemeine Einführung in die <strong>Assembler</strong>programmierung ist es nicht<br />
notwendig, alle Schnittstellen des 68HC11 zu besprechen. Daher wird nur die asynchrone serielle<br />
SCI-Schnittstelle behandelt.<br />
SCI (serial communication interface asynchronous)<br />
Port mit langsamer, asynchroner serieller Datenübertragung (bis etwa 100 kHz)<br />
Um die Schnittstelle mit der Außenwelt zu verbinden, werden die beiden niederwertigen Bits des<br />
Ports D verwendet. Für die Freigabe der Signale nach außen müssen im Register SCCR2 die Bits RE<br />
(Empfang) und TE (Senden) auf 1 gesetzt werden.<br />
Puffer und Statusbits<br />
Statusbits:<br />
Mikrocomputertechnik<br />
5.3 Serielle Schnittstellen 107
• RDRF (receive data register full): Wird gesetzt, wenn ein Zeichen vom<br />
Empfangsschieberegister ins Register SCDR übertragen wird. Wird zurückgesetzt durch<br />
Lesen von SCSR und danach Lesen von SCDR.<br />
• TDRE (transmit data register empty): Wird gesetzt, wenn ein Zeichen vom Register SCDR ins<br />
Sendeschieberegister übertragen wird. Wird zurückgesetzt durch Lesen von SCSR und danach<br />
Schreiben von SCDR.<br />
• TC (transmission complete): Wird gesetzt, wenn ein Zeichen komplett aus dem<br />
Sendeschieberegister herausgeschoben wurde. Wird zurückgesetzt durch Lesen von SCSR<br />
und danach Schreiben von SCDR.<br />
Empfangs-Funktion:<br />
Die Steuerungslogik erkennt ein seriell ankommendes Zeichen und schiebt es im eingestellten Takt ins<br />
Empfangs-Schieberegister (Receive Data Register, RDR). Sobald das Zeichen vollständig im<br />
Schieberegister steht, wird es parallel ins Empfangsregister kopiert; gleichzeitig wird im Statusregister<br />
(SCSR) das Bit 5 (Receive Data Register Full, RDRF) auf 1 gesetzt. Falls im Steuerregister (SCCR2)<br />
der Empfangsinterrupt zugelassen wurde (Receive Interrupt Enable, RIE), wird auch noch ein<br />
SCI-Interrupt erzeugt.<br />
Das sofortige Kopieren eines Zeichens vom Schieberegister ins Empfangsregister (SCDR) ist<br />
notwendig, damit ein eventuell unmittelbar nachfolgendes serielles Zeichen nicht das vorherige<br />
überschreibt. Allerdings muß das Empfangsregister bis spätestens unmittelbar vor dem nächsten<br />
Kopieren vom Prozessor gelesen werden, denn sonst geht dieses Zeichen durch Überschreiben<br />
verloren. Die Steuerung erkennt ein solches Überschreiben und setzt dann das Bit 3 im Statusregister<br />
(SCSR): Overrun Error (OR). Der Zeitabstand, in dem Zeichen eintreffen können, hängt von der<br />
Baudrate ab, z. B. beträgt der Zeichenabstand bei 9600 Baud ca. 1 ms.<br />
Sende-Funktion:<br />
Wird ein Zeichen ins Senderegister geschrieben, so prüft die Steuerlogik, ob das<br />
Sende-Schieberegister frei ist, um es dann dorthin zu kopieren und den Schiebevorgang zu starten.<br />
Damit ist das Senderegister wieder frei und es kann erneut per Store-Befehl beschrieben werden<br />
(nächstes Zeichen). Die Tatsache, daß dieses Schreiben erlaubt ist, signalisiert das Bit 8 (Transmit<br />
Data Register Empty, TDRE) des Statusregisters (SCSR) mit einer 1. Auch hier kann ein<br />
SCI-Interrupt ausgelöst werden, wenn im Steuerregister der Sende-Interrupt per TIE-Bit = 1 (Transmit<br />
Interrupt Enable) freigegeben ist. In manchen Fällen kann auch noch das tatsächliche Ende des<br />
Schiebevorgängs von Interesse sein (Transmission complete). Für diesen Zweck gibt es auch noch die<br />
Möglichkeit, diese Tatsache sowohl am entsprechenden Statusbit (TC) zu erkennen bzw. durch einen<br />
Interrupt melden zu lassen.<br />
Serielles Rahmenformat:<br />
Idle: Im Ruhezustand ist die Leitung auf auf 1-Pegel.<br />
Beim Datenformat von 9 Bit (M = 1) ist das neunte Bit im Register SCCR1 zu finden. Beim Wert M<br />
= 0 werden 8 Bit empfangen/gesendet (Normalfall).<br />
Setzen der Datenrate<br />
Mikrocomputertechnik<br />
Die Erzeugung der Datenrate erfolgt mehrstufig und ist daher etwas komplex. Es spielen dabei vier<br />
Teiler für die Taktfrequenz (in der Regel 8 MHz) zusammen (Register BAUD):<br />
SCI (serial communication interface asynchronous) 108
Der Takt gelangt erst in einen Prescaler mit vier möglichen Divisionsfaktoren (1, 3, 4, 13), dessen<br />
Output dann nochmals durch acht Divisoren geteilt werden kann. Bei einer Taktrate von 8 MHz lassen<br />
sich folgende Raten wählen (Einstellungen für das Praktikumssystem farbig hinterlegt):<br />
Neben den beiden schon erwähnten Bits TE und RE sind im Register SCCR2 die Steuerbits für die<br />
Interruptfreigabe enthalten.<br />
interrupt masks (set and reset by software)<br />
Mikrocomputertechnik<br />
• RIE receive interrupt enable, generate IRQ, if RDRF is set<br />
• TIE transmit interrupt enable, generate IRQ, if TDRE is set<br />
• TCIE tx complete interrupt enable, generate IRQ, if TC is set<br />
• ILIE idle-line interrupt enable, generate IRQ, if IDLE is set<br />
Das SCI-Statusregister SCSR liefert Informationen über den Ablauf der Kommunikation. Die<br />
Fehlerflags werden zurückgesetzt durch das Lesen von SCSR und SCDR.<br />
SCI (serial communication interface asynchronous) 109
error flags (set by hardware, reset by reading SCSR and SCDR)<br />
• OR overrun error char received and previously received char not yet read<br />
• NF noise flag data recovery logic detected noise during reception<br />
• FE framing error no logic high, when stop bit is expected<br />
SPI (serial peripherial interface synchronous)<br />
Port mit schneller, synchroner serieller Datenübertragung (bis etwa 2 MHz).<br />
Wird im Rahmen dieser Vorlesung nicht besprochen.<br />
Programmbeispiele<br />
Beispiel 1:<br />
Serielles Senden und Empfangen von Zeichen mit 9600 Bd<br />
Vereinbarungen:<br />
scdr equ $102F<br />
scsr equ $102E<br />
baud equ $102B<br />
sccr1 equ $102C<br />
sccr2 equ $102D<br />
Einstellungen:<br />
init ldaa #$30<br />
staa baud baudrate = 9600 bit/s<br />
ldaa #0<br />
staa sccr1<br />
ldaa #$0C<br />
staa sccr2 enable transmit & receive<br />
rts<br />
Datenverkehr:<br />
* Zeichen in Speichezelle "char" ausgeben<br />
chou ldaa char<br />
ldab scsr Sendereg. leer?<br />
andb #$80<br />
beq chou<br />
staa scdr transmit<br />
rts<br />
Mikrocomputertechnik<br />
* Zeichen nach Speicherzelle "char" einlesen<br />
chin ldab scsr Empfangsreg. leer?<br />
andb #$20<br />
SPI (serial peripherial interface synchronous) 110
Sendeschleife:<br />
beq chin<br />
ldaa scdr receive<br />
staa char<br />
rts<br />
main bsr init<br />
loop bsr chin "Schreibmaschine"<br />
bsr chout<br />
bra loop<br />
Beispiel 2:<br />
Serielles Senden von Zeichenketten mit 9600 Bd<br />
Vereinbarungen:<br />
scdr equ $102F<br />
scsr equ $102E<br />
baud equ $102B<br />
sccr1 equ $102C<br />
sccr2 equ $102D<br />
Einstellungen:<br />
init ldaa #$30<br />
staa baud baudrate = 9600 bit/s<br />
ldaa #0<br />
staa sccr1<br />
ldaa #$0C<br />
staa sccr2 enable transmit & receive<br />
rts<br />
Zeichen in Akku A ausgeben:<br />
chou ldab scsr Sendereg. leer?<br />
bpl chou<br />
staa scdr transmit<br />
rts<br />
Zeichenkette senden: Die Adresse der Zeichenkette wird in X übergeben, Ende der Zeichenkette wird<br />
durch ETX markiert definiert durch: ETX EQU 3.<br />
saus ldaa 0,x Zeichen holen<br />
cmpa #ETX ETX (3) ?<br />
beq saus_e dann fertig<br />
inx X inkrementieren<br />
bsr chou Zeichen senden<br />
bra saus und nächstes Zeichen<br />
saus_e rts<br />
Sendeschleife:<br />
Mikrocomputertechnik<br />
main bsr init<br />
loop ldx #TEXT<br />
bsr saus<br />
bra loop<br />
*<br />
TEXT dc.b 'Hello World' Meldungstext<br />
dc.b $0D,$0A,ETX Zeilenvorschub, ETX<br />
Programmbeispiele 111
Beispiel 3:<br />
Serielles Senden und Empfangen von Zeichenketten mit 9600 Bd<br />
Vereinbarungen: - siehe oben -<br />
Einstellungen: - siehe oben -<br />
Zeichen in Akku A ausgeben: - siehe oben -<br />
Zeichenkette senden: - siehe oben -<br />
Zeichen nach Akku A einlesen<br />
chin ldab scsr Empfangsreg. leer?<br />
andb #$20<br />
beq chin<br />
ldaa scdr receive<br />
rts<br />
Zeichenkette einlesen: Die Adresse eines Eingabepuffers wird in X übergeben. Das Eingabeende wird<br />
durch die Taste Carriage-Return (CR, $0D) signalisiert.<br />
sein bsr chin Zeichen einlesen<br />
cmpa #$0D Carriage Return?<br />
beq sein_e ja, Ende<br />
staa 0,x Zeichen im Puffer speichern<br />
inx X inkrementieren<br />
bra sein und nächstes<br />
sein_e ldaa #ETX ETX anhängen (CR wird nicht mit gesp.)<br />
staa 0,x<br />
rts<br />
Sendeschleife:<br />
main bsr init<br />
loop ldx #PUF<br />
bsr sein<br />
ldx #PUF<br />
bsr saus<br />
bra loop<br />
Irgendwo im Programm wird ein Puffer definiert, z. B.:<br />
org data<br />
PUF ds.b 80 80 Bytes Puffer reservieren<br />
Anmerkung: "sein" überprüft nicht, ob der maximale Pufferbereich überschritten wird und so<br />
eventuell andere Variablen überschrieben werden. Versuchen Sie, eine Begrenzung der Eingabe auf z.<br />
B. 80 Zeichen zu programmieren.<br />
Beispiel 4: Kommandoauswertung. Es wird ein Befehlsbuchstabe von der seriellen Schnittstelle<br />
eingelesen und verarbeitet. Es sind die Buchstaben 'a', 'b' und 'c' erlaubt - bei anderen Eingaben erfolgt<br />
eine Fehlermeldung. Als Pseudo-Aktion dient das Unterprogramm "doit", es gibt lediglich den<br />
eingegebenen Buchstaben als Grossbuchstaben aus.<br />
prog equ $8000<br />
data equ $2000<br />
stack equ $7FFF<br />
Mikrocomputertechnik<br />
Programmbeispiele 112
scdr equ $102f<br />
scsr equ $102e<br />
sccr1 equ $102c<br />
sccr2 equ $102d<br />
baud equ $102b<br />
reset equ $fffe<br />
cr equ 13<br />
lf equ 10<br />
org data<br />
buf ds.b 100 ; Eingabepuffer<br />
Mikrocomputertechnik<br />
org prog<br />
main lds #stack ; Stackpinter setzen<br />
bsr sini ; Schnittstelle init.<br />
loop ldx #hello ; Prompt ausgeben<br />
bsr saus<br />
bsr chin ; Taste einlesen<br />
cmpa #'a' ; ist es 'a'?<br />
bne next1 ; nein, weiter<br />
bsr doit ; Dummy-Aktion<br />
bra loop ; und weiter<br />
next1 cmpa #'b' ; ist es 'b'?<br />
bne next2 ; wie oben<br />
bsr doit<br />
bra loop<br />
next2 cmpa #'c' ; ist es 'c'?<br />
bne next3 ; wie oben<br />
bsr doit<br />
bra loop<br />
next3 ldx #oops ; keine erlaubte Taste<br />
bsr saus ; Fehlermeldung ausgeben<br />
bra loop<br />
doit ; Dummy-Aktion<br />
psha ; Akku A retten<br />
ldx #k1 ; Text ausgeben<br />
bsr saus<br />
pula ; Akku wieder holen (eingeg. Zeichen)<br />
suba #$20 ; in Grossbuchstaben umwandeln<br />
bsr chou ; und ausgeben<br />
bsr crlf ; neue Zeile<br />
rts<br />
crlf ldaa #cr ; Carriage Return, Line Feed ausgeben<br />
bsr chou<br />
ldaa #lf<br />
bsr chou<br />
rts<br />
saus ldaa 0,x ; Stingausgabe, siehe oben<br />
beq sfin<br />
bsr chou<br />
inx<br />
bra saus<br />
sfin rts<br />
sini clr sccr1 ; Schnittstelle initialisieren, siehe oben<br />
ldaa #$0C<br />
staa sccr2<br />
ldaa #$30<br />
staa baud<br />
rts<br />
Programmbeispiele 113
chou ldab scsr ; Zeichen ausgeben, siehe oben<br />
bpl chou<br />
staa scdr<br />
rts<br />
chin ldab scsr ; Zeichen einlesen, siehe oben<br />
andb #$20<br />
beq chin<br />
ldaa scdr<br />
rts<br />
; Zeichenkettenkonstante<br />
hello dc.b 'Cmd: ' ; Kommandoprompt<br />
dc.b 0<br />
oops dc.b 'Oops!' ; Fehlermeldung<br />
dc.b cr,lf,0<br />
k1 dc.b 'Eingabe war ' ; fuer Dummy-Aktion<br />
dc.b 0<br />
5.4 Zähler<br />
org reset ; Reset-Vektor<br />
fdb main<br />
end<br />
Mikrocomputertechnik<br />
Das Timer-System steuert Funktionen, die einen Bezug zur Echtzeit benötigen, also unabhängig von<br />
Befehlsausführungszeiten sein sollen:<br />
• Der Real-Time-Interrupt (Echtzeitunterbrechung) dient dem Zweck, in genau periodischen<br />
Zeitabständen einen bestimmten Vorgang auszulösen.<br />
• Die drei Input-Capture-Funktionen (Zeiterfassungsfunktionen) IC1 bis IC3 dienen zur<br />
Zeitmessung von Eingangssignalen an den Eingangspins PA0 bis PA2.<br />
• Mit den vier Output-Compare-Funktionen (Zeitvergleichsfunktionen) OC1 bis OC4 können<br />
bei bestimmten Timer-Zählerständen 1-Pegel oder 0-Pegel an den Ausgangspins PA3 bis PA6<br />
ausgegeben werden.<br />
• Der COP-Watchdog-Timer sorgt dafür, dass die Programmlaufüberwachung innerhalb einer<br />
überwachungsperiode rechtzeitig zurückgesetzt wird. Im Fehlerfall wird ein Reset (Neustart)<br />
des Rechners veranlasst.<br />
Der 68HC11 hat eine recht komplexe Timer-Struktur, die mit Abstand die meisten Register im<br />
E/A-Bereich belegt. Entsprechend komplex ist seine Programmierung.<br />
5.4 Zähler 114
Basis des Timersystems ist ein konstant durchlaufender, nicht beeinflussbarer 16-Bit-Zähler, der im<br />
Register TCNT abgebildet ist. Das Timersystem leitet seinen Takt über Teiler vom Quarztakt ab<br />
(Abbildung 31). Die folgenden Zeitangaben beziehen sich auf eine Quarzfrequenz von 8 MHz, was<br />
einem CPU-Takt von 2 MHz entspricht. Der Vorteiler für den freilaufenden 16-Bit-Zähler wird durch<br />
die Bits PR0/PR1 im Register TMSK2 programmiert. Die folgende Tabelle zeigt, mit welchen<br />
Taktperioden der Zähler dann getriggert wird.<br />
Die beiden Vorteiler werden durch die Bits PR0/PR1 im Register TMSK2 und RTR0/RTR1 im<br />
Register PACTL programmiert. Nach einem RESET steht hier jeweils ein Wert von 0, so daß die<br />
höchste Taktrate ausgewählt ist. Diese beiden Bits können nur direkt nach einem RESET verändert<br />
werden, danach ist jeder weitere Zugriff gesperrt. Diese besondere Eigenschaft des Mikroprozessors<br />
68HC11 verhindert ungewollte Veränderungen an der Timer-Auflösung durch unzulässige Zugriffe,<br />
die während des Betriebs durch Störimpulse von außen ausgelöst werden könnten.<br />
PRn<br />
1 0<br />
division<br />
factor<br />
output<br />
period<br />
0 0 1 32.77<br />
ms<br />
0 1 4 131.07<br />
ms<br />
1 0 8 262.14<br />
ms<br />
1 1 16 524.29<br />
ms<br />
Mikrocomputertechnik<br />
RTRn<br />
1 0<br />
division<br />
factor<br />
output<br />
period<br />
0 0 1 4.096<br />
ms<br />
0 1 2 8.192<br />
ms<br />
1 0 4 16.384<br />
ms<br />
1 1 8 32.768<br />
ms<br />
5.4 Zähler 115
TOF timer overflow<br />
flag<br />
TOI timer overflow<br />
interrupt enable<br />
RTIF real time interrupt<br />
flag<br />
RTII real time interrupt<br />
enable<br />
Der Timer<br />
Wird gesetzt, wenn der frei laufende 16-Bit-Zähler von FFFF auf 0<br />
wechselt (Zählerüberlauf). Wird zurückgesetzt durch Schreiben einer 1<br />
in TOF.<br />
Interruptfreigabe für "Timer Overflow Interrupt", 0 = Interrupt gesperrt,<br />
1 = Interrupt freigegeben.<br />
Wird gesetzt, wenn der Realtime-Interrupt-Zähler auf 0 wechselt<br />
(Zählerüberlauf). Wird zurückgesetzt durch Schreiben einer 1 in RTIF.<br />
Interruptfreigabe für "Realtime Interrupt", 0 = Interrupt gesperrt, 1 =<br />
Interrupt freigegeben.<br />
Der Timer des 68HC11 besitzt eine Länge von 16 Bit. Aus diesem Grund muß er mit einem<br />
16-Bit-Ladebefehl gelesen werden, da nur dann die beiden Bytes des Ergebnisses wirklich zusammen<br />
gehören. Würden das obere und das untere Byte getrennt voneinander gelesen, bestände kein<br />
eindeutiger Zusammenhang.<br />
Nach einem Reset der CPU ist der Zählerstand des Timers 0. Es gibt keine Möglichkeit, den<br />
Zählerstand des Timers auf einen bestimmten Wert zu setzen. Direkt nach dem Reset beginnt der<br />
Timer aufwärts zu zählen. Bei jedem Überlauf von $FFFF auf $0000 wird das Überlauf-Bit TOF<br />
(Timer Overflow) im Register TFLG2 gesetzt, um diesen Zustand anzuzeigen. Die Anwendersoftware<br />
kann so auf einfache Weise eine Kaskadierung des Timers auf beliebige Wortlänge durchführen, da<br />
dieses Bit auch einen Interrupt auslösen kann.<br />
Für die meisten Anwendungsfälle ist es sinnvoll, die längste zu messende Zeit zu bestimmen und dann<br />
den Vorteiler so zu definieren, daß innerhalb dieser Zeit kein Timer-Überlauf auftreten kann. Alle<br />
Zeitpunktberechnungen können dann mit einfacher 16-Bit-Arithmetik durchgeführt werden. Man darf<br />
nicht übersehen, daß das Timer-System mit 16 Bit auflöst, der Fehler bezogen auf eine Periode ist<br />
1/65536 entsprechend 0,0015 %. Diese Genauigkeit ist für fast alle Anwendungen ausreichend. Erhöht<br />
man die Taktrate des Timer-Systems und arbeitet mit höherer Auflösung, dann addieren sich<br />
Software-Reaktionszeiten, was häufig zu wesentlich größeren Fehlern führen.<br />
Bei jedem Überlauf des Timers von $FFFF auf $0000 wird das Überlauf-Bit (TOF = Timer Overflow<br />
Flag) im TFLG2-Register gesetzt. Das TOF-Bit muß vom Anwenderprogramm gezielt wieder<br />
gelöscht werden. Wird das Auslösen eines Interrupts bei jedem Timer-Oberlauf gewünscht, dann kann<br />
das zum TOF-Bit korrespondierende TOI-Bit (Timer Overflow Interrupt) im TFLG2-Register auf 1<br />
gesetzt werden.<br />
Der frei laufende Timer<br />
Mikrocomputertechnik<br />
Der frei laufende Haupt-Timer des 68HC11 wird bei Reset auf 0 gesetzt und beginnt dann zu laufen.<br />
Derartige Timer findet man auch bei fast jedem anderen Controller. Der Zählerstand kann über ein<br />
16-Bit-Register auf den Adressen $100E und $100F ausgelesen werden. Wichtig ist hierbei, dass<br />
mittels einer 16-Bit-Operation gelesen wird (LDD). Würde man zwei aufeinander folgende<br />
8-Bit-Operationen zum Lesen nehmen (LDAA, LDAB), bekäme man einen "Versatz" von vier<br />
Taktzyklen, da die Ladeoperation so lange dauert.<br />
Der Haupt-Timer läuft nach dem Einschalten mit dem E-Takt der CPU. Der Takt kann noch durch<br />
einen Prescaler geteilt werden, wobei die Faktoren 1, 4, 8 oder 16 möglich sind. Der Teilfaktor wird<br />
über die Bits 0 und 1 des TMASK-Registers eingestellt. Das folgende Programm illustriert den<br />
Sachverhalt, indem der Timer ständig ausgelesen und auf den Ports B und C ausgegeben wird.<br />
Der Timer 116
data equ $2000 ; Datenbereich<br />
prog equ $8000 ; Programmbereich<br />
stack equ $7FFF ; Stackbereich<br />
tirqv equ $FFDE ; Adresse TOF-Vektor<br />
resetv equ $FFFE ; Adresse Reset-Vektor<br />
pcdd equ $1007 ; Adressen Port C<br />
pcdr equ $1003<br />
portb equ $1004 ; Adresse Port B<br />
pacr equ $1026 ; Pulse Akku Control<br />
tflag equ $1025 ; Timer Flag<br />
tmask equ $1024 ; Timer Mask<br />
tcnt equ $100e ; Timer Counter<br />
org data<br />
org prog<br />
main lds #stack ; Init Stack<br />
ldab #$FF ; Port C auf Ausgang<br />
stab pcdd<br />
ldab #$03 ; Timer-Prescaler / 16<br />
stab tmask ; --> 524,3 ms<br />
loop ldd tcnt ; Zaehler laden HIGH in A,<br />
; LOW in B<br />
staa portb ; ausgeben<br />
stab pcdr<br />
bra loop<br />
org resetv ; Reset-Vektor setzen<br />
fdb main<br />
Real-Time-Interrupt<br />
Häufig wird in einem Mikroprozessorprogramm eine feste Zeitbasis zur Steuerung bestimmter<br />
Abläufe benötigt. Dafür besitzt der 68HC11 einen speziellen Real-Time-Interrupt, der von den Bits<br />
RTII im Register TMSK2 und RTIF im Register TFLG2 gesteuert wird. Nach Ablauf einer<br />
vordefinierten Zeitspanne wird das Bit RTIF im TFLG2-Register gesetzt. Zur Auslösung eines<br />
Interrupts muß auch hier das korrespondierende RTII-Bit im TMSK2-Register auf 1 gesetzt sein. Das<br />
RTIF-Bit muß zwingend vom Interrupt-Programm durch Schreiben einer 1 an diese Stelle wieder<br />
gelöscht werden, da sonst sofort der nächste Interrupt ausgelöst würde. Die Periodendauer des<br />
Real-Time-Interrupts wird über zwei Bits im PACTL-Register vorgesehen (RTRO und RTR1)<br />
eingestellt.<br />
Beispiel: Uhrentakt mittels RTI<br />
(Quelle: Wallrabe: Mikrocontrollerpraxis, Hanser Verlag)<br />
Dazu gehen wir von der kürzesten Grundperiode 4,096 ms aus, da sie die feinste Stufung erlaubt. Als<br />
Anfangsstand des Zählers wählen wir 244. Die so erzeugte Periode dauert somit 244 - 4,096 ms =<br />
999,424 ms. An der genauen Sekunde fehlen 0,576 ms, ein Fehler, der toleriert werden kann. Nach<br />
diesen Vorgaben ist das folgende Beispiel aufgebaut, das, vom Anfangswert 244 ausgehend, nach<br />
jedem RTI-Interrupt die Variable RTIZaehl herunterzählt und bei Erreichen von 0 einen Sekunden-,<br />
Minuten- und Stundenzähler hochzählt.<br />
Die Zeitwerte sollen natürlich dezimal und nicht binär (hexadezimal) ausgegeben werden. Daher wird<br />
nach jedem Inkrementieren eines Zählers dessen Wert mit dem Befehl DAA sofort in einen<br />
BCD-Wert umgewandelt und auch so abgespeichert.<br />
Voraussetzung ist, daß im Hauptprogramm folgende RAM-Variablen vorab definiert und initialisiert<br />
worden sind:<br />
RTIZaehl = Adresse des RTI-Zählers<br />
SekZaehl = Adresse des Sekunden-Zählers<br />
Mikrocomputertechnik<br />
Der Timer 117
MinZaehl = Adresse des Minuten-Zählers<br />
StdZaehl = Adresse des Stunden-Zählers<br />
Sek_alt = Zwischenspeicher<br />
Mikrocomputertechnik<br />
UHR DEC RTIZaehl RTI-Zähler dekrementieren.<br />
BNE UHR_E<br />
LDAA #244 Wenn RTI-Zähler = 0:<br />
STAA RTIZaehl Neu mit Ausgangswert laden.<br />
LDAA SekZaehl Nach 1 Sekunde:<br />
INCA Sekundenzähler hochzählen,<br />
DAA in BCD-Zahl wandeln.<br />
STAA SekZaehl<br />
CMPA #$60<br />
BNE UHR_E<br />
CLRB Nach 60 Sekunden:<br />
STAB SekZaehl Sekundenzähler auf 0 setzen,<br />
LDAA MinZaehl Minutenzähler hochzählen,<br />
INCA<br />
DAA<br />
STAA MinZaehl<br />
CMPA #$60<br />
BNE UHR_E Nach 60 Minuten:<br />
STAB MinZaehl Minutenzähler auf 0 setzen,<br />
LDAA StdZaehl Stundenzähler hochzählen,<br />
INCA<br />
DAA<br />
STAA StdZaehl<br />
CMPA #$24<br />
BNE UHR_E Nach 24 Stunden:<br />
STAB StdZaehl Stundenzähler auf 0.<br />
UHR_E LDAA #$40 Rücksetzen des RTI-Flags.<br />
STAA TFLG2<br />
RTI<br />
Diese Uhr tickt unsichtbar und lautlos im Inneren des 68HC11. Daher wird das Unterprogramm zu<br />
einem kompletten lauffähigen Beispielprogramm erweitert, bei dem die Zeit über die serielle<br />
Schnittstelle an den PC gesendet und Monitor sichtbar gemacht wird. Das Programm beginnt mit<br />
einem Initialisierungsteil, in dem die serielle Schnittstelle und der RTI-Interrupt vorbereitet sowie die<br />
Variablen auf ihre Ausgangswerte gesetzt werden.<br />
VECRTI equ $FFEB Real Time Interrupt<br />
TMSK2 equ $1024 Timer Interrupt Mask Reg.2<br />
SCSR equ $102e SCI Status Reg.<br />
SCDR equ $102f SCI Data Reg.<br />
BSR INIT_SCI Schnittstelle Init, siehe 5.3<br />
LDD #UHR<br />
STD VECRTI ...RTI-Serviceroutine "UHR".<br />
LDAA #$40 RTI-Interrupt freigeben.<br />
STAA TMSK2 (4,096 ms ungeaendert wie Vorgabe).<br />
LDAA #244 RTI-Zaehler<br />
STAA RTIZaehl auf Ausgangswert setzen.<br />
CLRB Ebenso...<br />
STAB SekZaehl ...Sekunden-Zaehler<br />
STAB Sek_alt ...Sekunden-Vergleichszaehler<br />
STAB MinZaehl ...Minuten-Zaehler<br />
STAB StdZaehl ...Stunden-Zaehler<br />
CLI Interrupts aktivieren<br />
UhrStart LDAA SekZaehl Warten, bis Sekunde einen neuen...<br />
CMPA Sek_alt<br />
BEQ UhrStart ...Wert hat.<br />
STAA Sek_alt Neuen Wert in Vergleichszaehler<br />
Der Timer 118
LDAA StdZaehl Stunden ausgeben<br />
JSR Hex_Tx<br />
LDAA #":" Trennzeichen ":" ausgeben<br />
JSR Byte_Tx<br />
LDAA MinZaehl Minuten ausgeben<br />
JSR Hex_Tx<br />
LDAA #":"<br />
JSR Byte_Tx<br />
LDAA SekZaehl Sekunden ausgeben<br />
JSR Hex_Tx<br />
LDAA #$0D Carriage Return ausgeben<br />
JSR Byte_Tx<br />
BRA UhrStart<br />
* Ausgabe eines Bytes hexadezimal ueber die serielle Schnittstelle<br />
* Das zu sendende Byte muî im Akku A vorliegen.<br />
Hex_Tx PSHA Zu sendendes Byte retten.<br />
ANDA #$F0 Hw.-Nibble abtrennen<br />
LSRA und 4 Stellen nach rechts schieben,<br />
LSRA dabei Nullen nachziehen.<br />
LSRA<br />
LSRA<br />
CMPA #9 0 bis 9 oder A bis F ?<br />
BHI Buchst1<br />
Ziff1 ADDA #"0" 0 bis 9.<br />
JSR Byte_Tx Zum Sender.<br />
BRA Nibble2<br />
Buchst1 ADDA #"A" A bis F.<br />
JSR Byte_Tx<br />
Nibble2 PULA Byte wieder holen.<br />
ANDA #$0F Nw.-Nibble abtrennen.<br />
CMPA #9<br />
BHI Buchst2<br />
Ziff2 ADDA #"0"<br />
JSR Byte_Tx<br />
RTS<br />
Buchst2 ADDA #"A"<br />
JSR Byte_Tx<br />
RTS<br />
* Ausgabe eines Bytes ueber die serielle Schnittstelle<br />
* Das zu sendende Byte muî im Akku A vorliegen.<br />
Byte_Tx LDAB SCSR Statusregister TDRE abfragen, ob leer.<br />
ANDB #$80<br />
BEQ Byte_Tx Abfrage wiederholen, wenn nicht.<br />
STAA SCDR Byte ausgeben.<br />
RTS<br />
Input Capture und Output Compare<br />
Mikrocomputertechnik<br />
Der Zählerstand kann von drei Input-Capture-Registern zur exakten Bestimmung des Zeitpunktes<br />
einer extern erkannten Flanke und von fünf Output-Compare-Registern zur Erzeugung exakter<br />
Impulse und Kurvenformen ausgewertet werden.<br />
Der Timer 119
Mikrocomputertechnik<br />
• Input Capture: Der Zählerstand des freilaufenden 16-Bit-Zählers wird als Echtzeitreferenz<br />
betrachtet, jede von der entsprechend programmierten Prozessorhardware erkannte Flanke<br />
eines extemen Signals speichert den aktuellen Stand dieses Zählers und damit den genauen<br />
Zeitpunkt in einem der Input-Capture-Register. Auf diese Weise ist es möglich, aus zwei<br />
aufeinanderfolgenden Impulsflanken eines Signals die Periodendauer als Differenz der<br />
Zeitpunkte zu bestimmen. Impulsbreiten können durch Verändern der aktiven Flanke nach<br />
Eintreten des ersten Ereignisses bestimmt werden.<br />
Jede einzelne Input-Capture-Funktion beinhaltet ein 16-Bit-Latch, in dem der Zeitpunkt eines<br />
Ereignisses festgehalten werden kann. Die notwendige Synchronisation zwischen<br />
asynchronem externen Ereignis und internem E-Takt wird von der Prozessor-Hardware<br />
unsichtbar für den Anwender vorgenommen. Der hierdurch entstehende Fehler ist klein gegen<br />
die Timer-Auflösung.<br />
Der Transfer des Timer-Inhalts in eines der Input-Capture-Register erfolgt bei der<br />
nichtzählenden Flanke des Timer-Signals, so daß ein sicherer Wert auf jeden Fall garantiert<br />
werden kann. Die Hardware zur Übertragung des Timer-Inhaltes ist für jedes<br />
Input-Capture-Register getrennt vorhanden, so daß es erlaubt ist, alle drei<br />
Input-Capture-Eingänge gleichzeitig zu triggern. Das Auslesen eines der<br />
Input-Capture-Register T1C1 bis T1C3 muß mit einem 16-Bit-Zugriff erfolgen, da nur so<br />
gewährleistet ist, daß die beiden Bytes des Ergebnisses wirklich zusammengehören. Wird der<br />
Inhalt eines der Input-Capture-Register nicht gelesen und tritt dann ein weiteres Ereignis ein,<br />
so wird der alte Wert überschrieben. Der Inhalt dieser Register repräsentiert also immer das<br />
letzte aufgetretene Ereignis. Je ein Bit im TMSK1- und TFLG1-Register sind als Schnittstelle<br />
zum Anwenderprogramm vorgesehen.<br />
Der Timer 120
Die Bits IC1F bis IC3F werden vom Mikroprozessor gesetzt, wenn einer der drei<br />
Input-Capture-Kanäle ein Ereignis registriert. Die zugehörigen Bits IC1I bis IC3I sind jeweils<br />
zur Freigabe eines Interrupts als Reaktion vorgesehen und müssen vom Anwenderprogramm<br />
definiert werden.<br />
Jeder der drei Kanäle kann auf verschiedene Flanken programmiert werden. Dazu sind im<br />
Register TCTL2 jeweils 2 Bit pro Capture-Kanal vorgesehen:<br />
EDGxB EDGxA Aktivierte Flanke<br />
0 0 Keine, Kanal ausgeschaltet<br />
0 1 Ansteigende Flanke<br />
1 0 Abfallende Flanke<br />
1 1 Beide Flanken<br />
Das folgende Programm verwendet die Input-Capture-Register, im die Periodendauer eines<br />
Signals zu messen. Das Signal ist am niederwertigen Kanal 0 (IC1) angeschlossen. Das erste<br />
Beispiel arbeitet im Polling Mode: Es wird bei der Initialisierung festgelegt, ob auf steigende<br />
oder fallende Flanke reagiert werden soll - in diesem Fall wurde die steigende Flanke gewählt.<br />
Nun wartet das Programm auf die erste Flanke und speichert den aktuellen Timerwert. Danach<br />
wird auf die nächste Flanke gewartet und von dem nun gelesenen Timerwert der Timerstand<br />
bei der ersten Flanke abgezogen. Das Ergebnis wird als Periodendauer gespeichert.<br />
data equ $2000 ; Datenbereich<br />
prog equ $8000 ; Programmbereich<br />
stack equ $7FFF ; Stackbereich<br />
resetv equ $FFFE ; Adresse Reset-Vektor<br />
tic1 equ $1010 ; Zaehlerstand<br />
tflg1 equ $1023 ; Timer Flag<br />
tctl2 equ $1021 ; Timer Control<br />
org data<br />
edge1 ds.b 2 ; Zaehler<br />
period ds.b 2 ; Clock Flag<br />
Mikrocomputertechnik<br />
org prog<br />
main lds #stack ; Init Stack<br />
ldab #$10 ; Flanke waehlen (fallend = 0, steigend = 1)<br />
stab tctl2 ; steigende Flanke an IC1<br />
loop ldab #$04<br />
stab tflg1 ; IC1F-Flag loeschen<br />
waitf1 ldab tflg1 ; auf erste Flanke warten<br />
andb #$04<br />
beq waitf1<br />
ldd tic1 ; akt. Zaehlerstand holen<br />
std edge1 ; und speichern<br />
ldab #$04<br />
stab tflg1 ; IC1F-Flag loeschen<br />
waitf2 ldab tflg1 ; auf zweite Flanke warten<br />
andb #$04<br />
beq waitf2<br />
ldd tic1 ; akt. Zaehlerstand holen<br />
subd edge1 ; ersten Zaehlerstand abziehen<br />
std period ; Periodendauer abspeichern<br />
*<br />
* restlicher<br />
* Programmcode<br />
*<br />
bra loop<br />
org resetv ; Reset-Vektor setzen<br />
fdb main<br />
Der Timer 121
Mikrocomputertechnik<br />
Statt wie oben im Hauptprogramm auf die beiden Flanken zu warten, kann auch hier wieder<br />
eine Interrupt-Service-Routine die Aufgabe übernehmen. Das folgende Programm zur<br />
Periodendauermessung ersetzt das Polling durch Interruptsteuerung. Die ISR speichert beim<br />
ersten Auftreten einer steigenden Flanke den aktuellen Zählerstand in der Variablen edge1<br />
und dekrementiert edgecnt. Bei der zweiten Flanke wird nur edgecnt dekrementiert, der<br />
daraufhin 0 ist und dem Hauptprogramm signalisiert, dass nun die Periodendauer wie beim<br />
vorhergehenden Programm berechnet werden kann.<br />
data equ $2000 ; Datenbereich<br />
prog equ $8000 ; Programmbereich<br />
stack equ $7FFF ; Stackbereich<br />
tirqv equ $FFEE ; Adresse Interrupt-Vektor<br />
resetv equ $FFFE ; Adresse Reset-Vektor<br />
tic1 equ $1010 ; Zaehlerstand<br />
tmsk1 equ $1022 ; Timer Mask<br />
tflg1 equ $1023 ; Timer Flag<br />
tctl2 equ $1021 ; Timer Control<br />
org data<br />
edgecnt ds.b 1 ; Flanken-Zaehler<br />
edge1 ds.b 2 ; Capture erste Flanke<br />
period ds.b 2 ; Clock Flag<br />
org prog<br />
main lds #stack ; Init Stack<br />
ldab #$10 ; Init Timer<br />
stab tctl2 ; steigende Flanke an IC1F<br />
ldab #$04<br />
stab tflg1 ; IC1F-Flag loeschen<br />
ldab #2 ; Flanken-Zaehler auf 2 setzen<br />
stab edgecnt<br />
ldab tmsk1 ; Interrupt freigeben<br />
orab #4<br />
stab tmsk1<br />
cli<br />
wait tst edgecnt ; warten, bis Flanken-Zahler = 0<br />
bne wait<br />
ldd tic1 ; akt. Zaehlerstand holen<br />
subd edge1 ; ersten Zaehlerstand abziehen<br />
std period ; Periodendauer abspeichern<br />
*<br />
* restlicher<br />
* Programmcode<br />
*<br />
bra wait<br />
* Interrupt-Service-Routine fuer Input Capture<br />
ic1_isr ldab #$04<br />
stab tflg1 ; IC1F-Flag loeschen<br />
dec edgecnt ; Flanken-Zaehler dekrementieren<br />
beq skip ; falls zweite Flanke, nichts tun<br />
ldd tic1 ; sonst akt. Zaehlerstand holen<br />
std edge1 ; und speichern<br />
skip rti<br />
org tirqv ; Reset-Vektor setzen<br />
fdb ic1_isr<br />
org resetv ; Reset-Vektor setzen<br />
fdb main<br />
Der Timer 122
•<br />
Mikrocomputertechnik<br />
Durch einige Modifikationen kann dies Programmschema auch verwendet werden, um<br />
anstelle der Periodendauer die Breite eines Impulses zu messen. Es wird dann wie oben bei<br />
der (ersten) steigenden Flanke der Zählerwert gespeichert und danach der Port so<br />
umkonfiguriert, dass nun auf eine fallende Flanke gewartet wird: in tflg1 wird anstelle von<br />
$10 nun $20 geschrieben. So wird als zweites Ereignis die fallende Flanke registriert.<br />
Der einzige Nachteil der obigen Input Capture-Programme liegt darin, dass sich nur Zeiten<br />
erfassen lassen, die im 16-Bit-Bereich liegen, also nicht größer als 32,761 ms sind. Um<br />
längere Perioden zu messen, kann man beispielsweise das Timer-Overflow-Flag in tmask2<br />
berücksichtigen und bei jedem Timer-überlauf einen weiteren Zähler inkrementieren. Auf<br />
diese Art und Weise kann so der hardwaremäßige 16-Bit-Zähler softwareseitig auf 32 oder<br />
mehr Bits erweitert werden.<br />
Output Compare: Jedes der fünf Output-Compare-Register wird laufend mit dem<br />
Zählerstand des freilaufenden Zählers verglichen. Bei Übereinstimmung wird dann exakt in<br />
diesem Moment die programmierte Reaktion ausgelöst, zum Beispiel die Ausgabe eines<br />
bestimmten Signals an einem Port. Auf diese Weise ist es möglich, ein Ausgangssignal mit<br />
der Genauigkeit und Auflösung des Timer-Systems zu einem gewünschten Zeitpunkt zu<br />
erzeugen, ohne dabei Fehler durch Software-Reaktionszeiten oder auch Verzögerungen durch<br />
Interrupt-Antwortzeiten zu haben.<br />
Insgesamt sind fünf Output-Compare-Funktionen vorhanden, die jeweils ein<br />
16-Bit-Vergleichsregister besitzen. Der Registerinhalt wird ständig mit dem Zählerstand<br />
verglichen. Bei Übereinstimmung wird das vorprogrammierte Ereignis ausgelöst. Auch hier<br />
ist je ein Bit im TMSK1- und TFLG1-Register als Schnittstelle zum Anwenderprogramm<br />
vorgesehen. Das jeweiling OCxF-Bit wird gesetzt, wenn Register und Zähler übereinstimmen.<br />
Mit den zugehörigen OCxI-Bit kann der Interrupt gesperrt oder freigegeben werden.<br />
Für die Kanäle 2 bis 5 kann im TCTL1-Register festgelegt werden, was mit dem zugehörigen<br />
Pin beim Eintreten eines Ereignisses geschehen soll:<br />
OMx OLx Reaktion<br />
0 0 Keine<br />
0 1 Polarität ändern (toggle)<br />
1 0 auf 0 setzen<br />
1 1 auf 1 setzen<br />
Mit dem Output Compare Register 1 kann man alle OC-Pins gleichzeitig manipulieren. Der<br />
OC-Pn 1 hat dabei Priorität über die anderen. Der OC1-Funktion sind zwei spezielle Register<br />
zugeordnet, OC1M und OC1D. Die Bits 3 bis 7 dieser Register entsprechen direkt den<br />
Leitungen von Port A, auf denen die OC-Werte ausgegeben werden. Für jede Leitung von<br />
Port A, die durch die OC-Funktion beinflußt werden soll, muß das entsprechende Bit in<br />
OC1M auf 1 gesetzt werden. Das Bitmuster für die Ausgabe wird dann in OC1D eingetragen.<br />
Auf diese Weise lassen sich fünf Pins exakt zeitgleich mit einem einzigen<br />
Output-Compare-Register beeinflussen.<br />
Das folgende Programm zeigt eine typische Anwendung: es wird ein Rechtecksignal von 1<br />
kHz auf OC2 erzeugt, wobei ein Tastverhältnis von 40% eingestellt wird. Die verwendeten<br />
Werte gelten wieder für 2 MHz Taktfrequenz und einen Prescaler-Faktor von 1. Zu Beginn<br />
wird PA6 auf 1 gesetzt und danach der Toggle-Modus festgelegt. Für die Frequenz von 1 kHz<br />
muss bei 2 MHz Prozessortakt die Summe von Low- und Highzeit 2000 E-Takt-Zyklen<br />
betragen. Für das gewünschte Tastverhältnis muss demnach die Low-Zeit 1200 Zyklen und<br />
die High-Zeit 800 Zyklen lang sein. Andere Tastverhältnisse lassen sich durch Ändern dieser<br />
Werte leicht bestimmen. Dass beim Initialisierten dreimal hintereinander der Wert $40<br />
verwendet wird, ist Zufall - bei anderen Ports sind die Werte unterschiedlich.<br />
data equ $2000 ; Datenbereich<br />
prog equ $8000 ; Programmbereich<br />
Der Timer 123
stack equ $7FFF ; Stackbereich<br />
resetv equ $FFFE ; Adresse Reset-Vektor<br />
porta equ $1000 ; Adresse Port A<br />
toc2 equ $1018 ; Output Compare Register<br />
tctl1 equ $1020 ; OC Control Register<br />
tflg1 equ $1023 ; Timer Flag<br />
tcnt equ $100e ; Timer Counter<br />
* Programmkonstante<br />
lotime equ 1200 ; 600 Mikrosekunden<br />
hitime equ 800 ; 400 Mikrosekunden<br />
org data<br />
Mikrocomputertechnik<br />
org prog<br />
main lds #stack ; Init Stack<br />
ldaa #$40 ; OC2 auf high<br />
staa porta<br />
ldaa #$40 ; OC2F Flag loeschen<br />
staa tflg1<br />
ldaa #$40 ; toggle-Mode setzen<br />
staa tctl1<br />
; Rechteck startet mit high<br />
ldd tcnt ; Zaehlerstand laden<br />
addd #hitime ; high-delay addieren<br />
std toc2 ; im Vergleichsregister speichern<br />
high ldaa tflg1 ; Schleife bis Zeit erreicht ist<br />
anda #$40<br />
beq high<br />
ldaa #$40 ; OC2-Flag loeschen<br />
staa tflg1<br />
ldd toc2 ; naechster Zyklus mit low<br />
addd #lotime<br />
std toc2<br />
low ldaa tflg1 ; Schleife bis Zeit erreicht ist<br />
anda #$40<br />
beq low<br />
ldaa #$40 ; OC2-Flag loeschen<br />
ldd toc2 ; naechster Zyklus wieder mit high<br />
addd #hitime<br />
std toc2<br />
bra high<br />
org resetv ; Reset-Vektor setzen<br />
fdb main<br />
Legt man anstelle des Toggle-Mode bei der Initialisierung fest, dass der PA-Ausgang nach<br />
dem Zeitablauf auf 0 gesetzt wird, erhält man beispielsweise einen Monoflop-Timer.<br />
Selbstverständlich lässt sich das obige Programm auch wieder so modifizieren, dass die ganze<br />
Sache interruptgesteuert abläuft. Die Interrupt-Serviceroutine wird jedesmal angesprungen,<br />
wenn die Zeit abgelaufen ist, und übernimmt das Eintragen der High- und Low-Zeiten. Damit<br />
haben Sie dann einen im Hintergrund ablaufenden Rechteckgenerator, dessen Tastverhältnis<br />
Sie jederzeit ändern können (indem Sie Vari-ablen anstelle der Konstanten verwenden) - also<br />
eine Pulsweiten-Modulation.<br />
Der OC1 nimmt eine Sonderstellung ein. Er kann über die Register OC1M und OC1D bis zu<br />
fünf OC-Pins steuern. OC1M legt fest, welche Pins von Port A beeinflusst wer-den und OC1D<br />
bestimmt, ob das entsprechende Bit auf 0 oder 1 gesetzt werden soll. übrigens ist der Pin PA7<br />
bidirektional. Soll er von OC1 gesteuert werden, muss er als Ausgang programmiert werden.<br />
Der Timer 124
Das folgende Programm zeigt, wie man mithilfe von OC1 und OC2 ein Rechtecksignal mit<br />
variablem Tastverhältnis erhält, das unabhängig vom Hauptprogramm im Hintergrund erzeugt<br />
wird. Im Initialisierungsteil wird festgelegt, dass OC2 bei Zeitgeberstand von 0 den Ausgang<br />
PA6 auf 1 setzt. OC1 wird zusätzlich so programmiert, dass beim Zeitgeberstand TV (6553)<br />
der Ausgang wieder auf 0 gesetzt wird. Nach Abschluß der Initialisierung laufen OC1 und<br />
OC2 synchron zur Zeitgeberperiode.<br />
data equ $2000 ; Datenbereich<br />
prog equ $8000 ; Programmbereich<br />
stack equ $7FFF ; Stackbereich<br />
resetv equ $FFFE ; Adresse Reset-Vektor<br />
porta equ $1000 ; Adresse Port A<br />
toc1 equ $1016 ; Output Compare Register 1<br />
toc2 equ $1018 ; Output Compare Register 2<br />
tctl1 equ $1020 ; OC Control Register<br />
tflg1 equ $1023 ; Timer Flag<br />
tmsk2 equ $1024 ; Timer Mask Register<br />
oc1m equ $100c ; OC1M-Register<br />
oc1d equ $100d ; OC1D-Register<br />
tcnt equ $100e ; Timer Counter<br />
TV equ 6553 ; Tastverhaeltnis (2^16 Zehntel)<br />
org data<br />
org prog<br />
main lds #stack ; Init Stack<br />
ldaa #$03 ; Timer-Takt auf 8 Mikrosekunden<br />
staa tmsk2 ; --> 524,3 ms zwischen Ueberlaeufen<br />
ldaa #$C0 ; OC2 --> PA6 auf 1 setzen<br />
staa tctl1<br />
ldd #0 ; Zaehler auf Null<br />
std toc2<br />
ldaa #$40 ; OC1 --> PA6 auf 0<br />
staa oc1m ; Bit selektieren<br />
ldaa #$BF ; soll 0 werden<br />
staa oc1d<br />
ldd #TV ; Pulsdauer festlegen<br />
std toc1<br />
loop bra loop ; Hauptprogramm tut nicht<br />
org resetv ; Reset-Vektor setzen<br />
fdb main<br />
Experimentieren Sie ruhig mit verschiedenen Werten für TV. Selbst im Simulator lassen sich<br />
Unterschiede erkennen.<br />
Pulse-Akkumulator<br />
Mikrocomputertechnik<br />
Der Pulse-Akkumulator des 68HC1 ist ein 8-Bit-Zähler, der wahlweise als Ereigniszähler oder als<br />
Zeitzähler mit externer Gate-Funktion verwendet werden kann. Für beide Fälle wird der Anschluß<br />
Port A Bit 7 als Eingang für das externe Signal benutzt. Es sind zwei Möglichkeiten vorgesehen, einen<br />
Interrupt auszulösen: bei jeder aktiven Flanke dieses Eingangs oder bei Überlauf des Zählerstandes<br />
von $FF auf $00.<br />
Wird der Pulse-Akkumulator als Zeitzähler eingesetzt, dann verarbeitet er das durch 64 geteilte Signal<br />
des internen E-Takts. Die Auflösung beträgt damit bei einer Quarzfrequenz von 8 MHz exakt 32<br />
Mikrosekunden, die längste meßbare Periode somit 256 * 0,032 ms = 8,192 ms. Beim Einsatz als<br />
Ereigniszähler können maximal 256 Flanken gezählt werden, die zu verarbeitende Frequenz muß<br />
niedriger als der E-Takt des Mikroprozessors sein. Die für die Interruptauslösung des<br />
Der Timer 125
Pulse-Akkumulatorsystems zuständigen Konfigurations- und Flagbits sind zusammen mit anderen<br />
Funktionen im TMSK2- und TFLG2-Register untergebracht. Das PAOVF-Bit im TFLG2-Register<br />
wird immer dann gesetzt, wenn ein Überlauf des Zählers von $FF auf $00 eintritt. Durch Setzen des<br />
korrespondierenden Interrupt-Bits PAOVI im TMSK2-Register kann der Anwender bestimmen, ob<br />
durch dieses Ereignis ein Interrupt ausgelöst werden soll (0 = kein Interrupt). Der gleiche<br />
Mechanismus steuert mit den Bits PAIF und PAII einen möglichen Prozessor-Interrupt bei jeder<br />
aktiven Flanke am Eingang des Pulse-Akkumulators.<br />
• Damit das Pulse-Akkumulator-System überhaupt arbeiten kann, muß der externe Pin 7 von<br />
Port A als Eingang konfiguriert werden. Hierzu muß das Bit DDRA7 im PACTL-Register auf<br />
0 gesetzt werden.<br />
• Das Bit PAEN dieses Registers schaltet den Pulse-Akkumulator generell ein und aus, wobei<br />
der Zählerstand nach dem Ausschalten des Systems weiter erhalten bleibt und ausgewertet<br />
werden kann.<br />
• Das Bit PAMOD definiert die Betriebsart des Zählers: eine O macht ihn zum Ereigniszähler,<br />
eine 1 wählt die Zeitmessung.<br />
• PEDGE erlaubt die Wahl der aktiven Flanke. Eine 0 läßt den Zähler auf abfallende Flanken<br />
reagieren, in der Betriebsart Zeitzähler stoppt ein Low-Signal die Messung, eine 1 in PEDGE<br />
wählt die ansteigende Flanke und ein High-Signal als Sperre für die Betriebsart Zeitzähler.<br />
5.5 Geschützte Register<br />
(time protected control registers)<br />
Diese Register können nur während der ersten 64 Taktzyklen des E-Taktes nach einem RESET<br />
beschrieben werden.<br />
INIT bit 7-4: RAM3, RAM2, RAM1, RAM0<br />
position direct page at 4k-boundaries<br />
(default = 0000, RAM = $0000-$00FF)<br />
bit 3-0: REG3, REG2, REG1, REG0<br />
position Register block at 4k-boundaries<br />
(default = 0001, REG = $1000-$103F)<br />
TMSK2 bit 1-0: PR1, PR0<br />
prescaler of main timer<br />
(default = 00, ps = 1)<br />
OPTION bit 5: IRQE<br />
IRQ edge or level sensitive<br />
(default = 0, level sensitive)<br />
bit 4: DLY<br />
delay after coming out of STOP power saving mode<br />
(default = 1, wait 4000 cycles to stabilize crystal oscillator)<br />
bit 1-0: CR1, CR0<br />
COP timer rate on 2 15 base<br />
(default = 00, tr = 1)<br />
Mikrocomputertechnik<br />
5.5 Geschützte Register 126
5.6 Interrupts<br />
Mikrocomputertechnik<br />
Beim Daten-Verkehr zwischen Computer und der Außenwelt gibt es fast immer große und vor allem<br />
unregelmäßige Zeitabstände zwischen den Transfers. Zur Synchronisation dieser Ereignisse mit den<br />
Abläufen in einem Computer dienen Steuersignale der Peripherie, die zumindest als Status-Bits in<br />
einem Status-Register eines Peripheriebausteins erkennbar sind: im einfachsten Fall muss das<br />
Programm diese Status-Information regelmäßig abfragen, und zwar so häufig, dass kein Ereignis -<br />
auch bei maximaler Rate - "übersehen" wird.<br />
Dieser polling mode führt zu einer hohen Rechnerbelastung aufgrund von Abfragen, die auch fast<br />
immer negativ ausfallen. Alle modernen Mikroprozessoren besitzen deshalb Hardware- Mechanismen<br />
zur Programmunterbrechung durch solche Ereignisse. Das "Pollen" des Programms nach Ereignissen<br />
wird hier ersetzt durch einen von der Hardware (Ablaufsteuerung, Mikroprogramm) erzwungenen<br />
Unterprogrammsprung zu einem vorbereiteten Bearbeitungs-Programm, der sogenannten<br />
Interrupt-Service-Routine (ISR).<br />
Die ähnlichkeit des Interrupt mit einem Unterprogrammsprung (JSR) ist tatsächlich groß. Das<br />
Auftreten des Interrupt-Request-Signals auf dem Bus wird vom Mikroprogramm am Ende jedes<br />
Befehlszyklus geprüft und führt ggf. zu einem Sprung zum Beginn der ISR. (Genaugenommen ist das<br />
regelmäßige Abfragen nach externen Ereignissen nur ins Mikroprogramm der Ablaufsteuerung<br />
verlagert worden, jedoch mit sehr hoher Effizienz).<br />
Ein Interrupt kann - falls zugelassen - im Unterschied zu einem JSR prinzipiell nach jedem beliebigen<br />
Befehl des Programms wirksam werden, dementsprechend muss wie beim JSR der PC-Stand gerettet<br />
werden; auch das erledigt die Ablaufsteuerung bei der Annahme des Interrupt Request, genau wie<br />
beim JSR. Die Interrupt-Service-Routine wird mit einem ähnlichen Befehl wie ein Unterprogramm<br />
verlassen (RTI statt RTS), denn auch hier muss der Rücksprung wieder zur "Unterbrechungsstelle"<br />
zurückführen.<br />
Man unterscheidet beim 68HC11 Interrupts, die (extern!) von Hardwaresignalen ausgelöst werden<br />
(XIRQ, IRQ und RESET) und den internen Interruptquellen (interne Peripheriebausteine oder "illegal<br />
Operation"). Außerdem gibt es einem Befehl (SWI), der ebenfalls einen Interrupt auslöst. Ein weiteres<br />
Unterscheidungskriterium ist die Maskierbarkeit. Der normale Interrupt ist nur dann wirksam, wenn<br />
das entsprechende Maskenbit im CC-Register gelöscht ist (=0). Die Signale RESET und XIRQ sind<br />
nicht maskierbar, sie werden deshalb auch als "nicht maskierbare Interrupts" bezeichnet.<br />
Der XIRQ weist dabei noch eine Besonderheit auf: er ist nach einem RESET so lange gesperrt<br />
(maskiert), bis er durch Nullsetzen von Bit 6 im CC-Register zugelassen wird. Danach ist er nicht<br />
mehr sperrbar!<br />
Der 68HC11 verfügt über insgesamt 21 externe und interne Interruptquellen. Entsprechend komplex<br />
ist seine Interruptstruktur. Hier nochmals zur Erinnerung der Ablauf eines Interrupts:<br />
Nach einem Reset des Prozessors sind zunächst die beiden CC-Register-Flags X und I gesetzt und<br />
somit alle Interrupts gesperrt (= maskiert, disabled). Diese beiden Flags nennt man auch<br />
"Innensperren", denn mit ihnen kann im Prozessor verhindert werden, dass anstehende (pending)<br />
Interrupts tatsächlich den Programmablauf unterbrechen.<br />
5.6 Interrupts 127
Es ist wichtig, dass zunächst die Interrupts nicht zugelassen werden, denn erst wenn per Programm<br />
einige Vorbereitungen getroffen sind (Peripheriebausteine initialisieren, Stackpointer setzen, ) kann<br />
ein eintreffender Interrupt korrekt bedient werden.<br />
Die Interrupt-Sperren in den verschiedenen Peripherie-Bausteinen nennt man "Außensperren". Damit<br />
hat der Programmierer die Möglichkeit ganz gezielt Ereignisse sich entweder nur per Statusbit<br />
anzeigen zu lassen (polling mode) oder es sich per Interrupt melden zu lassen.<br />
Auslösen einer Unterbrechung<br />
Signal RESET Unbedinger Abbruch und Neustart<br />
Signal XIRQ und (X-Bit = 0) Unbedingte Unterbrechung (non maskable interrupt)<br />
Signal IRQ und (I-Bit = 0)<br />
Bedingte Unterbrechung (interrupt request)<br />
(kann auch interne Ursachen haben)<br />
Befehl SWI Befehlsgesteuerte Unterbrechung (software interrupt)<br />
Befehl Illegal Opcode Nicht implementierter Befehl<br />
Interrupt-Vektoren<br />
Mikrocomputertechnik<br />
Die Interrupt Service Routine (ISR) kann an beliebiger Stelle im Speicher abgelegt werden. Beim<br />
Eintreffen des Interrupts muss die ISR aufgerufen werden. Die ISR-Startadresse muss daher im<br />
Speicher bereitgestellt werden (Aufgabe des Programmierers!). Die Adressen des<br />
16-Bit-Speicherworts, in dem die Adressen der ISR abgelegt werden, liegen hardwaremäßig fest. Für<br />
jeden der verschiedenen Interrupts gibt es ein fest zugeordnetes Speicherwort (Interrupt-Vektor):<br />
Auslösen einer Unterbrechung 128
Mikrocomputertechnik<br />
Priorität Name Adresse Interrupt-Quelle<br />
21 SCIINT $FFD6 SCI serial system<br />
20 SPIINT $FFD8 SPI serial system<br />
19 PAIINT $FFDA Pulse Accumulator Input Edge<br />
18 PAOVINT $FFDC Pulse Accumulator Overflow<br />
17 TOINT $FFDE Timer Overflow<br />
16 TOC5INT $FFE0 Timer Output Compare 5<br />
15 TOC4INT $FFE2 Timer Output Compare 4<br />
14 TOC3INT $FFE4 Timer Output Compare 3<br />
13 TOC2INT $FFE6 Timer Output Compare 2<br />
12 TOC1INT $FFE8 Timer Output Compare 1<br />
11 TIC3INT $FFEA Timer Input Capture 3<br />
10 TIC2INT $FFEC Timer Input Capture 2<br />
9 TIC1INT $FFEE Timer Input Capture 1<br />
8 RTIINT $FFF0 Real Time Interrupt<br />
7 IRQINT $FFF2 IRQ External Interrupt<br />
6 XIRQINT $FFF4 XIRQ External Interrupt<br />
5 SWIINT $FFF6 Software Interrupt<br />
4 BADOPINT $FFF8 Illegal Opcode Trap Interrupt<br />
3 NOCOPINT $FFFA COP Failure (Reset)<br />
2 CMEINT $FFFC COP Clock Monitor Fail (Reset)<br />
1 RESETINT $FFFE RESET Interrupt<br />
Die nicht maskierbaren Interrupts wie RESET, CMF, COP, XIRQ, Ill. Opcode oder SWI haben eine<br />
feste Priorität. Bei den anderen Interrupts läßt sich die Priorität ändern. Die vier Bits PSEL0 bis<br />
PSEL3 im HPRIO-Register legen fest, welche Interruptquelle die höchste Priorität besitzen soll.<br />
Auslösen einer Unterbrechung 129
Mikrocomputertechnik<br />
PSEL3 PSEL2 PSEL1 PSEL0 Interrupt-Quelle<br />
0 0 0 0 Timer Overflow<br />
0 0 0 1 Pulse Accumulator Overflow<br />
0 0 1 0 Pulse Accumulator Input Edge<br />
0 0 1 1 SPI serial system<br />
0 1 0 0 SCI serial system<br />
0 1 0 1 Reserve<br />
0 1 1 0 IRQ External Interrupt<br />
0 1 1 1 Real Time Interrupt<br />
1 0 0 0 Timer Input Capture 1<br />
1 0 0 1 Timer Input Capture 2<br />
1 0 1 0 Timer Input Capture 3<br />
1 0 1 1 Timer Output Compare 1<br />
1 1 0 0 Timer Output Compare 2<br />
1 1 0 1 Timer Output Compare 3<br />
1 1 1 0 Timer Output Compare 4<br />
1 1 1 1 Timer Output Compare 5<br />
Eine besonders wichtige Rolle in jedem Mikroprozessorsystem spielen die nicht maskierbaren<br />
Interrupts. Sie sind speziell für das Auslösen lebenswichtiger Funktionen vorgesehen, wie zum<br />
Beispiel zur Erkennung eines Versorgungsspannungsausfalls. Da der Mikroprozessor 68HC11 über<br />
die Möglichkeit verfügt, seine interne Organisation zu modifizieren, ist für den externen nicht<br />
maskierbaren Interrupt XIRQ ein spezielles Bit im Condition-Code-Regisier vorgesehen, mit dem<br />
dieser direkt nach einem Reset-Vorgang maskiert wird. Dies ist kein Widerspruch, denn wenn das<br />
Anwenderprogramm die interne Organisation (Speicheraufteilung, Festlegung des Registerblocks,<br />
Initialisierung des Stackpointers) durchgeführt hat, kann dieses Bit nur ein einziges Mal auf 0 gesetzt<br />
werden. Ein erneutes Maskieren des XIRQ ist danach nicht mehr möglich, so daß man von diesem<br />
Zeitpunkt an von einem echten nicht maskierbaren Interrupt sprechen kann.<br />
Während der Organisationsphase ist es in jedem Fall zwingend notwendig, keinen Interrupt<br />
zuzulassen, denn ein während dieses Zeitraumes aufgerufenes Interrupt-Programm würde auf<br />
Resourcen zurückgreifen wollen, die unter Umständen noch nicht verfügbar sind.<br />
Eine zweite nicht maskierbare Interrupt-Quelle ist eine Erkennungsschaltung für illegale Befehlscodes<br />
(Illegal Opcode Trap). Da nicht alle möglichen Bitkombinationen mit gültigen Befehlen besetzt sind,<br />
besteht die Möglichkeit, daß die CPU durch einen Fehler im Programm oder durch einen Störimpuls<br />
von außen einen ungültigen Befehl bekommt. In einem solchen Fall wird ein spezieller Interruptvektor<br />
angesprungen, der auf eine Fehlerbehandlungsroutine zeigen sollte. Wird dieser Vektor nicht vom<br />
Anwender initialisiert, dann kann es passieren, daß er auf einen weiteren ungültigen Befehl zeigt und<br />
die CPU damit in eine Endlosschleife gerät.<br />
Eine ähnliche Funktion hat der Softwareinterrupt SWI, der häufig während der Test- und<br />
Emulationsphase eines Programms benutzt wird. Er stellt einen normalen gültigen Befehl der CPU<br />
dar. Der Software-Interrupt wird in erster Linie von Emulations-Systemen zur Manipulation des<br />
Zielprozessors benutzt. Man kann ihn aber auch für Sytemaufrufe verwenden, wenn im 68HC11 ein<br />
Mini-Betriebssystem implementiert wird.<br />
Alle weiteren Interrupt-Quellen des 68HC11 können durch das 1-Bit im Condition-Code-Register<br />
maskiert werden. Wenn dieses Bit gesetzt ist, sind alle diese Interrupt-Quellen gesperrt. Jeder<br />
Auslösen einer Unterbrechung 130
Reset-Vorgang setzt dieses Bit. Es ist Aufgabe des Anwenderprogramms, den Interrupt nach<br />
sinnvoller Initialisierung des Systems gezielt freizugeben.<br />
Jeder Eintritt in ein Interruptprogramm setzt das I-Bit, um eine weitere Unterbrechung durch einen<br />
neuen Interrupt zu verhindern. Nach Beendigung des Interruptprogramms durch einen RTI-Befehl<br />
wird es automatisch wieder gelöscht, so daß erneute Interrupts wieder zugelassen sind.<br />
Zur Erweiterung der Interrupt-Struktur steht der Eingang IRQ zur Verfügung. Hier können beliebig<br />
viele externe Interrupt-Quellen angeschlossen werden. Zu diesem Zweck ist dieser Pin nach einem<br />
Reset auf Pegelabhängigkeit geschaltet ( Möglichkeit des "wired or" mehrerer Interruptquellen), um<br />
mit externen Peripherie-ICs kompatibel zu sein. Die Konfiguration als flankenempfindlicher Eingang<br />
wird seltener angewendet, da sie nur mit einer einzigen externen Interrupt-Quelle zusammenarbeiten<br />
kann.<br />
Zusammenfassung der notwendigen Voraussetzungen zum Arbeiten mit Interrupts:<br />
1. Der IRQ-Ausgang eines externen Peripheriebausteins muß mit einem der<br />
Prozessor-Interrupt-Eingänge verbunden sein: IRQ, XIRQ, RESET (Hardware-Design).<br />
Interne Peripheriekomponenten sind natürlich schon verbunden.<br />
2. Der Stackpointer muß per LDS-Befehl gesetzt worden sein, damit die Register beim Interrupt<br />
in den beabsichtigten Stackbereich gerettet werden.<br />
3. Die Interrupt-Service-Routine muß programmiert sein.<br />
a. gegebenenfalls muß der Interrupt-Verursacher identifiziert werden, falls mehrere per<br />
"wired or" zusammengeschlossen sind.<br />
b. das IRQ-FF beim Interrupt-Verursacher muß darin gelöscht werden<br />
4. Die Startadresse der ISR muß in den entsprechenden Vektorzellen stehen. Initialsierung<br />
beispielsweise:<br />
5.<br />
6.<br />
Mikrocomputertechnik<br />
ORG $FFFE<br />
DC.W main<br />
Im Peripheriebaustein-Kontrollregister "interrupt enable" setzen (= Außensperre öffnen).<br />
im Prozessor (CC-Register) den entsprechenden Interrupt zulassen (= Innensperre öffnen).<br />
Im Praktikum geht es vor allem um die Aktionen 3, 4, 5, und 6.<br />
Beispiel 1: Bedingte Unterbrechung am Eingang PA7<br />
Am Eingang PA7 (Pulse Akku) ist ein Taster angeschlossen, mit dem eine bedingte Unterbrechung<br />
ausgelöst werden kann. Das Auftreten des Interrupts soll über eine Variable PFLAG signalisiert<br />
werden, die auch über Port C ausgegeben wird.<br />
Alle auszuführenden Schritte werden im Folgenden ausführlich beschrieben:<br />
• Setzen der Eigenschaften für PA7 im PACTL-Register:<br />
1. PA7 muss als Eingang konfiguriert werden. Die entsprechende Konfiguration findet<br />
per DDRA-Bit im Register PACTL statt: es muss auf 0 gesetzt werden.<br />
2. Eine Interrupt-Auslösung durch PA7 ist nur möglich, wenn sich der Port A im<br />
Betriebsmodus "Puls Accu Enable" befindet. Dazu muss im Register PACTL das Bit<br />
PAEN auf 1 gesetzt werden.<br />
3. Im Pulse-Accu-Betrieb muss noch unterschieden werden zwischen "Event Counting"-<br />
Auslösen einer Unterbrechung 131
und "Gated Time"- Mode. Da jedes Ereignis einen Interrupt auslösen soll, ist der<br />
"Event Counting Mode" zu wählen. Dazu muss im Register PACTL das Bit PAMOD<br />
auf 0 gesetzt werden (PAMOD = 0 -> "Event Counting Mode").<br />
4. Die steigende Impulsflanke wird durch Bit PEDGE im Register PACTL bestimmt:<br />
"Rising Edge" wird durch eine 1 gewählt.<br />
• Die ausgewählte Flanke am PA7-Pin führt somit zu einem Setzen des Statusbits PAIF im<br />
Register TFLG2. Somit könnte die Flanke auch an diesem gesetzten Bit durch Lesen des<br />
TFLG2-Registers erkannt werden ( regelmäßiges Auslesen = Polling Mode). Es soll jedoch<br />
per Interrupt gemeldet werden, deshalb muss noch der zugehörige Interrupt zugelassen<br />
werden. Erreicht wird dies durch Setzen des Bits PAII im Register TMSK2.<br />
• Schließlich ist noch eine Interrupt-Service Routine (ISR) nötig, die beim Auftreten des<br />
Interrupts die gewünschten Aktionen vornimmt (z. B. Lampe einschalten durch Ausgabe eines<br />
Bits an einem anderen Port). Unbedingt notwendig ist darin das Löschen des PAIF-Bits im<br />
Register TFLG2, denn sonst würden ständig weitere Interrupts ausgelöst! Löschen dieses Bits<br />
geschieht durch Schreiben einer 1 ins Bit PAIF!<br />
• Die Startadresse dieser ISR muss im zugehörigen Vektor abgelegt werden, damit beim<br />
Interrupt der Programcounter mit dieser Adresse geladen werden kann.<br />
• Zuletzt (als letzte Aktion der Initialisierung) muss der Interrupt ganz allgemein zugelassen<br />
werden. Dies erledigt der CLI-Befehl.<br />
Hier nun das vollständige Programm dazu:<br />
data equ $2000 Datenbereich<br />
prog equ $8000 Programmbereich<br />
stack equ $7FFF Stackbereich<br />
pirqv equ $FFDA Adresse PA-Vektor<br />
resetv equ $FFFE Adresse Reset-Vektor<br />
padr equ $1000 Adresse Port A<br />
pcdd equ $1007 Adressen Port C<br />
pcdr equ $1003<br />
pacr equ $1026 Pulse Akku Control<br />
tflag equ $1025 Timer Flag<br />
tmask equ $1024 Timer Mask<br />
org data<br />
pflag ds.b 1<br />
org prog<br />
main lds #stack Init Stack<br />
clr pflag Init Flag<br />
ldab #$FF Port C auf Ausgang<br />
stab pcdd<br />
ldab #$40 Init Interrupt<br />
stab pacr Pulse Akku enable<br />
ldab #$10<br />
stab tmask PA7 enable<br />
cli Interrupt freigeben<br />
loop ldab pflag Ausgabeschleife<br />
stab pcdr<br />
bra loop<br />
Mikrocomputertechnik<br />
pirq ldaa #$10 Interrupt Service Routine<br />
staa tflg<br />
com pflag toggle 0 - FF 0 - FF - ...<br />
rti<br />
org pirqv Interrupt-Vektor setzen<br />
dc.w pirq<br />
Auslösen einer Unterbrechung 132
org resetv Reset-Vektor setzen<br />
dc.w main<br />
Beispiel 2: Bedingte Unterbrechung am Eingang STRA<br />
Am Eingang STRA ist ein Taster angeschlossen, mit dem eine bedingte Unterbrechung ausgelöst<br />
werden kann. Das Auftreten des Interrupts soll über eine Variable TFLAG signalisiert werden, die<br />
auch über Port C ausgegeben wird. Das Verfahren für STRA ist nahezu identisch mit dem oben<br />
beschriebenen.<br />
• Setzen der Eigenschaften für STRA-Interrupt: Das Bit STAI in PIOC muss auf 1 gesetzt<br />
werden. Eine Flanke am STRA-Pin führt dann zu einem Auslösen des Interrupts und Setzen<br />
des STAF-Bits in PIOC.<br />
• Weiter ist noch eine Interrupt-Service Routine (ISR) nötig, die beim Auftreten des Interrupts<br />
die gewünschten Aktionen vornimmt. Unbedingt notwendig ist darin das Löschen des<br />
STAF-Bits im Register PIOC, denn sonst würden weitere Interrupts nicht erkannt! Löschen<br />
dieses Bits geschieht durch Lesen von PIOC und danach Lesen von PORTCL!<br />
• Die Startadresse dieser ISR muss im zugehörigen Vektor abgelegt werden, damit beim<br />
Interrupt der Programcounter mit dieser Adresse geladen werden kann.<br />
• Zuletzt (als letzte Aktion der Initialisierung) muss der Interrupt ganz allgemein zugelassen<br />
werden. Dies erledigt der CLI-Befehl.<br />
data equ $2000 Datenbereich<br />
prog equ $8000 Programmbereich<br />
stack equ $7FFF Stackbereich<br />
irqv equ $FFF2 Adresse IRQ-Vektor<br />
resetv equ $FFFE Adresse Reset-Vektor<br />
pioc equ $1002 Adressen Port C<br />
portcl equ $1005<br />
pcdd equ $1007<br />
pcdr equ $1003<br />
org data<br />
tflag ds.b 1<br />
Mikrocomputertechnik<br />
org prog<br />
main lds #stack Init Stack<br />
clr tflag Init Flag<br />
ldab #$FF Port C auf Ausgang<br />
stab pcdd<br />
ldab #$40 Init Interrupt<br />
stab pioc STRA enable<br />
cli Interrupt freigeben<br />
loop ldab tflag Ausgabeschleife<br />
stab pcdr<br />
bra loop<br />
sirq ldaa pioc Interrupt Service Routine<br />
ldaa portcl<br />
com tflag toggle 0 - FF 0 - FF - ...<br />
rti<br />
org irqv Interrupt-Vektor setzen<br />
dc.w sirq<br />
org resetv Reset-Vektor setzen<br />
dc.w main<br />
Auslösen einer Unterbrechung 133
Beispiel 3: Timer-Unterbrechung<br />
Ein Binärzähler soll mit einer Frequenz von ca. 10 Hz betrieben werden. Seine aktuelle<br />
Stellung ist an Port C auszugeben. Als Taktquelle ist die bei Timerüberlauf auftretende<br />
Unterbrechung (Timer Overflow Interrupt) des freilaufenden 16-Bit-Zählers des 68HC11 zu<br />
verwenden. Da der Interrupt alle 32,77 ms auftritt, muss noch ein zusätzlicher<br />
Modulo-3-Zähler verwendet werden, um auf annähernd 100 ms zu kommen (genauer: 3 *<br />
32,77 ms = 98,31 ms).<br />
data equ $2000 Datenbereich<br />
prog equ $8000 Programmbereich<br />
stack equ $7FFF Stackbereich<br />
tirqv equ $FFDE Adresse TOF-Vektor<br />
resetv equ $FFFE Adresse Reset-Vektor<br />
padr equ $1000 Adresse Port A<br />
pcdd equ $1007 Adressen Port C<br />
pcdr equ $1003<br />
pacr equ $1026 Pulse Akku Control<br />
tflag equ $1025 Timer Flag<br />
tmask equ $1024 Timer Mask<br />
org data<br />
count ds.b 1 Zaehler<br />
cflag ds.b 1 Clock Flag<br />
Mikrocomputertechnik<br />
org prog<br />
main lds #stack Init Stack<br />
clr count Init Flag<br />
ldab #$FF Port C auf Ausgang<br />
stab pcdd<br />
ldab #$80 Init Interrupt<br />
stab tmask TOF-Interrupt enable<br />
ldab #$40<br />
stab pacr<br />
cli Interrupt freigeben<br />
loop ldab cflag Ausgabeschleife<br />
cmpb #3 Trigger-Zeitpunkt?<br />
bne loop Nein<br />
clr cflag Gotcha!<br />
inc count Zaehler erhoehen<br />
ldab count ...und ausgeben<br />
stab pcdr<br />
bra loop<br />
tirq ldaa #$80 Interrupt Service Routine<br />
staa tflg<br />
inc cflag<br />
rti<br />
org tirqv Interrupt-Vektor setzen<br />
dc.w tirq<br />
org resetv Reset-Vektor setzen<br />
dc.w main<br />
Bei der Einstellung der Parameter für den Timer werden ebenso wie beim PA7-Interrupt die<br />
Register TMASK und TFLAG verwendet. Werden beide Interrupts kombiniert, muss man<br />
darauf achten, die entsprechenden Bits für beide gemeinsam zu setzen. Das folgende<br />
Programm zeigt die Kombination aller drei Interrupts: Der Timer steuert einen Zähler, der auf<br />
Auslösen einer Unterbrechung 134
Port B ausgegeben wird. Der STRA-Interrupt wechselt zwischen Auf- und Abwärtszähler und<br />
der PA7-Interrupt startet oder stoppt den Zähler.<br />
data equ $2000 ; data area (e-ram)<br />
stak equ $7FFF ; stack area (e-ram)<br />
prog equ $8000 ; programm area (e-eerom)<br />
pvec equ $FFDA ; vector pa7<br />
tvec equ $FFDE ; vector timer<br />
svec equ $FFF2 ; sirq vector<br />
rvec equ $FFFE ; reset vector<br />
pioc equ $1002 ; parallel i/o control<br />
pbdr equ $1004 ; port b data<br />
pcdl equ $1005 ; port c data latch<br />
tmsk equ $1024 ; timer mask<br />
tflg equ $1025 ; timer flag<br />
pacr equ $1026 ; pulse accu control<br />
baud equ $102B ; SCI-baudrate<br />
sccr1 equ $102C ; SCI-control1<br />
sccr2 equ $102D ; SCI-control2<br />
scsr equ $102E ; SCI-status<br />
scdr equ $102F ; SCI-data<br />
***************************<br />
* data area *<br />
***************************<br />
org data<br />
coun ds.b 1 ; counter<br />
cflg ds.b 1 ; clock flag<br />
updn ds.b 1 ; direction flag<br />
stop ds.b 1 ; stop flag<br />
***************************<br />
* program area *<br />
***************************<br />
org prog<br />
main lds #stak ; load stackpointer<br />
bsr init ; data init<br />
cli ; enable irq<br />
loop ldaa cflg ; get clock flag<br />
cmpa #20 ; trigger point?<br />
bne loop ; no, wait<br />
clr cflg ; yes, clear clock flag<br />
tst stop ; stop active?<br />
bne loop ; yes, wait<br />
bsr count ; update counter<br />
bra loop ; close main loop<br />
***************************<br />
* subroutines *<br />
***************************<br />
Mikrocomputertechnik<br />
count ldaa coun ; load counter<br />
adda updn ; inc/dec counter<br />
staa coun ; save counter<br />
staa pbdr ; display counter<br />
rts<br />
init clr coun ; counter default<br />
Auslösen einer Unterbrechung 135
clr cflg ; no clock seen<br />
clr stop<br />
ldaa #1<br />
staa updn ; default count up<br />
ldab #$40 ; enable STRA interrupt<br />
stab pioc<br />
ldab #$40 ; enable PA7 interrupt<br />
stab pacr ; enable pulse accu<br />
ldab #$90 ; $80 (Timer) + $10 (PA7)<br />
stab tmsk<br />
rts<br />
***************************<br />
* interrupt handler *<br />
***************************<br />
tirq ldaa #$80<br />
staa tflg ; clear interrupt<br />
inc cflg ; count interrupts<br />
rti<br />
sirq ldaa pioc<br />
ldaa pcdl ; clear interrupt<br />
neg updn ; toggle direction<br />
rti<br />
pirq ldaa #$10<br />
staa tflg ; clear interrupt<br />
com stop ; toggle stop flag<br />
rti<br />
***************************<br />
* vectors *<br />
***************************<br />
org pvec<br />
fdb pirq ; PA7 interrupt<br />
org tvec<br />
fdb tirq ; DE timer overflow<br />
org svec<br />
fdb sirq ; STRA<br />
org rvec<br />
fdb main ; FE reset<br />
end<br />
Beispiel 4: XIRQ und STOP<br />
Der nichtmaskierbare Interrupt XIRQ muss beim Programmstart einmal freigegeben werden<br />
und läßt sich dann nicht mehr zurücksetzen. Das folgende Beispiel hat die kürzeste aller<br />
möglichen Interrupt-Serviceroutinen für den XIRQ, nämlich nur ein "rti". Natürlich kann man<br />
hier auch beliebigen Code unterbringen. Insofern bietet der XIRQ eigentlich nichts Neues.<br />
Zusammen mit dem STOP-Befehl wird es aber interessant. Zur Erinnerung: Der STOP-Befehl<br />
stoppt den Takt und schaltet die CPU in den Standbymodus. Ein Aufwecken ist nur per XIRQ<br />
oder IRQ möglich. Im folgenden Programm steht der STOP-Befehl in der Zählschleife, so<br />
dass bei jedem XIRQ um 1 weitergezählt wird und dann die CPU wieder schlafen geht.<br />
data equ $2000 ; data area<br />
Mikrocomputertechnik<br />
Auslösen einer Unterbrechung 136
stak equ $7FFF ; stack area<br />
prog equ $8000 ; program area<br />
xvec equ $FFF4 ; xirq vector<br />
rvec equ $FFFE ; reset vector<br />
portb equ $1004 ; port b data<br />
portc equ $1003 ; port c data<br />
pcdd equ $1007 ; port c data direction<br />
org data<br />
coun ds.b 1 ; counter<br />
org prog<br />
main lds #stak ; load stackpointer<br />
clr coun<br />
tpa ; enable xirq, stop<br />
anda #%00111111<br />
tap<br />
loop stop ; go to sleep<br />
inc coun ; count up<br />
ldab coun<br />
stab portb ; display<br />
bra loop<br />
; xirq isr<br />
xirq rti<br />
org xvec<br />
fdb xirq<br />
org rvec<br />
fdb main<br />
end<br />
Zum vorhergehenden<br />
Abschnitt Zum Inhaltsverzeichnis<br />
Copyright © FH München, FB 04, Prof. Jürgen Plate<br />
Letzte Aktualisierung: 06. Mai 2012<br />
Mikrocomputertechnik<br />
Zum nächsten<br />
Abschnitt<br />
Mikrocomputertechnik<br />
Prof. Jürgen Plate<br />
Auslösen einer Unterbrechung 137
6 Ausblick: andere Controller<br />
6.1 Atmel-Mikrocontroller<br />
Die Atmel AVR ist eine 8-Bit-Mikrocontroller-Familie des US-amerikanischen Herstellers Atmel. Die<br />
Controller dieser Familie sind wegen ihres einfachen Aufbaus und ihrer leichten Programmierbarkeit<br />
auch bei Hobby-Anwendern weit verbreitet. Die Typen unterteilen sich in die Gruppen<br />
• ATmega: "große" AVR-Controller mit bis zu 256 KB Flash-Speicher in 28- bis 100-poligen<br />
Gehäusen und mit integriertem Hardware-Multiplizierer.<br />
• ATtiny: kleinere AVR-Controller mit bis zu 16 KB Flash-Speicher in 6- bis 20-poligen<br />
Gehäusen.<br />
• AT90USB: ATmega mit integriertem USB-Controller<br />
• AT90CAN: ATmega mit CAN-Controller<br />
• Sondertypen: einige Spezialmodelle, z. B. zur Ansteuerung von Akku-Ladegeräten, Displays<br />
und für Steuerungen<br />
• AT90S: veraltete Typen, die "klassischen" AVRs<br />
Beispiel: Blockschaltung des ATTtiny<br />
6 Ausblick: andere Controller 138
Mikrocomputertechnik<br />
Die Atmel-Prozessoren besitzen eine RISC-Architektur und zeichen sich unter anderem durch eine<br />
relativ große Zahl von Universalregistern aus. Normalerweise wir ein Befehl in einem Taktzyklus<br />
ausgeführt. Je nach Typ besitzen sie<br />
• 32 größtenteils gleichwertige Register, davon lassen sich drei als Pointerregister<br />
(Indexregister) verwenden<br />
• ca. 70 bis 110 Befehle, die meist nur ein bis zwei Taktzyklen dauern<br />
• Taktfrequenz bis 20 MHz (intern erzeugt, extern oder mit Quarz)<br />
• Betriebsspannung von 1,8 bis 5,5 V<br />
• Speicher: 1 - 256 KByte Flash-ROM als Programmspeicher, 0 - 4 KByte EEPROM, 0 - 8<br />
KByte RAM<br />
• Peripherie: A/D-Wandler, 8- und 16-Bit-Timer mit PWM, SPI, I2C (TWI), UART,<br />
Analog-Komparator, Watchdog, externer SRAM<br />
• JTAG bei den größeren ATmegas, debugWire bei den neueren AVRs<br />
• Konfigurationswort (Wahl der Taktquelle usw.)<br />
Beispiel: Pins des ATtiny<br />
Beispiel: Pins des ATMega8<br />
Um einen AVR-Prozessor zu betreiben ist eigentlich nur die Stromversorgung nötig. Der Chip wird<br />
mit einer stabilen Versorgungsspannung (2,7 bis 5 Volt, je nach AVR und Taktfrequenz) versorgt und<br />
erhält den üblichen Stützkondensator (100 nF), der möglichst nahe am AVR angebracht wird.<br />
Weiterhin ist ein Pull-Up-Widerstand für den Resetpin nötig (man könnte ihn weglassen, aber dadurch<br />
würde der Reset-Eingang sehr anfällig für Störungen. Bei den AVR Typen mit<br />
Analog-Digital-Wandler muss man die Pins AVCC und AGND anschließen (auch wenn die<br />
Analog-Schnittstelle nicht verwendet wird), da es sonst zu Fehlfunktionen der entsprechenden Ports<br />
kommen kann. AREF und AVCC werden an die Versorgungsspannung geklemmt, AGND an Masse.<br />
Im Normalfall reicht der interne Oszillator für den Betrieb des AVR aus, lediglich wenn man eine<br />
höhere Taktfrequenz als 8 MHz oder eine größere Genauigkeit benötigt, muss ein Quarz<br />
angeschlossen werden. Die maximale Quarzfrequenz hängt auch von der Höhe der<br />
Versorgungsspannung ab.<br />
Beispiel: Blockschaltung des ATTtiny 139
Mikrocomputertechnik<br />
Die Harvard-/RISC-Architektur führt auch zu einer Speicheraufteilung, die sich vom bisher<br />
behandelten 68HC11 unterscheidet. Die ersten 32 Bytes des Speichers werden von den "General<br />
Purpose Working Registers" (GPWR) belegt. Der darauf folgende 64 Byte lange Speicherbereich<br />
enthält die Konfiguration der Peripherie und die "General Purpose Input Output Register"<br />
(GPIO-Register), was den Portadressen beim 68HC11 entspricht. Ab Adresse 0X0060 beginnt dann<br />
der eigentliche Arbeitsspeicher.<br />
Die Programmierung erfolgt in <strong>Assembler</strong> und C. Außerdem gibt es einen Basic-Dalekt (Bascom).<br />
Der <strong>Assembler</strong> kennt bis zu 120 Instruktionen (Rechnen, Sprünge, Bitmanipulation, Datentransfer,<br />
Kontroll-Funktionen).<br />
Die Prozessoren besitzen ein serielles Programmierinterface, wodurch die Programmierung in der<br />
Schaltung möglich ist (ISP, In System Programming). Verwendet werden drei Ports (z. B. PB0, PB1<br />
und PB2) sowie der Reset-Pin. Diese Ports und die zwei Betriebsspannungsanschlüsse wechseln beim<br />
Programmieren automatisch ihre Funktion und Richtung. Bei etlichen Type besteht die Wahl<br />
zwischen zwei Programmiermodi möglich (bei 12V am Reset-Eingang sind besondere Einstellungen<br />
zugänglich).<br />
Beim seriellen Programmieren werden die Programmbits nacheinander, gesteuert durch einen von<br />
außen angelegten Takt am Pin SCK, über den Pin MOSI in ein internes Schiebregister eingeschoben<br />
und von dort in den Flash-Speicher kopiert. Das Beobachten des Programmiervorgangs, ebenso das<br />
Verifizieren bzw. Lesen des Flash-Speichers erfolgt über den Datenausgang MISO. Beim<br />
Programmieren werden also drei Signalleitungen benötigt: der Takt SCK, die Eingabedaten MOSI und<br />
die Ausgabedaten MISO. Wie oben erwähnt, werden für die Programmierung drei Standard-Ports<br />
verwendet. Man kann also das Programmieren in der Anwender-Schaltung durchführen. Allerdings ist<br />
dabei zu beachten, dass die dafür drei benötigten Pins entweder<br />
• nur für diesen Zweck reserviert werden,<br />
• andernfalls die Beschaltung der Pins in Richtung Peripherie über Widerstände von mindestens<br />
1 Kiloohm erfolgt (Bild unten, linke Seite), oder<br />
• die Programmierports über eine Multiplexschaltung nur bei aktivem Reset mit dem<br />
Programmiersignal verbunden werden (Bild unten, rechte Seite).<br />
Die Atmel Controller besitzen zudem einen reservierten Speicherbereich in welchen ein eigener<br />
Bootloader geladen werden kann, der dann automatisch bei einem RESET des Controllers ausgeführt<br />
wird. Der Bootloader kann über die Konfigurationsbits des Controllers (Fusebits) eingestellt werden.<br />
Mit den beiden Fusebits BOOTSZ0 und BOOTSZ1 (für Bootsize) kann die Grösse des<br />
Bootloaderspeichers eingestellt werden und das Fusebit BOOTRST aktivoert die Bootladefunktion.<br />
Dementsprechend ändert sich auch der Startpunkt nach einem Reset. Um den Bootloader (und auch<br />
den Programmspeicher) vor ungewolltem Überschreiben zu schützen, sind vier Bootloader Lockbits<br />
(BLB) vorgesehen, die jeweils einen Speicherbereiche mit einem Schreib-/Leseschutz versehen. Diese<br />
Beispiel: Blockschaltung des ATTtiny 140
Mikrocomputertechnik<br />
Lockbits verhindern aber nicht das Auslesen oder Beschreiben über die ISP-Schnittstelle. Mittels<br />
Bootloader kann der AVR-Prozessor beispielsweise auch Programme über eine serielle Schnittstelle<br />
laden (fast wie beim 68HC11).<br />
Die Bedeutung der einzelnen Pins erschließt sich vollständig nur durch das Studium des Datenbuchs.<br />
An dieser Stelle soll jedoch eine kurze Zusammenfassung versucht werden. Dabei wird nur auf Pins<br />
mit speziellen Eigenschaften eingegangen, normale Ein- und Ausgänge werden nicht erwähnt. VCC,<br />
GND, AVCC und AREF dienen der Spannungsversorgung von Digital- und Analogteil des<br />
Controllers. Das Programmierinterface wird durch die Pins RESET, SS, MOSI, MISO und SCK<br />
gebildet. Diese Pins verbindet man mit dem Computer um ein Programm in den Controller zu laden.<br />
RXD und TXD betreffen die serielle Schnittstelle (USART). Die XTAL-Pins erlauben den Anschluss<br />
eines externen Quarzes oder sonstigen Taktgene-rators. Mit den OC-Pins kann ein<br />
pulsweitenmoduliertes Signal erzeugt werden. So kann man mit einem digitalen Pin analoge Signale<br />
erzeugen, indem ein Siebglied nachgeschaltet wird. Die ADC-Pins stellen die Eingänge des<br />
Analog-Digital-Wandlers dar.<br />
Beispiel ATtiny13, einer der kleinsten AVR-Prozessor<br />
• Zentraleinheit mit 32 Arbeitsregistern zu je 8 Bits, R0..R31, intern ca. 9 MHz Takt<br />
• Speicher: 512 Worte Programmspeicher (Flash), 64 Byte EEPROM, 64 Byte RAM<br />
• ein 8-Bit-Timer/Zähler, der Timer wird vom Taktoszillator über Vorteiler (durch<br />
1/8/64/256/1024) getaktet, im Zählermoduls erfolgt die Taktung durch ansteigende oder<br />
abfallende Signale am T0-Pin.<br />
• max. 6 Ein-/Ausgabe-Pins (I/O-Pins), deren Richtung als Ein- oder Ausgang programmierbar<br />
ist. Bei Eingängen sind Pull-Up-Widerstände zuschaltbar. Auslösung von Interrupts bei<br />
Eingang INT0 (PB1) programmierbar oder bei Pegelwechsel bei allen Pins wählbar, mit<br />
Maskierung der auslösenden Pins. Weiterhin enthält er einen zuschaltbarer Analogvergleich<br />
an den Pins AIN0 und AIN1 (PB0 und PB1) (Interrupt bei Wechsel).<br />
• Vier-Kanal AD-Wandler mit 10 Bit Auflösung. Interne Spannungsreferenz 1,1 V oder<br />
Betriebsspannung als Spannungsreferenz.<br />
Als Programmierbeispiel sollen hier die aus dem 68HC11-Praktikum bekannten Zeitschleifen dienen.<br />
Eine Zeitschleife mit einem 8-Bit-Register sieht in <strong>Assembler</strong> folgendermaßen aus:<br />
.equ c1 = 200 ; Anzahl Schleifendurchlaeufe<br />
ldi R16,c1 ; 1 Takt<br />
Loop: ; Schleifenbeginn<br />
nop ; 1 Takt<br />
nop ; 1 Takt<br />
dec R16 ; 1 Takt<br />
brne Loop ; 2 Takte wenn nicht Null, 1 Takt bei Null<br />
Man sieht auch, dass bei einer RISC-Architektur in der Regel jeder Befehl nur einen Takt lang dauert.<br />
Wenn's länger dauern soll, nimmt man eine Zeitschleife mit einem 16-Bit-Doppelregister:<br />
.equ c1 = 0 ; laengste Dauer 2^16 Durchlaeufe<br />
ldi R25,HIGH(c1) ; R25 laden, 1 Takt<br />
ldi R24,LOW(c1) ; 1 Takt<br />
Loop: ; Schleifenbeginn<br />
nop ; 1 Takt<br />
nop ; 1 Takt<br />
sbiw R24 ; 16-Bit-Dekrement, 2 Takte<br />
brne Loop ; 2 Takte wenn nicht Null, 1 Takt bei Null<br />
Damit sind wir beim beliebten "Hello World" für kleine Controller: Die im Sekundenrhytmus<br />
blinkenden LED an einem Port:<br />
.inc "tn13def.inc" ; Definitionen fuer einen ATtiny13<br />
Beispiel: Blockschaltung des ATTtiny 141
.equ c1 = 60000 ; Bestimmt die Blinkfrequenz<br />
sbi DDRB,0 ; Portbit als Ausgang programmieren<br />
Loop:<br />
sbi PORTB,0 ; Portbit auf high<br />
rcall Delay ; UP-Aufruf<br />
cbi PORTB,0 ; Portbit auf low<br />
rcall Delay ; UP-Aufruf<br />
rjmp Loop<br />
Delay: ; Unterprogramm fuer Warteschleife<br />
ldi R25,HIGH(c1) ; wie oben gezeigt<br />
ldi R24,LOW(c1)<br />
Delay1:<br />
nop<br />
nop<br />
nop<br />
nop<br />
nop<br />
sbiw R24,1<br />
brne Delay1<br />
Von Atmel selbst wird eine komplette Entwicklungsplattform angeboten (<strong>Assembler</strong>, Simulator usw.),<br />
die man von der Atmel-Webseite herunterladen kann. Zusätzlich existiert eine komplette<br />
C-Entwicklungsplattform auf der Basis des GNU-Compilers (Open Source). Näheres dazu liefert der<br />
Link zu "tuxgraphics.org" unten. Des weiteren wird noch ein Compiler für einen Basic-Dialekt<br />
namens BASCOM-AVR angeboten, der aber nicht kostenlos ist.<br />
Für Einsteiger in den Bereich der Mikrocontroller und Elektronik ist besonders das Arduino-Projekt<br />
interessant, das eine günstige Entwicklungsplattform zur Verfügung stellt. Die Hardware-Seite besteht<br />
aus verschiedenen einfachen Controllermodulen, die über USB (Emulation einer seriellen<br />
Schnittstelle) mit dem PC kommunizieren. Die Softwareentwicklung erfolgt in einer integrierten<br />
Open-Source-Entwicklungumgebung, die bereits viele Bibliotheken für die Ansteuerung der Hardware<br />
mitbringt. Außerdem gibt es eine große Community, die dieses System einsetzt und unterstützt.<br />
Literatur<br />
Atmel-Webseite<br />
Günter Schmitt: Mikrocomputertechnik mit Controllern der Atmel-AVR-RISC-Familie, Oldenbourg<br />
Verlag<br />
Claus Kühnel: Programmieren der AVR-RISC-Mikrocontroller mit BASCOM-AVR, Skript Verlag<br />
Kühnel<br />
Weiterführende Links<br />
Mikrocomputertechnik<br />
http://www.atmel.com/products/avr/<br />
http://shop.avr-praxis.de/index.html<br />
http://tuxgraphics.org/electronics/200904/avr-c-programming.shtml<br />
http://imakeprojects.com/Projects/avr-tutorial/<br />
/http://www.avr-projekte.de/<br />
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial<br />
http://www.mcselec.com (Bascom und Demo)<br />
6.2 PIC-Microcontroller von Microchip<br />
Von Microchip werden inzwischen mehr als 400 unterschiedliche Flash-Controller angeboten, die im<br />
Baukastensystem aus einem Prozessorkern, Speicher und einigen Peripheriemodulen<br />
zusammengesetzt sind. Anhand des Prozessorkerns kann man fünf Familien unterscheiden:<br />
Beispiel: Blockschaltung des ATTtiny 142
• Controller mit 12-Bit-Kernel (PIC10Fxxx, PIC1xF50x) - Minmalsysteme,<br />
• Controller mit 14-Bit-Kernel (PIC16Fxxx, PIX12Fxxx), seit vielen Jahren in Verwendung,<br />
haben sich zu den Arbeitspferden entwickelt,<br />
• Controller mit 16-Bit-Kernel (PIC18Fxxx, PIC18FxxJxx, PIC18FxxKxx), räumen mit einigen<br />
Mängeln der 14-Bit-Kernel auf (linear adressierbarer großer Speicher),<br />
• Controller mit 24-Bit-Kernel (PIC24, dsPIC30Fxxx, dsPIC33Fxxxx), haben 16 Bit<br />
Datenworte, einige eignen sich für digitale Signalverarbeitung,<br />
• Controller mit 32-Bit-Kernel (PIC32MXxxx), haben einen MIPS32-Kern und sind<br />
dementsprechend rechenstark, mit den urspünglichen PIC-Microcontrollern haben sie außer<br />
dem Namen nichts mehr gemein.<br />
Die Bit-Angabe hat in diesem Fall ausnahmsweise nichts mit der Datenwortbreite des jeweiligen<br />
Controllers zu tun, sondern mit der Breite der Befehlsworte des PIC. Ein größerer Wert deutet also auf<br />
einen komplexeren Controller mit leistungsfähigerem Befehlssatz hin. Alle Typen der PIC16XX- und<br />
PIC18XX-Familien verfügen über einen sehr kompakten RISC-Befehlssatz, unterschiedlichste<br />
On-Chip Peripherie, verschieden ausgeführte Programm- und Datenspeicher sowie über<br />
Gehäuseausführungsvarianten. Die CPU dieser Mikrocontrollerfamilien zeichnet sich aus durch eine<br />
strikte Trennung von Programm- und Datenspeicher und durch die Möglichkeit, gleichzeitig auf diese<br />
Speicher über getrennte Busse zuzugreifen, (Harvard-Architektur). Die folgende Tabelle soll einen<br />
knappen Überblick aller PICs vermitteln:<br />
12-Bit-Kernel 14-Bit-Kernel 16-Bit-Kernel<br />
Datenwort 8 Bit<br />
Befehlswort 12 Bit<br />
256 ..<br />
Programmspeichergröße 2k<br />
Worte<br />
EEPROM-Größe 0<br />
16 ..<br />
RAM-Größe<br />
134<br />
Byte<br />
Stack-Tiefe 2<br />
Interrupts keine<br />
4 MHz<br />
max. Taktfrequenz .. 20<br />
MHz<br />
verschiedene Befehle ~33<br />
Hardwaremultiplikation nein<br />
klein, billig, leistungsschwach -<br />
geeignet, um alte PIC-Software<br />
(12-Bit-PICs ohne Flash) weiter<br />
zu nutzen.<br />
Mikrocomputertechnik<br />
Datenwort 8 Bit<br />
Befehlswort 14 Bit<br />
1 .. 8k<br />
Programmspeichergröße Worte -<br />
segmentiert<br />
EEPROM-Größe<br />
0 .. 256<br />
Byte<br />
RAM-Größe<br />
64 .. 368<br />
Byte<br />
Stack-Tiefe 8<br />
Interrupts einfach<br />
max. Taktfrequenz<br />
4 MHz .. 20<br />
MHz<br />
verschiedene Befehle ca. 35<br />
Hardwaremultiplikation nein<br />
Eingeführte Standardtypen, für die<br />
viele Anwendungen zur Verfügung<br />
stehen.<br />
Beispiel: Blockschaltung und Pins des PIC16F84<br />
Datenwort 8 Bit<br />
Befehlswort 16 Bit<br />
4k .. 128k<br />
Programmspeichergröße Byte -<br />
linear<br />
0 .. 1024<br />
EEPROM-Größe<br />
Byte<br />
256 ..<br />
RAM-Größe<br />
3936<br />
Byte<br />
Stack-Tiefe 31<br />
Interrupts priorisiert<br />
4 MHz ..<br />
max. Taktfrequenz<br />
40 MHz<br />
verschiedene Befehle ca. 75<br />
Hardwaremultiplikation ja 8 Bit<br />
Optimiert für den Einsatz von<br />
höheren Programmiersprachen.<br />
6.2 PIC-Microcontroller von Microchip 143
Mikrocomputertechnik<br />
Ähnlich wie bei den Atmel-Prozessoren ist auch bei den PICs die Taktung recht einfach. Der<br />
Controller kann seinen Takt von einer externen Quelle erhalten oder mit einem internen Oszillator<br />
erzeugen. Letzterer kann entweder extern beschaltet werden (RC-Glied oder Quarz) oder der Takt<br />
wird komplett intern erzeugt. Dabei bietet nicht jeder PIC-Typ alle Möglichkeiten.<br />
Wie man aus der Tabelle erkennen kann, gibt es für <strong>Assembler</strong>-Programmierer zwei<br />
Herausforderungen:<br />
• Die Stacktiefe und damit die Zahl der verschactelten Unterprogrammaufrufe ist<br />
hardwaremäßig begrenzt.<br />
• Bei etlichen Typen ist der Arbeitsspeicher segmentiert, d.h. in einzelne Speichersegmente<br />
bzw. -seiten unterteilt, was beispielsweise die Größe von Arrays begrenzt.<br />
Als Beispiel für den Aufbau des Prozessors soll hier der Type 16Fxx dienen, dessen Blockschaltung<br />
und Pinbelegung oben abgebildet sind. Die PIC16xx-Mikrocontroller haben einen RISC-Befehlssatz<br />
mit nur 35 Befehlen, so dass die maschinennahe Programmierung in <strong>Assembler</strong>syntax im Vergleich zu<br />
CPUs mit umfangreicheren Befehlssätzen relativ aufwendig ist. Alle Mitglieder der PIC16xx-Familie<br />
verfügen über Power-On Reset und Watchdog Timer. Unterschiede liegen vor allem in der<br />
verschiedenen Ausstattung mit On-Chip Peripheriekomponenten.<br />
Die Mikrocontroller der PIC16F8x-Gruppe und der PIC16C84 sind nur mit einer geringen Anzahl von<br />
On-Chip-Komponenten ausgestattet, die aber für viele typische Mikrocontolleranwendungen völlig<br />
ausreichend ist. Er verfügt über zwei Ports mit insgesamt 13 Pins, die jedoch über eine relativ große<br />
Beispiel: Blockschaltung und Pins des PIC16F84 144
Mikrocomputertechnik<br />
Treiberfähigkeit verfügen, so dass LEDs problemlos direkt angeschlossen werden können. Ein<br />
8-Bit-Timer mit programmierbarem Vorteiler (1:1, 1:2, 1:4 bis 1:256) kann für Zeitgeber bzw.<br />
Zählerfunktionen eingesetzt werden. Auch bei den PIC müssen On-Chip-Funktionen über ein<br />
Konfigurationswort definiert werden, welches beim Programmiervorgang des Zielcontrollers auf eine<br />
spezielle Speicherstelle geschrieben werden muss.<br />
Bei der Programmierung spielt ein dem Akkumulator ähnliches Arbeitsregister W eine wichtige Rolle,<br />
mit dem alle arithmetischen und logischen Operationen durchgeführt werden. Dabei erfolgt die<br />
Verarbeitung der Daten prinzipiell in drei Schritten:<br />
1. Hole ein Byte aus dem RAM in das Arbeitsregister W<br />
2. Führe die gewünschte Operation aus<br />
3. Lege das Ergebnis im RAM ab<br />
Neben einer direkten Datenadressierung im RAM und einer besonderen Adressierung von<br />
Tabellenelementen im Codespeicher gibt es noch eine indirekte Adressierungsart. Dazu wird in das<br />
FSR (File Select Register) die Adresse der entsprechenden RAM-Speicherzelle geschrieben. Über das<br />
IND-Register kann nun auf die RAM-Speicherzelle schreibend oder lesend zugegriffen werden. Der<br />
PIC 16F84 besitzt einen 13 Bit breiten Programmzähler, der einen Programmspeicher von 8k Worten<br />
adressieren könnte. Der Adressbereich 0x0000-0x03FF (1 K Worte) ist physikalisch implementiert.<br />
Der Resetvektor liegt auf der Adresse 0; der Interruptvektor auf der Adresse 4. Der Datenspeicher<br />
unterteilt sich in das RAM (68 x 8 Bit, Adressbereich von 0x0C 0x4F) und im unteren<br />
Speicherbereich (0x00 0x0B) die I/O-Register. Diese Register werden als Special-Function-Register<br />
(SFR) bezeichnet.<br />
Das RAM wird auch als General-Purpose-Register (GPR) bezeichnet. Der Speicher ist in zwei Seiten<br />
(Bank 0 und Bank 1) unterteilt, die durch das Statusregister auswählbar sind. Bank 1 enthält die<br />
gleiche Anzahl von Speicherstellen wie Bank 0, wobei die General-Purpose-Register aus Bank 0<br />
gespiegelt sind, also auf beiden Seiten erreichbar sind. Einige Register sind jedoch nur über eine<br />
Speicherbank zu erreichen. Dazu zählen das OPTION- und das TRIS-Register, die auf Bank 1 als<br />
normale Register zu erreichen sind.<br />
Der 64 x 8 Bit große EEPROM-Bereich hat die Adressen 0x00 0x3F und ist sowohl lesbar als auch<br />
beschreibbar. Es bietet sich an, wenn Daten zu speichern sind, die auch nach dem Abschalten der<br />
Betriebsspannung erhalten bleiben müssen (z.B. Kalibrierdaten). Auf das EEPROM kann nicht direkt<br />
zugegriffen werden, sondern der Zugriff erfolgt über vier spezielle Register: EECON1, EECON2,<br />
EEADR, EEDAT.<br />
Speicherbelegung des PIC16F84 (nach Microchip-Unterlagen)<br />
Beispiel: Blockschaltung und Pins des PIC16F84 145
Wie schon im Atmel-Abschnitt geschildert, verfügen auch die PIC-Prozessoren über die Möglichkeit<br />
der ISP-Programmierung. Dazu liefert Microchip eine passende Programmier-Hardware an. Derzeit<br />
aktuell ist der MPLAB PICkit 3 (weiterhin erhältlich ist der PICkit 2). Er ermöglicht das Debuggen<br />
und die Programmierung der PIC-Mikrocontroller mithilfe des MPLAB Integrated Development<br />
Environment (IDE). Der MPLAB PICkit 3 wird per USB-Schnittstelle am PC angeschlossen und<br />
verwendet zwei Portleitungen und den Reset-Anschluss zur Programmierung.<br />
Literatur<br />
Günter Schmitt: PIC-Mikrocontroller, Oldenbourg Verlag<br />
http://www.microchip.com/<br />
Weiterführende Links<br />
http://www.microchip.com/<br />
http://www.microchipdirect.com/<br />
http://www.olimex.com/<br />
http://www.sprut.de/electronic/pic/<br />
Mikrocomputertechnik<br />
Beispiel: Blockschaltung und Pins des PIC16F84 146
Mikrocomputertechnik<br />
6.3 MSP-430-Microcontroller von Texas Instruments<br />
Dies ist eine relativ neue 16-Bit Mikrocontrollerfamile, die speziell für Lowpower-Anwendungen<br />
entwickelt wurde. Es handelt sich um Controller mit:<br />
• 16-Bit Risc-Controllerkern<br />
• Einfacher Befehlssatz (nur 27 Befehle)<br />
• Takt: 8/16 MHz bei der MSP430F2xxx-Serie bzw. 25MHz bei der MSP430F5xxx-Serie<br />
• 1 KByte bis 256 KByte integrierter Flashspeicher<br />
• 256 Byte bis 16 KByte integriertes RAM<br />
• Peripherieeinheiten je nach Typ, z. B. USART, analoge Spannungskomparatoren,<br />
A/D-Wandler mit 10, 12 oder 16 Bit Auflösung, DA-Wandler, Timer<br />
• internes EEPROM<br />
• USB 2.0 Full Speed Interface<br />
• JTAG-Interface für Programmierung und Debugging<br />
• Betriebsspannung zwischen 1,8 und 3,6 V<br />
• Sehr geringe Stromaufnahme: 0.1 µA im Off-Modus, 0.8 µA im Standby und 250 µA / MIPS<br />
im Normalbetrieb<br />
Blockschema des MSP430<br />
Texas Instruments erweitert die Familie laufend, was auf einen großen Erfolg dieser Controllerlinie<br />
hindeutet. Der MSP430 besitzt eine Von-Neumann-Architektur. Die Größe des adressierbaren<br />
Speichers ist bei den meisten Typen auf 64 KByte limitiert. Je nach Modell können die<br />
Speichergrößen aber auch bis zu 256 KByte Flash und 16 KByte RAM umfassen. Bei allen<br />
Familienmitgliedern sind die untersten 2 KByte für interne Funktionen, z. B. einen Boot-Loader,<br />
reserviert. Seit 2007 wird auch eine Fami-lie mit der so genannten MSP430X-CPU angeboten. Deren<br />
Speichermodell kann bis zu 1 MByte Speicher adressieren (20 Bit Adressbus). Daher sind hier auch<br />
alle Register 20 Bit breit.<br />
Der Hardwaremultiplizierer erlaubt die Multiplikation von 8-Bit- und 16-Bit-Zahlen (mit/ohne<br />
Vorzeichen), wobei als Ergebnis eine bis zu 32 Bit große Zahl entsteht. Der jüngste Typ kann<br />
32-Bit-Operanden multiplizieren (64-Bit-Resultat). Er beherrscht weiterhin Multiplizieren und<br />
Addieren (MAC) wie ein DSP. In den untersten 16 Bytes sind spezielle Register (SFR, Special<br />
6.3 MSP-430-Microcontroller von Texas Instruments 147
Function Register) für die Interrupt- und "Modul"-Steuerung eingeblendet. Die Register der<br />
8-Bit-Peripherie belegen die folgenden Adressen ($010 bis $0FF). Die darauf folgenden 255 Bytes<br />
($100 bis $1FF) sind für 16-Bit-Peripherie reserviert (Speicherzugriff wortweise). Der<br />
Mikrocontroller verfügt über 16 Interrupt-Vektoren, welche zum Teil maskierbar sind. Beim MSP430<br />
sind nur die beiden höchsten Prioritäten nicht maskierbar, somit können nur diese beiden nicht in ihrer<br />
Funktion beeinflusst werden.<br />
Der Takt kann auf drei Arten erzeugt werden, die je nach Bedarf sehr geringen Stromverbrauch<br />
(32,768 kHz in Form eines Uhrenquarz), sehr schnelles Aufwachen nach einem Interrupt (interner<br />
RC-Oszillator) oder hohe Frequenz (bis zu 16 MHz) ermöglichen. Je nach Typ gibt es einem oder<br />
zwei Eingänge für Quarzoszillatoren sowie einen internen RC-Oszillator, dessen Frequenz in weiten<br />
Bereichen eingestellt werden kann. Die MSP430-Serie wurde konsequent für batteriebetriebene<br />
Lowpower-Anwendungen konzipiert. Typische Anwendungen sind Geräte mit Langzeitbatterie, wie<br />
zum Beispiel Energiezähler, Datenlogger oder auch Blutdruckmessgeräte. Die Peripherieeinheiten der<br />
Controller sind recht leistungsfähig und ihre Programmierung relativ einfach. Nachteilig für den<br />
Bastler ist lediglich die Tatsache, dass die Controller nur SMD-Bauformen (SO- oder TQFP-Gehäuse)<br />
erhältlich sind.<br />
Neben Parallel- und Seriellports sind die Mitglieder der MSP430-Familie (je nach Typ) mit<br />
Analogperipherie bestückt. Die Analog-Digital-Wandler haben eine Auflösung von 10, 12, 14 oder 16<br />
Bit, wobei je nach Typ des MSP430 als Wandlungsverfahren suk-zessive Approximation, Rampenoder<br />
Sigma-Delta-Verfahren eingesetzt wird. Die Digital-Analog-Wandler haben eine Auflösung von<br />
8 oder 12 Bit. Als Referenzspan-nung können hier wie bei den Komparatoren und A/D-Wandlern die<br />
internen oder externen Referenzen benutzt werden. Der Ausgangsverstärker kann automatisch<br />
kalib-riert werden, damit die Ausgangsspannung korrekt den digitalen Werten folgt. Der D/A-Wandler<br />
kann mit bis zu 550 kHz getaktet werden.<br />
Der MSP430 besitzt 16 Register, wobei vier von ihnen fest belegt sind. Register 0: Program-Counter,<br />
Register 1: Stack-Pointer, Register 2: Status-Register und Register 3: Constant-Generator. Diese vier<br />
Register haben spezielle Funktionen, sind aber wie alle anderen zwölf Register auch frei benutzbar.<br />
Der MSP430 beherrsch die komplette Palette der Adressierungsarten: Register-Adressierung,<br />
indizierte Adressierung, absolu-te Adressierung sowie indirekte Adressierung mit und ohne<br />
Autoinkrement. Der Befehlssatz beinhaltet 27 Grundbefehle und 24 "emulierte" Befehle, die aus den<br />
Grundbefehlen zusammengesetzt sind. Die Dauer der Befehlsabarbeitung dauert befehlsabhängig<br />
zwischen eins und sechs Taktzyklen. Der Prozessor ist in C und <strong>Assembler</strong> programmierbar. Für die<br />
Softwareentwicklung stehen verschiedene Compiler zur Ver-fügung. Auf der Website von TI gibt es<br />
eine auf 4 KByte begrenzte Version des IAR-C-Compilers (Kickstart-Version), der neben dem<br />
Compiler auch eine vollständige IDE mit Debugger usw. bietet. Seit einiger Zeit stellt TI auch eine<br />
vollständige Entwicklungsumgebung für den MSP430 auf Eclipse-Basis unter dem Namen<br />
"CCEssentials" zur Verfügung. Diese Entwicklungsumgebung enthält einen C-Compiler, der auf 16<br />
KByte begrenzt ist. Außerdem gibt es für die MSP430-Serie auch eine Version des GCC-Compilers<br />
inklusive Debugger für Linux und Windows.<br />
Literatur:<br />
Lutz Bierl: Das große MSP430 Praxisbuch, Franzis-Verlag<br />
Matthias Sturm: Mikrocontrollertechnik am Beispiel der MSP430-Familie, Hanser-Verlag<br />
Chris Nagy: Embedded Systems Design Using the TI MSP430 Series, Nownos<br />
Weiterführende Links<br />
Mikrocontroller-Net<br />
Entwicklungsboard für knapp 5 Euro<br />
University of Colorado<br />
Mikrocomputertechnik<br />
Blockschema des MSP430 148
http://www.olimex.com/<br />
6.4 8051-Microcontroller<br />
Mikrocomputertechnik<br />
Bei der 8051-Familie handelt es sich um 8-Bit-Mikrocontroller der ersten Generation (Anfang der<br />
1980er Jahre) von Intel. Trotzdem werden Prozessoren mit 8051-Kern nach wie vor von<br />
verschiedenen Herstellern produziert. Eigentlich ist der 8051 für heutige Verhältnisse zu langsam und<br />
nicht mehr zeitgemäß. Der große Vorteil der 8051-Familie begründet sich durch die große Auswahl an<br />
Controllern mit sehr unterschiedlicher Hardwareausstattung. So gibt es sie mit SPI-, I2C-, CAN-,<br />
USB-, RS232-, Profibus-, LIN- oder Ethernetschnittstelle, mit Analog-Digital- und<br />
Digital-Analogwandlern, Timern, Capture-and-Compare-Einheiten usw. Softwareseitig sind alle diese<br />
Controller kompatibel mit dem Ur-8051, solange die spezielle Erweiterungen der neueren Typen nicht<br />
verwendet werden. Aufgrund der unterschiedlichen Befehlslängen von einem bis zu drei Byte sowie<br />
den unterschiedlichen Ausführungszeiten für einen Befehl handelt es sich eindeutig um eine<br />
CISC-Architektur. Das folgende Bild zeigt die Blockschaltung des Prozessors und einige<br />
Erweiterungen.<br />
Blockschema des 8051<br />
Aktuellere Vertreter dieser Familie sind z. B. die MicroConverter von Analog Devices, die<br />
AT89-Familie von Atmel, die MSC12-Familie von Texas Instruments oder die DS89C430 von Maxim<br />
(Dallas). Allen Modellen ist gemeinsam:<br />
• 8-Bit Prozessorkern mit einheitlichem Befehlssatz<br />
• mindestens 128 Bytes internes RAM<br />
• externes RAM und ROM<br />
• ein einheitliches Adressierungsmodell für so genannte Special Function Register (SFR)<br />
• Full-Duplex-UART<br />
• 5 Interrupt-Quellen<br />
• 2 Interrupt-Prioritäten<br />
• diverse Timer<br />
Ein Befehlszyklus entspricht in der ursprünglich von Intel entwickelten Struktur einem bis drei<br />
Maschinenzyklen. Ein Maschinenzyklus entspricht 12 Taktzyklen. Heute übliche Varianten des 8051<br />
kommen hingegen meist mit nur zwei Taktzyklen pro Maschinenzyklus aus. Damit ist bei gleicher<br />
6.4 8051-Microcontroller 149
Taktfrequenz eine deutlich höhere Befehlsabarbeitung möglich. Eine Besonderheit dieses Prozessors<br />
ist der Bitprozessor, der eine schnelle und einfache Bitmanipulation erlaubt.<br />
Später wurde sogar eine Version des 8051 mit integriertem EEPROM und BASIC-Interpreter unter<br />
der Typenbezeichnung 8052AH angeboten, die es erlaubte über die serielle Schnittstelle zu<br />
kommunizieren und Programm einzugeben und diese dann im internen EEPROM abzulegen - fast wie<br />
bei den frühen Heimcomputern.<br />
Darüber hinaus gibt es von verschiedenen Firmen erweiterte MCS-51-Mikrocontroller, z. B. die von<br />
Infineon in NMOS-Technik produduzierten Modelle 80515 (8192 Bytes ROM, 256 Bytes RAM, drei<br />
16-Bit-Timer, UART, zwei externe Interruptquellen, PWM, 8-fach-A/D-Wandler) oder 80535<br />
(externes ROM/EEPROM, 256 Bytes RAM, drei 16-Bit-Timer, UART, zwei externe Interruptquellen,<br />
PWM, 8-fach-A/D-Wandler).<br />
Wegen der großen Verbreitung der 8051-Familie gibt es auch eine Vielzahl von synthetisierbaren<br />
MCS-51-Implementierungen. Diese sind als IP-Cores in einer Hard-warebeschreibungssprache wie<br />
beispielsweise VHDL verfügbar. Sie eignen sich für den Einsatz in FPGAs und<br />
anwendungsspezifischen integrierten Schaltungen (ASICs). Typische Anwendungsbeispiele sind<br />
USB-Controller, wie sie in Druckern oder Schnittstellenadaptern eingesetzt werden. In diese sind zur<br />
Steuerung der diversen Protokolle MCS-51-Mikrocontroller integriert.<br />
Literatur:<br />
Mikrocomputer SAB 8051 Befehlsliste. Hrsg. von der Siemens AG<br />
Andreas Roth: Das Microcontroller Kochbuch MCS51, mitp Verlag<br />
J. Walter: Mikrocomputertechnik mit der 8051-Controller-Familie, Springer 2008<br />
Weiterführende Links<br />
Wikipedia<br />
8051 Projects<br />
Paul's 8051 Tools, Projects and Free Code<br />
8051 Befehlsliste<br />
Zum vorhergehenden Abschnitt Zum Inhaltsverzeichnis Zum nächsten Abschnitt<br />
Copyright © FH München, FB 04, Prof. Jürgen Plate<br />
Mikrocomputertechnik<br />
Mikrocomputertechnik<br />
Prof. Jürgen Plate<br />
Blockschema des 8051 150
7 Anhang<br />
7.1 Literatur und Links<br />
Literatur<br />
Arnulf Wallrabe:<br />
Mikrocontrollerpraxis<br />
Einstieg mit dem 68HC11<br />
Hanser Verlag<br />
Dieses Buch beschreibt den Prozessor sehr viel ausführlicher als das Werk von Rose (s. u.) und bringt<br />
auch viele Beispiele. Dafür kommt hier die Beschreibung der einzelnen Befehle zu kurz. Aufgrund des<br />
Inhaltes und des Preises ist es nach meiner Ansicht noch am besten als Begleitung zur Vorlesung<br />
geeignet. Auch hier liegt eine Programmdiskette bei.<br />
Michael Rose:<br />
Mikroprozessor 68HC11<br />
Architektur und Applikation<br />
Hüthig Verlag<br />
Das Buch beschreibt den Befehlssatz recht ausführlich, aber es gibt kaum kleinen Beispiele zu den<br />
Befehlen. Die umfangreicheren Beispiele im letzten Drittel des Buchs beziehen sich auf ein<br />
bestimmtes System. Das Buch ist relativ teuer, da neben einer Programmdiskette auch eine Platine für<br />
den Aufbau des Mustersystems beiliegt.<br />
Ludwig Orgler:<br />
MC68HC11 Microcontroller<br />
Franzis Verlag<br />
Sehr Hardware- und Schaltungsorientierte Anleitung. Auch hier fehlt die Beschreibung der Befehle.<br />
Das Buch ist eher etwas für Praktiker, die schon erste Erfahrungen mit dem Prozessor gesammelt<br />
haben. Auch hier liegt eine Diskette bei.<br />
Rainer Bermbach:<br />
Embedded Controller<br />
Hanser Verlag<br />
Dieses Buch macht mit dem Aufbau von Embedded Controllern auf INTEL-Basis vertraut<br />
(80186-Familie). Eine recht ordentliche Einführung in die <strong>Assembler</strong>-Programmierung. Auf der<br />
CD-ROM zum Buch gibt es eine komplette Entwicklungsumgebung, ein Tutorial und Datenblätter.<br />
Rainer Kelch:<br />
Rechnergrundlagen - Von der Binärlogik zum Schaltwerk<br />
Fachbuchverlag Leipzig<br />
Rainer Kelch:<br />
Rechnergrundlagen - Vom Rechenwerk zum Universalrechner<br />
Fachbuchverlag Leipzig<br />
Beide Bücher fühen von der Digitaltechnik bis hin zum fertigen Prozessor und behandeln dabei auch<br />
Informationtheorie, Zahlendarstellung und binäres Rechnen. In jedem Buch steckt eine CD mit<br />
7 Anhang 151
weiteren Infos und Lernprogrammen.<br />
Ausserdem gibt es noch die englischen Referenz-Handbücher von Motorola, das nur von Motorola<br />
selbst bezogen werden kann:<br />
M68HC11 Reference Manual und M68HC11 Technical Data<br />
Das Reference-Manual ist hier abrufbar:<br />
68HC11 Reference Manual (PDF, 3 MByte) und<br />
68HC11 Reference Manual (PS, 0,9 MByte).<br />
68HC11 Links<br />
• The MIT Handy Board<br />
• Motorola Microcontollers<br />
• HC11 FAQ<br />
• Axiom Manufacturing<br />
• Technological Arts<br />
• Windows-based Simulator (THRSIM11)<br />
• Another Windows-based Simulators<br />
Latest version<br />
• Roger's Embedded Microcontrollers Home Page<br />
• Course Notes: Digital Logic and Computer Systems<br />
• Circuit Cellar, The Computer Applications Journal<br />
• The Magazine of Electronics Technology<br />
Freeware 68HC11 C Compilers<br />
• Small C - Small-C ported to the 68HC11 (includes C source code).<br />
• ICC11 - An older version (v0.50) of the ImageCraft 68HC11 C compiler.<br />
• gcc11 - A version of the GNU compiler for the 68HC11, ported by Coactive Aesthetics.<br />
• Interactive C - Originally developed for the MIT LEGO Robot (6.270) Contest, IC provides a<br />
subset of C in an integrated development environment.<br />
Commercial 68HC11 C Compilers<br />
Mikrocomputertechnik<br />
• ImageCraft - A low-cost but high-quality compiler, which includes an optimizer,<br />
floating-point support, assembler, linker, and librarian. Available in DOS command line<br />
($75), Windows IDE ($130), and Linux command line ($75) versions. The only major missing<br />
features are true 32-bit longs, and support for in-circuit emulators, though they offer the<br />
"NoICE" monitor/debugger for $30.<br />
• Dunfield - This reasonably-priced ($100) compiler includes an assembler, linker, librarian,<br />
library (with ASM source), monitor (with source), and various utilities and sample programs.<br />
It lacks intrinsic support for the "long" and "float" data types, doesn't support typedef's,<br />
enum's or bitfields, and only the first 15 characters of symbol names are significant. The<br />
documentation is decent, but you'll have to print it out yourself -- it's only supplied on disk.<br />
Dunfield also has low-cost compilers available for many other microcontrollers, including a<br />
freeware one for MS-DOS that produces very small and fast executables.<br />
• IAR Systems - It is also a high-end (starting at $1400) compiler, with good industry support.<br />
Documentation is fair -- good in spots, poor in others, with the most pronouced weakness<br />
being poor organization and indexes. ANSI compliance is excellent, as is optimization,<br />
especally with the most recent upgrade (v4.11). The only major omissions are lack of library<br />
source, and no in-line assembly (all ASM code must be in separate files).<br />
Literatur 152
Mikrocomputertechnik<br />
• Cosmic - This is a professional-level compiler (starting at about $1500) with support for most<br />
major emulators and debuggers. Documentation was voluminous, and poorly written, but<br />
adequate. Library source was included; however, the source comments were in French.<br />
Download their Evaluation Kit and try it out.<br />
• Introl - They have both hobbyist ($150) and professional ($2000) HC11 compilers, offering<br />
full ANSI compliance, library source, an assembler, a linker, and a debugger. They also have<br />
similar products for the entire Motorola line (6805, 6808, 6809, 68HC12, 68HC16, and 68300<br />
families). Demos are available for download.<br />
• Avocet - Avocet is a well-respected name in embedded development tools. They have two<br />
families of C compilers. AVCASE is $1595 and includes Avocet C, a macro assembler, a<br />
monitor debugger, and a simulator. They've also taken over the 2500 AD line of products,<br />
which includes a C compiler ($815), assembler ($415), and simulator ($365). Demos are<br />
available for download.<br />
• HI-Tech - A high-end compiler at a mid-range price (~$850), it boasts full ANSI C<br />
compilance, an optimizing compiler, assembler, linker, library with full source, and a<br />
source-level debug monitor.<br />
• Archimedes - A high-end ($1395 to $2995) HC11 compiler for Windows; also versions for<br />
other Motorola processors (HC12, HC16, and 683XX). 30-day money-back guarantee. Demo<br />
can be downloaded from web site.<br />
• Newton Labs - Makers of a commercial version of Interactive C, with prices ranging from $35<br />
to $100, and versions for Windows 95/Windows NT, Macintosh, and various Unix platforms.<br />
The commercial version includes support for more Standard C features, as well as a better<br />
integrated environment, extensive peripheral libraries, and professional documentation.<br />
7.2 Tips zur Programmierung<br />
Der eigentlichen Programmierung (=Codierung) geht eine Entwurfsphase voraus:<br />
• Konzeption des Programms<br />
Vorüberlegungen zum Programm: Aufgaben, Umfang, Wirtschaftlichkeitsbetrachtungen,<br />
Termine, Personal<br />
• Grobentwurf<br />
Lösungswege und Konzepte entwickeln, Aufgabenumfang festlegen, Randbedingungen<br />
prüfen (z.B. SPeicherplatz, Geschwindigkeit)<br />
• Detailentwurf, Modularisierung<br />
Genaue Definition von Programmeigenschaften und Benutzerschnittstelle, Anforderungen<br />
(z.B. Rechengenauigkeit, Fehlerbehandlung, Hardwareabhängigkeit, ....). Festlegen von<br />
Datenstrukturen und des Aufgabenumfangs der einzelnen Module.<br />
• Überprüfung des Entwurfs am Schreibtisch<br />
Möglichst durch jemand anderen den Entwurf überprüfen lassen.<br />
• Dann folgt Codierung und Test der Programmmodule und anschließend:<br />
♦ Integration der Module zum Programm<br />
♦ Test des Gesamtprogramms und Korrektur<br />
♦ Parallel zur Programmierung: Dokumentation und Bedienungshandbuch<br />
Durch Testen von Programmen kann man nur<br />
deren Fehlerhaftigkeit feststellen<br />
- aber niemals deren Korektheit!<br />
68HC11 Links 153
Grundlegende Prinzipien:<br />
Es ist unmöglich, ein Programm Narrensicher<br />
zu machen, weil Narren zu erfindungsreich sind!<br />
• In kleinen überschaubaren Schritten vorgehen. Nicht zuviel zur gleichen Zeit machen.<br />
• Große Projekte in kleine, logisch zusammengehörende Einheiten (Module) zerlegen. Die<br />
Module so autonom wie möglich auslegen und separat testen.<br />
• Ablauf so einfach wie möglich gestalten. Das macht die Programme leichter lesbar und<br />
durchschaubarer.<br />
• Beim Entwurf (und Dokumentation) grafische Möglichkeiten (Flußdiagramme,<br />
Struktogramme, etc.) und Pseudocode nutzen.<br />
• Den ersten Entwurf so klar und einfach wie möglich halten. Optimieren können Sie später<br />
(falls überhaupt nötig).<br />
• Systematisch vorgehen. Checklisten verwenden. Beim Test Grenzfälle beachten.<br />
• Keine Algorithmen verwenden, die man nicht verstanden hat.<br />
• Berücksichtigen Sie Debugging, Test und Wartung schon beim Erstellen des Programms (z.<br />
B. Ausgabeanweisungen und Überwachungsprozeduren, die später auskommentiert werden).<br />
• Fangen Sie mit dem Kodieren erst an, wenn der Entwurf komplett steht.<br />
• Schreiben Sie Programme so, daß Änderungen leicht möglich sind. Vermeiden Sie<br />
Seiteneffekte in Unterprogrammen oder Sprünge aus Unterprogrammen in andere (weil da<br />
zufällig Code steht, der "passt").<br />
• Behalten Sie trotz Modularisierung das Gesamtprogramm im Auge. Testen Sie die Interaktion<br />
zwischen Modulen gleich und nicht erst bei der Gesamtintegration.<br />
• Bei komplexen Daten ist das Design von Datenstrukturen genauso wichtig, wie das<br />
Programmdesign.<br />
• Versuchen Sie nicht, neu entwickelte Hardware und die Software dazu gleichzeitig zu testen.<br />
Programm-Dokumentation<br />
Mikrocomputertechnik<br />
Die Programmdokumentation besteht nicht nur aus dem kommentierten Listing, sondern aus:<br />
• Beschreibung der grundsätzlichen Wirkungsweise des Programms oder des Unterprogramms<br />
(benutzerbezogen)<br />
• Ausführlicher Bedienungsanleitung<br />
♦ Beschreibung sämtlicher Programmfunktionen<br />
♦ Grenzen für Eingabewerte (Wertebereich)<br />
♦ Fehlermeldungen und die Benutzerreaktion auf die Fehler<br />
♦ Beispiel(e) für jede Programmfunktion<br />
♦ Besonderheiten, die beim Einsatz zu beachten sind<br />
• programmiererbezogene Programmbeschreibung<br />
♦ verwendete Algorithmen und deren Implementierung<br />
♦ Hinweise über Seiteneffekte einzelner Unterprogramme<br />
♦ Wartungs-Historie (Dok. von Änderungen/Erweiterungen)<br />
♦ mögliche Fehlersituationen und Reaktion des Programms darauf<br />
♦ alle "trickreichen" Programmsequenzen<br />
♦ Datenstrukturen<br />
• Ablaufpläne (Flußdiagramme, Struktogramme, Datenfluß)<br />
• kommentiertes Programmlisting<br />
• Programmversion und Erstellungs-/Änderungs-Datum auf Listing<br />
7.2 Tips zur Programmierung 154
7.3 ASCII-Tabelle<br />
ASCII Tabelle (sedezimal)<br />
| 00 nul| 01 soh| 02 stx| 03 etx| 04 eot| 05 enq| 06 ack| 07 bel|<br />
| 08 bs | 09 ht | 0a nl | 0b vt | 0c np | 0d cr | 0e so | 0f si |<br />
| 10 dle| 11 dc1| 12 dc2| 13 dc3| 14 dc4| 15 nak| 16 syn| 17 etb|<br />
| 18 can| 19 em | 1a sub| 1b esc| 1c fs | 1d gs | 1e rs | 1f us |<br />
| 20 sp | 21 ! | 22 " | 23 # | 24 $ | 25 % | 26 & | 27 ' |<br />
| 28 ( | 29 ) | 2a * | 2b + | 2c , | 2d - | 2e . | 2f / |<br />
| 30 0 | 31 1 | 32 2 | 33 3 | 34 4 | 35 5 | 36 6 | 37 7 |<br />
| 38 8 | 39 9 | 3a : | 3b ; | 3c < | 3d = | 3e > | 3f ? |<br />
| 40 @ | 41 A | 42 B | 43 C | 44 D | 45 E | 46 F | 47 G |<br />
| 48 H | 49 I | 4a J | 4b K | 4c L | 4d M | 4e N | 4f O |<br />
| 50 P | 51 Q | 52 R | 53 S | 54 T | 55 U | 56 V | 57 W |<br />
| 58 X | 59 Y | 5a Z | 5b [ | 5c \ | 5d ] | 5e ^ | 5f _ |<br />
| 60 ` | 61 a | 62 b | 63 c | 64 d | 65 e | 66 f | 67 g |<br />
| 68 h | 69 i | 6a j | 6b k | 6c l | 6d m | 6e n | 6f o |<br />
| 70 p | 71 q | 72 r | 73 s | 74 t | 75 u | 76 v | 77 w |<br />
| 78 x | 79 y | 7a z | 7b { | 7c | | 7d } | 7e ~ | 7f del|<br />
ASCII Tabelle (oktal)<br />
|000 nul|001 soh|002 stx|003 etx|004 eot|005 enq|006 ack|007 bel|<br />
|010 bs |011 ht |012 nl |013 vt |014 np |015 cr |016 so |017 si |<br />
|020 dle|021 dc1|022 dc2|023 dc3|024 dc4|025 nak|026 syn|027 etb|<br />
|030 can|031 em |032 sub|033 esc|034 fs |035 gs |036 rs |037 us |<br />
|040 sp |041 ! |042 " |043 # |044 $ |045 % |046 & |047 ' |<br />
|050 ( |051 ) |052 * |053 + |054 , |055 - |056 . |057 / |<br />
|060 0 |061 1 |062 2 |063 3 |064 4 |065 5 |066 6 |067 7 |<br />
|070 8 |071 9 |072 : |073 ; |074 < |075 = |076 > |077 ? |<br />
|100 @ |101 A |102 B |103 C |104 D |105 E |106 F |107 G |<br />
|110 H |111 I |112 J |113 K |114 L |115 M |116 N |117 O |<br />
|120 P |121 Q |122 R |123 S |124 T |125 U |126 V |127 W |<br />
|130 X |131 Y |132 Z |133 [ |134 \ |135 ] |136 ^ |137 _ |<br />
|140 ` |141 a |142 b |143 c |144 d |145 e |146 f |147 g |<br />
|150 h |151 i |152 j |153 k |154 l |155 m |156 n |157 o |<br />
|160 p |161 q |162 r |163 s |164 t |165 u |166 v |167 w |<br />
|170 x |171 y |172 z |173 { |174 | |175 } |176 ~ |177 del|<br />
7.4 I/O-Register<br />
Mikrocomputertechnik<br />
The following quick-reference table shows all control registers and bits. The addresses are those<br />
resulting from a hardware reset. The registers are generally grouped according to the device they are<br />
associated with. Some registers are input/output registers while other perform only control functions.<br />
Reference appropriate text material before using these registers.<br />
19881019/wj van ganswijk<br />
1000 porta<br />
1001 reserved<br />
1002 pioc<br />
w 1....... staf: strobe a flag, set at active edge of stra pin/inactive<br />
w .1...... stai: hardware interrupt request when STAF=1<br />
w ..1..... cwom: port c open-drain<br />
w ...1.... hnds: handshake/simpel strobe mode<br />
w ....1... oin: output/input handshake select<br />
w .....1.. pls: STRB pulse/level active<br />
w ......1. ega: rising/falling edge select for STRA<br />
w .......1 invb: STRB active high/low<br />
1003 portc<br />
1004 portb<br />
7.3 ASCII-Tabelle 155
Mikrocomputertechnik<br />
1005 portcl<br />
1006 reserved<br />
1007 ddrc: data direction register for port c (1=output)<br />
1008 portd (b0..b5)<br />
rw 1....... mode0 or boot: strb<br />
rw 1....... mode1 or test: r/w<br />
rw .1...... mode0 or boot: stra<br />
rw .1...... mode1 or test: as<br />
rw ..1..... pd5/ss*<br />
rw ...1.... pd4/sck<br />
rw ....1... pd3/mosi<br />
rw .....1.. pd2/miso<br />
rw ......1. pd1/txd<br />
rw .......1 pd0/rxd<br />
1009 ddrd: data direction register for port d (1=output) (b0..b5)<br />
100a porte: port e data register<br />
100b cforc: timer compare force register<br />
w 1....... foc1<br />
w .1...... foc2<br />
w ..1..... foc3<br />
w ...1.... foc4<br />
w ....1... foc5<br />
w 11111111 force compare(s)<br />
w .....xxx reserved<br />
100c oc1m: set bits to enable oc1 to control corresponding pin(s) of port a<br />
w 1....... oc1m7<br />
w .1...... oc1m6<br />
w ..1..... oc1m5<br />
w ...1.... oc1m4<br />
w ....1... oc1m3<br />
w .....xxx reserved<br />
w 11111111 force compare(s)<br />
100d oc1d: if oc1mx is set, data in oc1dx is output to port a bit-x<br />
on successful oc1 compares<br />
w 1....... oc1d7<br />
w .1...... oc1d6<br />
w ..1..... oc1d5<br />
w ...1.... oc1d4<br />
w ....1... oc1d3<br />
w .....xxx reserved<br />
w 11111111 force compare(s)<br />
100e tcnt: timer counter register<br />
1010 tic1: timer input capture register<br />
1012 tic2: timer input capture register<br />
1014 tic3: timer input capture register<br />
1016 toc1: timer output compare register<br />
1018 toc2: timer output compare register<br />
101a toc3: timer output compare register<br />
101c toc4: timer output compare register<br />
101e toc5: timer output compare register<br />
1020 tctl1: timer control register 1<br />
w 1....... om2<br />
w .1...... ol2<br />
w ..1..... om3<br />
w ...1.... ol3<br />
w ....1... om4<br />
w .....1.. ol4<br />
w ......1. om5<br />
w .......1 ol5<br />
for all pairs:<br />
w 00...... timer disconnected from output pin logic<br />
w 01...... ocx output line: toggle<br />
w 10...... ocx output line: 0<br />
w 11...... ocx output line: 1<br />
1021 tctl2: timer control register 2<br />
w xx...... reserved<br />
w ..1..... edg1b<br />
7.4 I/O-Register 156
Mikrocomputertechnik<br />
w ...1.... edg1a<br />
w ....1... edg2b<br />
w .....1.. edg2a<br />
w ......1. edg3b<br />
w .......1 edg3a<br />
for all pairs:<br />
w ..00.... capture: disabled<br />
w ..01.... capture: on rising edge only<br />
w ..10.... capture: on falling edge only<br />
w ..11.... capture: on any edge<br />
1022 tmsk1: main timer interrupt mask reg 1<br />
w 1....... oc1l: output compare 1 interrupt enable<br />
w .1...... oc2l: output compare 2 interrupt enable<br />
w ..1..... oc3l: output compare 3 interrupt enable<br />
w ...1.... oc4l: output compare 4 interrupt enable<br />
w ....1... oc5l: output compare 5 interrupt enable<br />
w .....1.. ic1l: input compare 1 interrupt enable<br />
w ......1. ic2l: input compare 2 interrupt enable<br />
w .......1 ic3l: input compare 3 interrupt enable<br />
1023 tflg1: main timer interrupt flag reg 1<br />
w 1....... oc1f: clear output compare flag 1<br />
w .1...... oc2f: clear output compare flag 2<br />
w ..1..... oc3f: clear output compare flag 3<br />
w ...1.... oc4f: clear output compare flag 4<br />
w ....1... oc5f: clear output compare flag 5<br />
w .....1.. ic1f: clear input capture flag 1<br />
w ......1. ic2f: clear input capture flag 2<br />
w .......1 ic3f: clear input capture flag 3<br />
1024 tmsk2: misc timer interrupt mask reg 2<br />
w 1....... toi: timer overflow interrupt enable<br />
w .1...... rtii: interrupt enable<br />
w ..1..... paovi: pulse accumulator overflow interrupt enable<br />
w ...1.... paii: pulse accumulator input interrupt enable/disable<br />
w ....xx.. reserved<br />
w ......00 pr1,pr0: timer prescale factor 1<br />
w ......01 pr1,pr0: timer prescale factor 4<br />
w ......10 pr1,pr0: timer prescale factor 8<br />
w ......11 pr1,pr0: timer prescale factor 16<br />
1025 tflg2: misc timer interrupt flag reg 2<br />
w 1....... tof: clear timer overflow flag<br />
w .1...... rtif: clear real time (periodic) interrupt flag<br />
w ..1..... paovf: clear pulse accumulator overflow flag<br />
w ...1.... paif: clear paif pulse accumulator input edge flag<br />
w ....xxxx reserved<br />
1026 pactl: pulse accumulator control register<br />
w 1....... ddra7: data direction for port a bit7 is output/input<br />
w .1...... paen: enable/disable pulse accumulator system enable<br />
w ..1..... pamod: pulse acc mode: gated time accumulation/event counter<br />
w ...1.... pedge: pulse acc edge ctrl: rising/falling edges<br />
w ....xx.. reserved<br />
w ......00 rtr1,rtr0: interrupt rate divide by 2^13<br />
w ......01 rtr1,rtr0: interrupt rate divide by 2^14<br />
w ......10 rtr1,rtr0: interrupt rate divide by 2^15<br />
w ......11 rtr1,rtr0: interrupt rate divide by 2^16<br />
1027 pacnt: pulse accumulator count register<br />
1028 spcr: spi control register<br />
w 1....... spie: spi interrupt enable<br />
w .1...... spe: spi system enable<br />
w ..1..... dwom: port d: open-drain/normal<br />
w ...1.... mstr: master/slave mode<br />
w ....1... cpol: clock polarity<br />
w .....1.. cpha: clock phase<br />
w ......00 spr1,spr0: spi e-clock divided by 2<br />
w ......01 spr1,spr0: spi e-clock divided by 4<br />
w ......10 spr1,spr0: spi e-clock divided by 8<br />
w ......11 spr1,spr0: spi e-clock divided by 16<br />
1029 spsr: spi status register<br />
7.4 I/O-Register 157
Mikrocomputertechnik<br />
r 1....... spif: spi interrupt request<br />
r .1...... wcol: write collision status flag<br />
r ...1.... modf: spi mode error interrupt status flag<br />
r ..x.xxxx reserved<br />
102a spdr: spi data register<br />
102b baud: sci baud rate control register<br />
w 1....... tclr: clear baud counter chain (test only)<br />
w .x...... reserved<br />
w ..00.... scp1,scp0: serial prescaler select: divide e-clock by 1<br />
w ..01.... scp1,scp0: serial prescaler select: divide e-clock by 2<br />
w ..10.... scp1,scp0: serial prescaler select: divide e-clock by 4<br />
w ..11.... scp1,scp0: serial prescaler select: divide e-clock by 13<br />
w ....1... rckb: sci baud rate clock test (test only)<br />
w .....000 scr2,scr1,scr0: prescaler output divide by 1<br />
w .....001 scr2,scr1,scr0: prescaler output divide by 2<br />
w .....010 scr2,scr1,scr0: prescaler output divide by 4<br />
w .....011 scr2,scr1,scr0: prescaler output divide by 8<br />
w .....100 scr2,scr1,scr0: prescaler output divide by 16<br />
w .....101 scr2,scr1,scr0: prescaler output divide by 32<br />
w .....110 scr2,scr1,scr0: prescaler output divide by 64<br />
w .....111 scr2,scr1,scr0: prescaler output divide by 128<br />
102c sccr1: sci control register 1<br />
w 1....... r8: receive bit 8<br />
w .1...... t8: transmit bit 8<br />
w ...1.... m: ninth data bit<br />
w ....1... wake: wake up by address mark/idle line (msb/no low)<br />
w ..x..xxx reserved<br />
102d sccr2: sci control register 2<br />
w 1....... tie: transmit interrupt enable<br />
w .1...... tcie: transmit complete interrupt enable<br />
w ..1..... rie: receiver interrupt enable<br />
w ...1.... ilie: enable/disable idle line interrupts<br />
w ....1... te: transmitter enable (toggle to queue idle character)<br />
w .....1.. re: receiver enable on/off<br />
w ......1. rwu: receiver asleep/normal<br />
w .......1 sbk: send break<br />
102e scsr: sci status register<br />
r 1....... tdre: transmit data register empty flag<br />
r .1...... tc: transmit complete flag<br />
r ..1..... rdrf: receive data register full flag<br />
r ...1.... idle: idle line detected flag<br />
r ....1... or: over-run error flag<br />
r .....1.. nf: noise error flag<br />
r ......1. fe: framing error flag<br />
r .......x reserved<br />
102f scdr: sci data register<br />
1030 adctl: a/d control/status register<br />
r 1....... ccf: conversions complete flag (sets after fourth conversion)<br />
rw .x...... reserved<br />
w ..1..... scan: convert continuously/4 conversions and stop<br />
w ...1.... mult: convert four channel group/single channel<br />
rw ....0000 cd,cc,cb,ca: ad0 port e bit0<br />
rw ....0001 cd,cc,cb,ca: ad1 port e bit1<br />
rw ....0010 cd,cc,cb,ca: ad2 port e bit2<br />
rw ....0011 cd,cc,cb,ca: ad3 port e bit3<br />
rw ....0100 cd,cc,cb,ca: ad4 port e bit4<br />
rw ....0101 cd,cc,cb,ca: ad5 port e bit5<br />
rw ....0110 cd,cc,cb,ca: ad6 port e bit6<br />
rw ....0111 cd,cc,cb,ca: ad7 port e bit7<br />
rw ....10xx cd,cc,cb,ca: reserved<br />
rw ....1100 cd,cc,cb,ca: Vref hi<br />
rw ....1101 cd,cc,cb,ca: Vref low<br />
rw ....1110 cd,cc,cb,ca: Vref hi/2<br />
rw ....1111 cd,cc,cb,ca: test/reserved<br />
1031 adr1<br />
1032 adr2<br />
1033 adr3<br />
7.4 I/O-Register 158
Mikrocomputertechnik<br />
1034 adr4<br />
1035 reserved<br />
1036 reserved<br />
1037 reserved<br />
1038 reserved<br />
1039 option: system configuration options<br />
w 1....... adpu: a->d system powered up/down<br />
w .1...... csel: a->d and ee use an internal-r-c/system-e clock<br />
w ..1..... irqe: irq configured for falling edges/low level<br />
w ...1.... dly: enable/disable oscillator start-up delay (from stop)<br />
w ....1... cme: slow or stopped clocks cause reset/disabled<br />
w .....x.. reserved<br />
w ......00 cr1,cr0: e/2^15 divided by 1<br />
w ......01 cr1,cr0: e/2^15 divided by 4<br />
w ......10 cr1,cr0: e/2^15 divided by 16<br />
w ......11 cr1,cr0: e/2^15 divided by 64<br />
103a coprst: arm/reset cop timer circuitry,<br />
write $55 and $aa to reset cop watchdog timer<br />
103b pprog: eeprom programming register<br />
w 1....... odd: program odd rows in half of eeprom (test only)<br />
w .1...... even: program even rows in half of eeprom (test only)<br />
w ..x..... reserved<br />
w ...1.... byte: erase only one byte/row or all of eeprom<br />
w ....1... row: erase only one 16 byte row/all 512 bytes of eeprom<br />
w .....1.. erase: erase/normal read of program mode<br />
w ......1. eelat: eeprom busses configured for program or erase/read<br />
w .......1 eepgm: program or erase power switched on/off<br />
to program eeprom:<br />
- set eelat<br />
- write data to desired address<br />
- set eepgm for the required programming time<br />
to erase eeprom:<br />
- select row = 1/0<br />
- select byte = 1/0<br />
- set erase and eelat = 1<br />
- write to an eeprom address to be erased<br />
- set eepgm for the required erase time period<br />
103c hprio: highest priority interrupt and misc.<br />
w 1....... rboot: boot rom enabled/not in map (normal)<br />
w .00..... smod,mda: single chip mode<br />
w .01..... smod,mda: expanded multiplexed mode<br />
w .10..... smod,mda: special bootstrap<br />
w .11..... smod,mda: special test<br />
w ...1.... irv: data from internal reads visible/not<br />
on external bus<br />
reset to in test/boot mode: 1, in normal modes: 0<br />
r ....0000 psel3,2,1,0: timer overflow<br />
r ....0001 psel3,2,1,0: pulse accum. overflow<br />
r ....0010 psel3,2,1,0: puls accum. input edge<br />
r ....0011 psel3,2,1,0: spi serial xfer complete<br />
r ....0100 psel3,2,1,0: sci serial system<br />
r ....0101 psel3,2,1,0: reserved (default to irq)<br />
r ....0110 psel3,2,1,0: irq (ext pin or parallel i/o<br />
r ....0111 psel3,2,1,0: real time interrupt<br />
r ....1000 psel3,2,1,0: timer input capture 1<br />
r ....1001 psel3,2,1,0: timer input capture 2<br />
r ....1010 psel3,2,1,0: timer input capture 3<br />
r ....1011 psel3,2,1,0: timer output compare 1<br />
r ....1100 psel3,2,1,0: timer output compare 2<br />
r ....1101 psel3,2,1,0: timer output compare 3<br />
r ....1110 psel3,2,1,0: timer output compare 4<br />
r ....1111 psel3,2,1,0: timer output compare 5<br />
103d init: ram and i/o mapping register<br />
w xxxx.... ram3,2,1,0: ram block position (x000..x0ff)<br />
w ....xxxx reg3,2,1,0: register block position (x000..x03f)<br />
00000001 at reset<br />
103e test1: factory test register<br />
7.4 I/O-Register 159
w 1....... tilop: test illegal opcode<br />
w .x...... reserved<br />
w ..1..... occr: output condition code register status to timer port<br />
w ...1.... cbyp: timer divider chain bypass<br />
w ....1... disr: disable resets from cop and clock monitor<br />
w .....1.. fcm: force clock monitor failure<br />
w ......1. fcop: force cop watchdog failure<br />
w .......1 tcon: test configuration<br />
103f config: configuration control register<br />
w ....1... nosec: dis/enable security mode<br />
(security only if mask option)<br />
w .....1.. nocop: dis/enable cop system<br />
w ......1. romon: en/disable rom at $e000..$ffff<br />
w .......1 eeon: en/disable eeprom at $b600..$b7ff<br />
note: The bits of this register are implemented with eeprom cells.<br />
programming and erasure follow normal eeprom procedures.<br />
The erased state of this location is $0f. A new value<br />
programmed into this register is not readable until after a<br />
subsequent reset sequence.<br />
7.5 Interrupt-Adressen<br />
SCIINT EQU $FFD6 ; SCI serial system<br />
SPIINT EQU $FFD8 ; SPI serial system<br />
PAIINT EQU $FFDA ; Pulse Accumulator Input Edge<br />
PAOVINT EQU $FFDC ; Pulse Accumulator Overflow<br />
TOINT EQU $FFDE ; Timer Overflow<br />
TOC5INT EQU $FFE0 ; Timer Output Compare 5<br />
TOC4INT EQU $FFE2 ; Timer Output Compare 4<br />
TOC3INT EQU $FFE4 ; Timer Output Compare 3<br />
TOC2INT EQU $FFE6 ; Timer Output Compare 2<br />
TOC1INT EQU $FFE8 ; Timer Output Compare 1<br />
TIC3INT EQU $FFEA ; Timer Input Capture 3<br />
TIC2INT EQU $FFEC ; Timer Input Capture 2<br />
TIC1INT EQU $FFEE ; Timer Input Capture 1<br />
RTIINT EQU $FFF0 ; Real Time Interrupt<br />
IRQINT EQU $FFF2 ; IRQ External Interrupt<br />
XIRQINT EQU $FFF4 ; XIRQ External Interrupt<br />
SWIINT EQU $FFF6 ; Software Interrupt<br />
BADOPINT EQU $FFF8 ; Illegal Opcode Trap Interrupt<br />
NOCOPINT EQU $FFFA ; COP Failure (Reset)<br />
CMEINT EQU $FFFC ; COP Clock Monitor Fail (Reset)<br />
RESETINT EQU $FFFE ; RESET Interrupt<br />
7.6 Das Motorola-S-Format<br />
Mikrocomputertechnik<br />
Eine Datei im Motorola-S-Format ist eine Textdatei mit beliebig vielen Zeilen, die Sedezimalziffern in<br />
ASCII-Darstellung enthalten. Die Zeilen werden mit CR, LF abgeschlossen. Diese Datei enthält<br />
Binärcode in ASCII-Form.<br />
Die Datei kann (muß aber nicht) mit einer Einleitungszeile beginnen, dem Sign-On-Record. Man<br />
erkennt ihn am einleitenden S0 (Ziffer Null). Er enthält einen Kommentar, z. B. den Programmnamen<br />
(im Beispiel unten "DATA I/O"). S-Records enthalten pro Zeile eine Adresse, an der die Daten<br />
abgelegt werden sollen.<br />
Jede Datenzeile beginnt mit zwei Startzeichen "S" und einer Ziffer. Die nächsten beiden Zeichen<br />
geben die hexadezimale Anzahl der Datenbytes in der Zeile an, wobei auch die Adreßangabe (2 Bytes)<br />
und die Prüfsumme mitgezählt werden (also Zahl der "echten" Datenbytes + 3). Darauf folgen vier<br />
Zeichen, welche die hexadezimale Adresse des ersten Bytes des Datenrecords angeben. Nun folgen<br />
7.5 Interrupt-Adressen 160
die Datenbytes zweistellig hexadezimal. Leerzeichen werden überlesen. Zum Schluß folgt ein Byte<br />
Prüfsumme (zweistell. Hex.). Die Prüfsumme ist das Einerkomplement aus der Summe von<br />
Längenangabe, Adresse und Datenbytes. Der Typ des Records wird durch eine Ziffer bezeichnet:<br />
• 0: Startrecord (siehe oben)<br />
• 1,2,3: Datenrecord<br />
• 7,8,9: Enderecord<br />
Der Typ sorgt für die Unterscheidung der Adreßlänge:<br />
• Bei Typ 0 is die Adresse immer $0000 und 16-Bit (4 Ziffern) lang<br />
• Bei Typ 1 oder 9 is die Adresse 16-Bit (4 Ziffern) lang<br />
• Bei Typ 2 oder 8 is die Adresse 24-Bit (6 Ziffern) lang<br />
• Bei Typ 3 oder 7 is die Adresse 32-Bit (8 Ziffern) lang<br />
Die letzte Zeile der Datei beginnt mit den Startzeichen "S" und der Ziffer 9, 8 oder 7. Er bildet den<br />
End-Of-File-Record. Ein Enderecord enthält keine Daten, aber die Adresse in diesem Record stellt die<br />
Startadresse des Programms dar.<br />
Beispiel:<br />
S0 0B 0000 44 41 54 41 20 49 2F 4F F4 <br />
S1 13 0000 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FC <br />
S1 13 0010 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF EC <br />
S1 13 0020 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF DC <br />
S1 13 0030 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF CC <br />
S1 13 0040 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF BC <br />
S9 03 0000 FC ¦<br />
¦ ¦ ¦ ¦ ¦<br />
¦ ¦ ¦ Datenbytes Prüfsumme<br />
¦ ¦ Adresse<br />
¦ Längenangabe (Datenbytes + 3)<br />
Record-Markierung<br />
Zum vorhergehenden Abschnitt Zum Inhaltsverzeichnis Zum nächsten Abschnitt<br />
Copyright © FH München, FB 04, Prof. Jürgen Plate<br />
Mikrocomputertechnik<br />
Mikrocomputertechnik<br />
Prof. Jürgen Plate<br />
7.6 Das Motorola-S-Format 161
Programmbeispiel-Sammlung<br />
Den folgenden "Programmschnipseln" fehlt noch das "Drumrum"<br />
(Definitionen von Variablen, Hauptprogramm, usw.). Sie dienen der<br />
Illustration verschiedener Programmiertechniken in <strong>Assembler</strong>.<br />
Allgemeiner Vorspann für's Praktikum<br />
data equ $2000 ; data area (e-ram)<br />
stak equ $7FFF ; stack area (e-ram)<br />
prog equ $8000 ; programm area (e-eerom)<br />
rvec equ $FFFE ; reset vector<br />
pioc equ $1002 ; parallel i/o control<br />
portb equ $1004 ; port b data<br />
portcl equ $1005 ; port c data latch<br />
portc equ $1003 ; port c data reg.<br />
ddrc equ $1007 ; portc data dir. reg.<br />
tmsk equ $1024 ; timer mask<br />
tflg equ $1025 ; timer flag<br />
pacr equ $1026 ; pulse accu control<br />
baud equ $102B ; SCI-baudrate<br />
sccr1 equ $102C ; SCI-control1<br />
sccr2 equ $102D ; SCI-control2<br />
scsr equ $102E ; SCI-status<br />
scdr equ $102F ; SCI-data<br />
***************************<br />
* data area *<br />
***************************<br />
org data<br />
***************************<br />
* program area *<br />
***************************<br />
org prog<br />
main lds #stak ; load stackpointer<br />
***************************<br />
* Nachspann: Vektoren *<br />
***************************<br />
org reset<br />
fdb main<br />
end<br />
Speicherbereich Kopieren<br />
* Parameter: A Länge (Anzahl Bytes), X Quelle, Y Ziel<br />
move pshb<br />
mov1 ldab 0,x ; hole Quellbyte<br />
stab 0,y ; speichern im Zielbereich<br />
inx ; Adressen erhöhen<br />
iny<br />
deca ; runterzählen bis 0<br />
bne mov1<br />
pulb<br />
rts<br />
Programmbeispiel-Sammlung 162
Die größere von zwei Zahlen finden<br />
Vergleichen ($40) und ($41), Ergebnis in $42<br />
LDAA $40 ; 1. Zahl holen<br />
CMPA $41 ; 2. Zahl größer?<br />
BHS WEITER ; 1. Zahl ist größer<br />
LDAA $41 ; 2. Zahl laden<br />
WEITER STAA $42 ; Abspeichern<br />
16-Bit-Addition (Prüfsumme)<br />
Addition eines Feldes von 8-Bit-Werten. Die Anzahl der Werte steht in Speicherbyte $42, die zu<br />
addierenden Werte folgen ab Adresse $43. Das 16-Bit-Ergebnis wird in $40 (MSB) und $41 (LSB)<br />
abgelegt.<br />
CHECKSUM CLRA ; Summe in A und B, Register<br />
CLRB ; zuerst mal löschen<br />
LDX #$0043 ; Adresse erster Summand (Feldanfang)<br />
CSUM ADDB ,X ; Feldelement addieren<br />
ADCA #0 ; Übertrag im MSB aufaddieren<br />
INX ; X inkrementieren<br />
DEC $42 ; Elementezähler vermindern<br />
BNE CSUM ; Wiederholen, solange Zähler > 0 ist<br />
STD $40 ; Checksumme speichern<br />
RTS<br />
Quadrate von 0 - 15 über Tabelle ermitteln<br />
Wert in $41, Ergebnis in $42<br />
LDAB $41 ; Operanden holen<br />
LDX #TABELLE ; X-Register auf Tabellenanfang<br />
ABX ; X und B addieren<br />
LDAA 0,X ; B-ten Eintrag aus Tabelle holen<br />
STAA $42 ; und abspeichern<br />
TABELLE DC.B 0,1,4,9,16,25,36,49,64,81,100<br />
DC.B 121,144,169,196,225<br />
Addieren von 24-Bit-Zahlen<br />
org data<br />
eins dc.b 04,82,40 ; 1. Summand<br />
zwei dc.b 02,37,98 ; 2. Summand<br />
drei dc.b $00,$00,$00 ; Ergebnis<br />
org prog<br />
.<br />
.<br />
.<br />
ldaa eins+2<br />
adda zwei+2<br />
staa drei+2<br />
ldaa eins+1<br />
adca zwei+1<br />
staa drei+1<br />
ldaa eins+0<br />
adca zwei+0<br />
staa drei+0<br />
.<br />
.<br />
.<br />
Mikrocomputertechnik<br />
Allgemeiner Vorspann für's Praktikum 163
Addition von 8-stelligen BCD-Zahlen<br />
Die 1. Zahl belegt den Speicherbereich $41 - $44 (LSB zuerst)<br />
Die 2. Zahl -"- $51 - $54 -"-<br />
Das Ergebnis wird auf die erste Zahl gespeichert<br />
LDAB #4 ; Zahlen sind 4 Byte lang = 8 Stellen<br />
LDX #$41 ; 1. Operand<br />
LDY #$51 ; 2. Operand<br />
CLRA ; Akku A (und Carry-Flag) löschen<br />
BCDADD LDAA 0,X ; zwei Ziffern des 1.Operanden holen<br />
ADCA 0,Y ; zwei Ziffern des 2.Operanden addieren<br />
INY<br />
DAA ; Dezimalkorrektur für BCD<br />
STAA 0,X ; Ergebnis abspeichern<br />
INX<br />
DECB<br />
BNE BCDADD ; solange, bis alle Stellen bearbeitet<br />
Zählen der negativen Elemente in einem Feld<br />
ANZAHL EQU 20 ; z.B. 20 Feldelemente<br />
FELD DS.B 20 ; Platz für 20 Werte<br />
COUNT DS.B 1 ; 1 Byte Zähler<br />
.<br />
.<br />
.<br />
CLRB ; Zähler für neg. Elemente löschen<br />
LDX #FELD ; X auf Feldanfang<br />
LDAA ANZAHL<br />
STAA COUNT ; Zähler setzen<br />
LOOP LDAA 0,X ; nächstes Feldelement<br />
BPL WEITER ; wenn positiv weiter<br />
INCB ; negative Elemente zählen<br />
WEITER INX<br />
DEC COUNT<br />
BNE LOOP ; bis alle Elemente getestet sind<br />
STAB COUNT ; Ergebnis in COUNT speichern<br />
Ein- und Ausgabe auf Ports<br />
Mikrocomputertechnik<br />
Das folgende Programm liest die unteren 4 Bits von Port C ein und gibt sie auf Port B wieder aus,<br />
gleichzeitig blinken die oberen 4 Bits von Port C.<br />
.<br />
.<br />
.<br />
clr portb ; Portb auf 0 setzen<br />
ldab #%1010 ; Register B setzen<br />
ldaa #%11110000 ; Port C Richtungsregister setzen:<br />
staa ddrc ; Bits 0-3 Eingabe, 4-7 Ausgabe<br />
loop ldaa portc ; Port C lesen<br />
anda #$0F ; untere 4 Bits ausmaskieren<br />
staa portb ; auf Port B ausgeben<br />
stab portc ; Register B ausgeben<br />
eorb #%11110000 ; und Bits 4-7 invertieren<br />
bsr delay ; 0,5 s warten (siehe unten)<br />
jmp loop ; endlosschleife<br />
.<br />
.<br />
.<br />
Allgemeiner Vorspann für's Praktikum 164
Taste an PA7 einlesen<br />
prog equ $8000<br />
data equ $2000<br />
stack equ $7FFF<br />
pioc equ $1002 ; parallel i/o control<br />
portb equ $1004 ; port b data<br />
portc equ $1005 ; port c data latch<br />
portcl equ $1005 ; port c data latch<br />
tmsk equ $1024 ; timer mask<br />
tflg equ $1025 ; timer flag<br />
pacr equ $1026 ; pulse accu control<br />
baud equ $102B ; SCI-baudrate<br />
sccr1 equ $102C ; SCI-control1<br />
sccr2 equ $102D ; SCI-control2<br />
scsr equ $102E ; SCI-status<br />
scdr equ $102F ; SCI-data<br />
reset equ $fffe<br />
org data<br />
key ds.b 1<br />
org prog<br />
main lds #stack ; load stackpointer<br />
clr key<br />
ldaa #%01010000 ; pa7 freigabe pos. flanke<br />
staa pacr<br />
clra<br />
loop bsr taste<br />
ldaa key<br />
staa portb<br />
bra loop<br />
taste psha<br />
ldaa tflg ; taste gedrueckt?<br />
anda #$10<br />
beq tend ; nix gewesen<br />
ldaa #$10<br />
staa tflg ; Anforderung loeschen<br />
com key ; Ereignis melden<br />
tend pula<br />
rts<br />
org reset<br />
fdb main<br />
end<br />
Mikrocomputertechnik<br />
16-Bit Schieberegister, Richtung per PA7-Taste umschaltbar<br />
data equ $2000 ; data area (e-ram)<br />
stak equ $7FFF ; stack area (e-ram)<br />
prog equ $8000 ; programm area (e-eerom)<br />
rvec equ $FFFE ; reset vector<br />
pioc equ $1002 ; parallel i/o control<br />
portb equ $1004 ; port b data<br />
portcl equ $1005 ; port c data latch<br />
portc equ $1003 ; port c data reg.<br />
ddrc equ $1007 ; portc data dir. reg.<br />
tmsk equ $1024 ; timer mask<br />
tflg equ $1025 ; timer flag<br />
pactl equ $1026 ; pulse accu control<br />
baud equ $102B ; SCI-baudrate<br />
Allgemeiner Vorspann für's Praktikum 165
sccr1 equ $102C ; SCI-control1<br />
sccr2 equ $102D ; SCI-control2<br />
scsr equ $102E ; SCI-status<br />
scdr equ $102F ; SCI-data<br />
***************************<br />
* data area *<br />
***************************<br />
org data<br />
flag ds.b 1<br />
shift ds.b 2<br />
***************************<br />
* program area *<br />
***************************<br />
org prog<br />
main lds #stak ; load stackpointer<br />
clr flag<br />
ldaa #%01010000 ; pa7 Eingang, Freigabe, pos. Flanke<br />
staa pactl<br />
ldaa #$FF ; portc als Ausgabe<br />
staa ddrc<br />
clr shift ; Schieberegister mit 1 laden<br />
ldab #1<br />
stab shift+1<br />
loop bsr taste ; Tastenstatus abfragen<br />
ldaa flag ; flag = 0 - links, flag = ff - rechts<br />
bne rechts<br />
links ldd shift ; nach links schieben<br />
lsld<br />
bne raus ; falls 0, neu laden mit 1 im LSB<br />
ldab #1<br />
bra raus ; zur Ausgabe<br />
rechts ldd shift ; rechts schieben<br />
lsrd<br />
bne raus ; falls 0 mit 1 laden im MSB<br />
ldaa #$80<br />
raus std shift ; akt. Wert speichern<br />
staa portb ; und ausgeben (auf zwei 8-Bit-Ports)<br />
stab portc<br />
bsr delay<br />
bra loop<br />
rts<br />
taste psha ; Akku retten<br />
ldaa tflg ; Taste gedrueckt?<br />
anda #$10<br />
beq tend ; nix gewesen<br />
ldaa tflg<br />
oraa #$10<br />
staa tflg ; Anforderung loeschen<br />
com flag ; Ereignis melden<br />
tend pula ; Akku restore<br />
rts<br />
delay ldy #$ffff<br />
dely1 nop<br />
nop<br />
nop<br />
nop<br />
nop<br />
Mikrocomputertechnik<br />
Allgemeiner Vorspann für's Praktikum 166
nop<br />
nop<br />
dey<br />
bne dely1<br />
rts<br />
***************************<br />
* vectors *<br />
***************************<br />
org rvec<br />
fdb main ; FFFE reset<br />
end<br />
Auf-/Abwärtszähler, Taste an STRA<br />
Der folgende Zähler zählt abhängig von der Variablen "tflag" aufwärts oder abwärts. Die Zählrichtung<br />
wird durch eine Taste am Eingang STRA umgeschaltet.<br />
; Vereinbarungen<br />
prog equ $8000<br />
data equ $2000<br />
stack equ $7FFF<br />
portb equ $1004<br />
portc equ $1003<br />
portcl equ $1005<br />
pioc equ $1002<br />
ddrc equ $1007<br />
reset equ $fffe<br />
.<br />
.<br />
org data ; Datenbereich<br />
tflag ds.b 1<br />
.<br />
.<br />
Mikrocomputertechnik<br />
org prog ; Programmbereich<br />
main lds #stack ; Stackpointer laden<br />
clr portb ; Ports/Variablen init.<br />
ldaa #1 ; tflag = 1<br />
staa tflag<br />
loop bsr count ; Hauptschleife, nur zwei UP-Aufrufe<br />
bsr taste ; Taste abfrage<br />
jmp loop ; auf/ab zaehlen<br />
; Zaehl-Unterprogramm<br />
; tflag wird addiert (tflag kann 1 oder -1 sein)<br />
count adda tflag ; zaehlen<br />
staa portb ; ausgeben<br />
bsr delay ; 0,5 s warten (siehe unten)<br />
rts<br />
; Tasten-Abfrage-UP<br />
; bei jedem Tastendruck wird tflag negiert (+1 -1, -1 +1)<br />
taste psha ; Akku A retten<br />
ldaa pioc ; Taste gedrueckt<br />
bpl njet ; nein fertig<br />
ldaa portcl ; dummy-read zum Ruecksetzend es Tastenbits in pioc<br />
neg tflag ; tflag negieren<br />
njet pula ; Akku A restaurieren<br />
rts<br />
.<br />
.<br />
.<br />
Allgemeiner Vorspann für's Praktikum 167
Alternativlösung mit bedingter Verzweigung<br />
loop bsr delay<br />
tst updn<br />
bne decr<br />
inc count<br />
ldaa count<br />
cmpa #$FF<br />
bne endf<br />
com updn<br />
bra endf<br />
decr dec count<br />
ldaa count<br />
tsta<br />
bne endf<br />
com updn<br />
endf ldaa count<br />
staa portb<br />
jmp loop<br />
BCD-Zähler mit Rücksetzen per STRA<br />
data equ $2000 ; data area (e-ram)<br />
stak equ $7FFF ; stack area (e-ram)<br />
prog equ $8000 ; programm area (e-eerom)<br />
rvec equ $FFFE ; reset vector<br />
pioc equ $1002 ; parallel i/o control<br />
portb equ $1004 ; port b data<br />
portcl equ $1005 ; port c data latch<br />
portc equ $1003 ; port c data reg.<br />
ddrc equ $1007 ; portc data dir. reg.<br />
tmsk equ $1024 ; timer mask<br />
tflg equ $1025 ; timer flag<br />
pacr equ $1026 ; pulse accu control<br />
baud equ $102B ; SCI-baudrate<br />
sccr1 equ $102C ; SCI-control1<br />
sccr2 equ $102D ; SCI-control2<br />
scsr equ $102E ; SCI-status<br />
scdr equ $102F ; SCI-data<br />
***************************<br />
* data area *<br />
***************************<br />
org data<br />
flag ds.b 1<br />
***************************<br />
* program area *<br />
***************************<br />
org prog<br />
main lds #stak ; load stackpointer<br />
clra<br />
clr flag<br />
bsr init<br />
schl adda #1 ; BCD hochzaehlen<br />
daa<br />
anda #$0F<br />
bsr taste ; Taste abfragen<br />
psha ; a auf den stack<br />
lsla ; 4 x schieben<br />
Mikrocomputertechnik<br />
Allgemeiner Vorspann für's Praktikum 168
lsla<br />
lsla<br />
lsla<br />
staa portc ; ausgeben<br />
pula ; a restore<br />
ldab flag ; Tastendruck bearbeiten<br />
stab portb ; auf Port B ausgeben<br />
bne weiter ; wenn nicht 0<br />
clra ; Zaehler loeschen<br />
com flag ; flag wieder setzen -> sonst "haengt" es<br />
weiter bsr delay<br />
bra schl<br />
init ldaa #$02 ; hands=0, raising edge 00000010<br />
staa pioc<br />
ldaa #%11110000<br />
staa ddrc<br />
rts<br />
delay ldy #$ffff<br />
dely1 nop<br />
nop<br />
nop<br />
nop<br />
nop<br />
nop<br />
nop<br />
dey<br />
bne dely1<br />
rts<br />
taste psha<br />
ldaa pioc ; taste gedrueckt (Bit 7)?<br />
bpl tend ; nix gewesen<br />
ldaa portcl ; dummy read --> Reset STAF<br />
com flag ; ereignis melden<br />
tend pula<br />
rts<br />
***************************<br />
* vectors *<br />
***************************<br />
org rvec<br />
fdb main ; FE reset<br />
end<br />
Software-Uhr<br />
Eine Software-Uhr wird in der Regel durch einen periodischen Interrupt (z. B. vom Timer) unterstützt.<br />
Bei jedem Interrupt wird ein Zähler incrementiert. Die Zählung erfolgt in Sekunden, Minuten und<br />
Stunden. Das im Vordergrund arbeitende Programm kann auf die Zeitinformation zugreifen.<br />
Die Bedienung des Timer-Interrupts wird hier nur angedeutet (da noch nicht behandelt). Der<br />
CLOCK-Interrupt wird im Beispiel alle 100 ms ausgelöst = 10 Tics/s.<br />
ZEHNTEL DS.B 1 ; 1/10 Sekunden<br />
SEKUNDEN DS.B 1 ; Sekunden<br />
MINUTEN DS.B 1 ; Minuten<br />
STUNDEN DS.B 1 ; Stunden<br />
.<br />
.<br />
.<br />
Mikrocomputertechnik<br />
Allgemeiner Vorspann für's Praktikum 169
CLOCK<br />
* An dieser Stelle muß die<br />
* Timer-Hardware bedient werden<br />
INC ZEHNTEL ; 1/10 Sekunden erhöhen<br />
LDAA #10<br />
CMPA ZEHNTEL ; Sekunde erreicht?<br />
BNE ENDCLOCK ; nein - fertig<br />
CLR ZEHNTEL ; sonst 1/10 Sekunden auf 0 setzen<br />
INC SEKUNDEN ; und Sekunden erhöhen<br />
LDAA #60<br />
CMPA SEKUNDEN ; Minute erreicht?<br />
BNE ENDCLOCK ; nein - fertig<br />
CLR SEKUNDEN ; sonst Sekunden auf 0 setzen<br />
INC MINUTEN ; und Minuten erhöhen<br />
CMPA MINUTEN ; Stunden erreicht?<br />
BNE ENDCLOCK ; nein - fertig<br />
CLR MINUTEN ; sonst Minuten auf 0 setzen<br />
INC STUNDEN ; und Stunden erhöhen<br />
LDAA #24<br />
CMPA STUNDEN ; Tageswechsel?<br />
BNE ENDCLOCK ; nein - fertig<br />
CLR STUNDEN ; sonst Stunden auf 0 setzen<br />
ENDCLOCK RTI ; Rücksprung<br />
Die Dauer der ISR beträgt im schlechtesten Fall weniger als 150 Taktzyklen. Da die ISR nur alle 100<br />
ms ausgelöst wird, ist die zusätzliche Belastung des Systems relativ gering (ca. 0,1%).<br />
Nützliche Unterprogramme<br />
Mikrocomputertechnik<br />
Die folgenden Unterprogramme lassen sich in eigenen Programmen verwenden.<br />
Ergänzen eines ASCII-Codewortes auf gerade Parität<br />
EVENPAR PSHB ; Codewort zwischenspeichern<br />
CLRA ; Zaehler = 0<br />
ZHL LSRB ; naechstes Bit ins Carry holen<br />
ADCA #0 ; Carry zu A ddieren<br />
TSTB ; Restwort = 0?<br />
BNE ZHL ; nein, weiter<br />
PULB ; Codewort holen<br />
ASLB ; links schieben<br />
LSRA ; Parity-Bit ins Carry<br />
RORB ; Parity-Bit ins MSB vom Codewort<br />
RTS<br />
Nützliche Unterprogramme 170
Binärwert (0 - 15) zu ASCII konvertieren<br />
Unterprogramm zur Konvertierung eines Binärwertes (0 - 15) in die ASCII-Darstellung (z.B. für die<br />
Ausgabe am Terminal). Der Wert wird in Register A an das UP übergeben und das entsprechende<br />
ASCII-Zeichen wird vom UP wieder in A zurückgegeben.<br />
Der Abstand zwischen der Ziffer "9" und dem Buchstaben "A" beträgt im ASCII-Zeichensatz 7<br />
Zeichen, weshalb zwischen den Eingangswerten 0 - 9 und 10 - 15 unterschieden werden muss. Bei<br />
Werten größer 10 muss daher 7 addiert werden.<br />
*<br />
* Konvertierung Binär zu ASCII<br />
* Parameter in Akku A<br />
*<br />
BINASC ANDA #0F ; auf Werte zwischen 0 und 15 begrenzen<br />
CMPA #9 ; Wert 0 bis 9 ?<br />
BLS ZIF ; ja, dann direkt umwandeln<br />
ADDA #7 ; "A" - "9" - 1 = $41 - $39 - 1 = 7<br />
ZIF ADDA #$30 ; $30 = "0" (ASCII-Wert)<br />
RTS<br />
ASCII-Zeichen zu Binär konvertieren<br />
Mikrocomputertechnik<br />
Unterprogramm zur Konvertierung eines ASCII-Zeichens (0 - 9, A - F) in einen Binärwert, z.B. bei<br />
der Eingabe von Zahlen über das Terminal. Das Zeichen wird in Akku A übergeben und der Wert<br />
wieder in A zurückgegeben. Das UP arbeitet invers zum obigen UP. Bei Fehleingabe (keine Ziffer)<br />
wird Akku A auf $FF gesetzt.<br />
*<br />
* Unterprogramm ASCII-Binär-Konvertierung (0 - 9, A - F)<br />
* Parameter in A<br />
*<br />
ASCBIN SUBA #$30 ; $30 = ASCII "0"<br />
BLO FEHL ; Erg. negativ keine Ziffer<br />
CMPA #9 ; kleiner oder gleich 9?<br />
BLS DONE ; dann fertig<br />
SUBA #7 ; "A" - "F" 10 - 15<br />
CMPA #10 ; kleiner als 10?<br />
BLO FEHL ; dann Fehler<br />
CMPA #15 ; größer 15?<br />
BLS DONE ; nein, fertig<br />
FEHL LDAA #$FF ; Fehlerflag setzen<br />
DONE RTS<br />
Binär zu ASCII-Decodierung (1, 2 oder 4 Stellen)<br />
Im Speicher liegen die Werte bekanntermaßen binär vor. Um einen Speicherinhalt oder eine Adresse<br />
auf der seriellen Schnittstelle (Terminal) oder einem LC-Display ausgeben zu können, müsen die<br />
Werte als ASCII-Zeichen dargestellt werden.<br />
Die folgenden vier miteinander verbundenen Unterprogramme erweitern das Beispiel oben und<br />
wandeln einen 16-Bit-Wert, einen 8-Bit-Wert (Byte) oder einen 4-Bit-Wert (Nibble) in eine<br />
Hexadezimalzahl in ASCII-Darstellung um (4, 2, oder 1 Stelle):<br />
• hx4a wandelt den Inhalt von Akku D in vier ASCII-Zeichen, die in einem 4 Byte langen<br />
Puffer abgelegt werden. Beim Unterprogrammaufruf muß das Indexregister Y auf die letzte<br />
Stelle des Puffers zeigen.<br />
• hx2a wandelt den Inhalt von Akku B in zwei ASCII-Zeichen, die in einem 2 Byte langen<br />
Puffer abgelegt werden. Beim Unterprogrammaufruf muß das Indexregister Y auf die letzte<br />
Stelle des Puffers zeigen.<br />
Nützliche Unterprogramme 171
Mikrocomputertechnik<br />
• hx1a wandelt den Inhalt von Akku B (Bits 0-3) in ein ASCII-Zeichen, das in einem 1 Byte<br />
langen Puffer abgelegt wird. Beim Unterprogrammaufruf muß das Indexregister Y auf den<br />
Puffers zeigen.<br />
Diese Unterprogramme werden beim vierten Praktikumstermin benötigt.<br />
hx4a psha ; Akku A auf dem Stack ablegen<br />
bsr hx2a ; Akku B umwandeln (Stelle 3 und 4)<br />
pulb ; Akku A vom Stack holen, in Akku B ablegen<br />
; Nun einfach in hx2a fallen und Akku B<br />
; umwandeln (Stelle 1 und 2)<br />
hx2a pshb ; Akku B aud dem Stack sichern<br />
bsr hx1a ; Bits 0-3 von Akku B umwandeln<br />
pulb ; Original-Akku B wieder holen<br />
lsrb ; viermal schieben (Bits 4-7 --> 0-3)<br />
lsrb<br />
lsrb ; und nun die obere Haelfte umwandeln<br />
lsrb ; indem einfach in hx1a gefallen wird<br />
; Nun wird die eigentliche Arbeit gemacht:<br />
hx1a andb #$0F ; die oberen 4 Bita ausmaskieren<br />
addb #48 ; ASCII-Wert von "0" addieren<br />
cmpb #57 ; groesser als "9"?<br />
bls hx1b ; nein, dann speichern<br />
addb #7 ; sonst die Distanz zwischen "9" und "a" addieren<br />
hx1b stab 0,y ; Im Speicher ablegen, auf den Y zeigt<br />
dey ; Y zeigt jetzt auf die Stelle davor<br />
rts ; und weg<br />
Überlesen von Leerzeichen am Anfang einer Zeichenkette<br />
Nach Ausführung zeigt X auf das erste Zeichen != ' '. Der String muß mit einem Zeichen != '<br />
' abgeschlossen sein.<br />
LDX #STRING ; Beginn der Zeichenkette<br />
CHECK LDAA 0,X ; Zeichen lesen<br />
INX ; X erhoehen<br />
CHECK CMPA #$20 ; Leerzeichen?<br />
BEQ CHECK ; Ja, weiter testen<br />
DEX ; nein, Zeiger korrigieren<br />
.<br />
.<br />
.<br />
STRING DC.B ' Zeichenkette mit 4 Leerzeichen am Anfang'<br />
DC.B 0 Abschlußzeichen<br />
Beispiel: Vergleich zweier Zeichenketten (Strings)<br />
Die Adressen der beiden Zeichenketten werden in X und Y übergeben. Als Ergebnis wird Akku A<br />
verwendet - 0: Strings sind ungleich, FF: Strings sind gleich<br />
; Vergleich zweier Strings, Anfangsadressen in X und Y<br />
; Ergebnis wird in Akku A zurueckgegeben (0: ungleich, FF: gleich)<br />
vergl ldaa 0,X ; Zeichen aus String 1 vergleichen<br />
cmpa 0,Y ; mit Zeichen aus String 2<br />
bne ver0 ; Strings ungleich, fertig<br />
cmpa #0 ; Stringende<br />
beq ver1 ; Strings sind gleich, fertig<br />
inx ; naechstes Zeichen<br />
iny<br />
bra vergl<br />
ver1 ldaa #$ff<br />
rts<br />
Nützliche Unterprogramme 172
ver0 clra<br />
rts<br />
Delay-Routine<br />
Das folgende Unterprogramm erlaubt längere Verzögerungszeiten als das in Kapitel 3 vorgestellte, da<br />
hier das 16-Bit-Register X verwendet wird. "delay" dauert 4 + 3 + $f422*16 + 4 + 5 + 5 Taktzyklen,<br />
was einer Wartezeit von 8,5 + $f422*8 µs = 499992,5 µs entspricht - also ungefähr 0,5 s.<br />
delay pshx ; Register x retten, 4 cycl<br />
ldx #$f211 ; Anfangswert laden, 3 cycl<br />
delay1 nop ; 5 x nop = 10 cycl<br />
nop<br />
nop<br />
nop<br />
nop<br />
dex ; X runterzaehlen, 3 cycl<br />
bne delay1 ; 3 cycl<br />
pulx ; Register restaurieren, 5 cycl<br />
rts ; 5 cycl<br />
Delay-Routine - Angabe der Frequenz<br />
Die Frequenz wird in Akku B übergeben (Werte zwischen 1 und 15).<br />
delay clra ; Akku D: Akku A = 0, Akku B = Wert<br />
andb #$0F<br />
beq del_end ; Division durch 0 verhindern<br />
ldx #$FF00 ; Wert fuer 1 Hz --> X<br />
xgdx ; Schalter in X, 1-Hz-Wert in D<br />
idiv ; D/X<br />
delay1 nop<br />
nop<br />
nop<br />
nop<br />
nop<br />
nop<br />
nop<br />
dex<br />
bne delay1<br />
del_end rts<br />
Demo 16-Bit-Tabellenzugriff<br />
Die Variablen sek und zsek werden gemeinsam aus einer Tabelle belegt. Die Auswahl des<br />
Tabellenelementes erfolgt über 4 Schalter an Port C.<br />
org data<br />
sek ds.b 1<br />
zsek ds.b 1<br />
Mikrocomputertechnik<br />
org prog<br />
main lds #stack ; Initialisierung<br />
clr portb<br />
ldaa #%11110000 ; Bits 0-3 als Eingang<br />
staa ddrc<br />
loop ldab portc ; Schalter einlesen<br />
andb #$0F<br />
lslb ; Akku B * 2, weil 16-Bit-Zugriff<br />
; (jeweils 2 Byte)<br />
ldx #tabelle ; Tabellenzugriff: X zeigt aus Tab.-Anfang<br />
Nützliche Unterprogramme 173
abx ; aktuelle Position: B + X<br />
ldd 0,X ; Wert laden<br />
std sek ; Sekunden in sek, 1/10 in zsek<br />
jmp loop<br />
* 0 1 2 3 4 5 6 7<br />
tabelle dc.b 0,0, 2,5, 4,0, 10,0, 15,5, 20,0, 25,3, 31,4,<br />
* 8 9 10 11 12 13 14 15<br />
dc.b 40,0, 51,2, 60,0, 65,8, 72,4, 80,1, 85,7, 95,3<br />
Zufallszahlen<br />
Bei C gibt es in der Regel eine Random-Funktion, die Pseudo-Zufallszahlen liefert. In <strong>Assembler</strong><br />
muss man, sofern es keine passende Bibliothek gibt, selbst eine entsprechende Funktion<br />
programmieren. Im Folgenden wird eine typische Form der Implementierung verwendet, um<br />
8-Bit-Zufallszahlen zu generieren. Es handelt sich um die 16-Bit-Variante der klassischen Formel S' =<br />
S * M + A. Als Zufallswert wird das Highbyte der 16-Bit-"Seed" des Zufallsgenerators im Akku A<br />
zurückgegeben. Für die Konstanten werden die Werte M = 181 und A = 359 aus folgenden Gründen<br />
gewählt:<br />
• Beide Werte sind Primzahlen.<br />
• Die Gleichung durchläuft mit diesem Werten alls 65 536 möglichen Werte für die "Seed".<br />
• Es gibt keine Wiederholungen von Sequenzen mit 4 oder mehr Werten<br />
• Die Random-Werte sind relativ gleichverteilt<br />
Die Funktion benötigt wenig Speicherplatz und nur 4 Byte RAM. Mit dem Unterprogramm RndInit<br />
wird der Anfangswert der "Seed" auf Null gesetzt. Sie können aber auch jeden beliebigen<br />
Anfangswert verwenden - etwa den Eingangswert eines A/D-Wandler-Ports.<br />
data equ $2000 ; Datenbereich<br />
prog equ $8000 ; Programmbereich<br />
stack equ $7FFF ; Stackbereich<br />
resetv equ $FFFE ; Adresse Reset-Vektor<br />
pcdd equ $1007 ; Adressen Port C<br />
pcdr equ $1003<br />
* Random-Constants:<br />
RndMult equ 181 ; Multiplikationsfaktor<br />
RndAdd equ 359 ; zu addierender Offset<br />
org data<br />
RndSeed ds.b 2 ; 2 Byte Random Seed<br />
RndTmp ds.b 2 ; temporaerer Speicher<br />
org prog<br />
main lds #stack ; Init Stack<br />
ldaa #$FF<br />
staa pcdd ; Port C als output<br />
clr pcdr<br />
bsr RndInit ; Seed = 0<br />
loop bsr Random ; A = random number<br />
staa pcdr ; A -> Port C<br />
bsr Delay ; wait<br />
bra loop<br />
* Initialize the random number generator<br />
RndInit clr RndSeed<br />
clr RndSeed+1<br />
rts<br />
Mikrocomputertechnik<br />
Nützliche Unterprogramme 174
* Return the next 8-bit pseudo random number<br />
* Berechnet SEED = SEED * 181 + 359<br />
* return high byte of the new SEED in A<br />
* Return value: The A register.<br />
Random pshb ; save B<br />
* scratch = seed * RndMult<br />
ldaa #RndMult ; A = #181<br />
ldab RndSeed+1 ; B = low byte of the seed<br />
mul ; D = A x B<br />
std RndTmp ; scratch = D<br />
ldaa #RndMult ; A = #181<br />
ldab RndSeed ; B = high byte of the seed<br />
mul ; D = A x B<br />
* low byte of mult. result is added to the high byte of scratch<br />
addb RndTmp ; B = B + scratch_high<br />
stab RndTmp ; scratch = seed * 181<br />
ldd RndTmp ; D = scratch<br />
addd #RndAdd ; D = D + 359<br />
std RndSeed ; save new seed value<br />
* A holds RndSeed from addition<br />
pulb ; retore B<br />
rts<br />
* Delay wie ueblich ...<br />
Delay LDX #$FFFF<br />
LoopX DEX<br />
BNE LoopX<br />
RTS<br />
org resetv ; Reset-Vektor setzen<br />
dc.w main<br />
Komplette Programmbeispiele<br />
Die folgenden Programme sind vollständig und lassen sich direkt assemblieren, simulieren und im<br />
Zielsystem ausführen.<br />
Ausgabe beliebiger Bitmuster<br />
Mikrocomputertechnik<br />
Es wird ein Array mit Bitmustern angelegt ("muster"), die nacheinander auf Port B ausgegeben<br />
werden. Ein Nullbyte markiert das Ende des Arrays. Wenn dies erreicht ist, beginnt die Ausgabe<br />
wieder beim ersten Element. Das Array ist beliebig erweiterbar.<br />
prog equ $8000 ; Vereinbarungen<br />
data equ $2000<br />
stack equ $7FFF<br />
portb equ $1004<br />
reset equ $fffe<br />
org prog<br />
main lds #stack<br />
ldx #muster ; X verweist auf das erste Feldelement<br />
loop ldaa 0,x ; erstes Feldelement laden<br />
bne ausg ; wenn nicht 0, ausgeben<br />
ldx #muster ; sonst wieder zum ersten Element<br />
bra loop ; ohne Ausgabe<br />
ausg staa portb ; Bitmuster ausgeben<br />
jsr delay ; 0,5 s warten<br />
inx ; naechstes Element<br />
bra loop<br />
delay pshx ; Delay, siehe oben<br />
ldx #$f422<br />
delay1 nop<br />
Komplette Programmbeispiele 175
nop<br />
nop<br />
nop<br />
nop<br />
dex<br />
bne delay1<br />
pulx<br />
rts<br />
muster dc.b %11110000, %01111000, %00111100, %00011110<br />
dc.b %00001111, %00011110, %00111100, %01111000<br />
dc.b %0<br />
org reset ; Reset-Vektor setzen<br />
fdb main<br />
end<br />
Dezimal zu Siebensegment Codierung<br />
Der Inhalt von Akkumulator B soll in die Siebensegmentdarstellung gemäß untenstehender Abbildung<br />
umcodiert werden. Der erzeugte Code wird ebenfalls in Akku B zurückgegeben. Bei Werten größer 9,<br />
soll B mit $FF besetzt werden.<br />
prog equ $8000<br />
data equ $2000<br />
stack equ $7FFF<br />
portb equ $1004<br />
reset equ $fffe<br />
org data<br />
count ds.b 1<br />
Mikrocomputertechnik<br />
org prog<br />
main lds #stack<br />
clr count ; Speicher loeschen<br />
loop ldab count ; Schleifenbeginn, count mod 16 hochzaehlen<br />
incb<br />
andb #$0F<br />
stab count<br />
bsr umco ; Count in Akku B wird umcodiert, Ergebnis in Akku B<br />
stab portb ; und ausgeben<br />
jsr delay ; 0,5 s warten<br />
bra loop<br />
; Umcodierung binaer --> 7-Segment, eingabe und Ausgabe in Akku B<br />
umco ldx #umcotab ; Tabellenadresse laden<br />
andb #$0F ; fuer B nur Werte 0 - F zulassen<br />
abx ; X = X + B<br />
ldab 0,x ; 7-Sement-Wert holen, Adressierung durch X-Register<br />
rts<br />
Komplette Programmbeispiele 176
delay pshx ; Delay, siehe oben<br />
ldx #$f422<br />
delay1 nop<br />
nop<br />
nop<br />
nop<br />
nop<br />
dex<br />
bne delay1<br />
pulx<br />
rts<br />
; Siebensegment-Tabelle (Segmentanordnung: -abcdefg)<br />
; Die Ziffern "0" bis "9" sind decodiert, fuer "A" bis "F"<br />
; wird nur ein "-" angezeigt --> noch zu ergaenzen<br />
umcotab dc.b %01111110, %00110000, %01101101, %01111001<br />
dc.b %00110011, %01011011, %01011111, %01110000<br />
dc.b %01111111, %01111011, %00000001, %00000001<br />
dc.b %00000001, %00000001, %00000001, %00000001<br />
org reset<br />
fdb main<br />
end<br />
Serielle Eingabe mit Backspace und Ignorieren von Zeichen < " "<br />
gets stx pufanf<br />
gets0 bsr recv<br />
cmpb #cr<br />
beq gets1<br />
cmpb #bs<br />
beq gets2<br />
cmpb #' ' ; Zeichen < ' ' ignorieren<br />
blo gets0<br />
bsr send<br />
stab 0,x<br />
inx<br />
bra gets0<br />
gets1 clrb ; Newline - Eingabeende<br />
stab 0,x ; Nullbeit als Abschluss<br />
bsr crlf ; cr + lf ausgeben<br />
rts<br />
gets2 cpx pufanf ; Backspace<br />
beq gets0 ; nur bis Pufferanfanng zurück<br />
dex<br />
ldab #bs ; BS , Leer, BS ausgeben<br />
bsr send<br />
ldab #' '<br />
bsr send<br />
ldab #bs<br />
bsr send<br />
bra gets0<br />
; cr+lf ausgeben<br />
crlf ldab #cr<br />
bsr send<br />
ldab #lf<br />
bsr send<br />
rts<br />
Mikrocomputertechnik<br />
Komplette Programmbeispiele 177
Kommandoeingabe über die serielle Schnittstelle<br />
; Vereinbarungen<br />
prog equ $8000<br />
data equ $2000<br />
stack equ $7FFF<br />
portb equ $1004<br />
portc equ $1003<br />
portcl equ $1005<br />
pioc equ $1002<br />
ddrc equ $1007<br />
scdr equ $102f<br />
scsr equ $102e<br />
sccr1 equ $102c<br />
sccr2 equ $102d<br />
baud equ $102b<br />
reset equ $fffe<br />
; ASCII-Zeichen<br />
cr equ 13<br />
lf equ 10<br />
org prog<br />
main lds #stack ; Initialisierungen<br />
bsr sini<br />
loop ldx #cmd ; Prompt ausgeben<br />
bsr ssend<br />
bsr recv ; Befehl (1 Zeichen) einlesen<br />
cmpa #'a' ; ist es 'a'?<br />
bne next1 ; nein, weiter<br />
bsr doit ; Kommando 'a' verarbeiten<br />
bra loop<br />
next1 cmpa #'b' ; ist es 'b'?<br />
bne next2 ; nein, weiter<br />
bsr doit ; Kommando 'b' verarbeiten<br />
bra loop<br />
next2 cmpa #'c' ; ist es 'c'?<br />
bne next3 ; nein, weiter<br />
bsr doit ; Kommando 'c' verarbeiten<br />
bra loop<br />
next3 ldx #oops ; falsche Eingabe: "Oops" ausgeben<br />
bsr ssend<br />
bra loop<br />
; Kommandobearbeitungsroutine, hier als Dummy<br />
doit psha ; Kommandobearbeitung, erst Akku A retten<br />
ldx #k1 ; Text "Eingabe war" ausgeben<br />
bsr ssend<br />
pula ; Akku A wiederherstellen<br />
suba #$20 ; Kleinbuchstaben in Grossbuchstaben wandeln<br />
bsr send ; ausgeben<br />
bsr crlf ; "neue Zeile" ausgeben<br />
rts<br />
; Carriage Return und Line Feed ausgeben<br />
crlf ldaa #cr<br />
bsr send<br />
ldaa #lf<br />
bsr send<br />
rts<br />
Mikrocomputertechnik<br />
; String ausgeben (ohne cr/lf am Ende), Stringadresse (erstes Zeichen)<br />
Komplette Programmbeispiele 178
; muss in Register X uebergeben werden (siehe Kapitel 5)<br />
ssend ldaa 0,x<br />
beq sfin<br />
bsr send<br />
inx<br />
bra ssend<br />
sfin rts<br />
; serielle Schnittstelle initialisieren (siehe Kapitel 5)<br />
sini clr sccr1<br />
ldaa #$0C<br />
staa sccr2<br />
ldaa #$30<br />
staa baud<br />
rts<br />
; Zeichen seriell ausgeben (siehe Kapitel 5)<br />
send ldab scsr<br />
bpl send<br />
staa scdr<br />
rts<br />
; Zeichen seriell empfangen (siehe Kapitel 5)<br />
recv ldab scsr<br />
andb #$20<br />
beq recv<br />
ldaa scdr<br />
rts<br />
; String-Konstanten (Strings werden durch ein 0-Byte abgeschlossen)<br />
cmd dc.b 'Kommando: '<br />
dc.b 0<br />
oops dc.b 'Oops!'<br />
dc.b cr,lf,0<br />
k1 dc.b 'Eingabe war '<br />
dc.b 0<br />
org reset ; Reset-Vektor setzen<br />
fdb main<br />
end<br />
Demo für den Timer-Interrupt<br />
Das Programm zählt eine Variable "count" interruptgesteuert hoch.<br />
prog equ $8000<br />
data equ $2000<br />
stack equ $7FFF<br />
portb equ $1004<br />
portc equ $1003<br />
ddrc equ $1007<br />
reset equ $fffe<br />
tvec equ $FFDE ; interrupt vector of timer<br />
tmsk equ $1024 ; timer mask<br />
tflg equ $1025 ; timer flag<br />
pacr equ $1026 ; pulse accu control<br />
org data<br />
count ds.b 1<br />
cflg ds.b 1<br />
org prog<br />
main lds #stack ; init variables<br />
clr portb<br />
Mikrocomputertechnik<br />
Komplette Programmbeispiele 179
clr count<br />
clr cflg<br />
ldab #$40 ; enable PA7 interrupt<br />
stab pacr ; enable pulse accu<br />
ldab #$80<br />
stab tmsk<br />
cli ; enable interrupts<br />
loop ldaa cflg ; get clock flag<br />
cmpa #20 ; trigger point?<br />
bne loop ; no, wait<br />
clr cflg ; yes, clear clock flag<br />
inc count ; count up<br />
ldaa count<br />
staa portb ; display counter<br />
bra loop<br />
; interrupt service routine<br />
tirq ldaa #$80<br />
staa tflg ; clear interrupt<br />
inc cflg ; count interrupts<br />
rti<br />
org tvec ; set interrupt vector<br />
fdb tirq ; DE timer overflow<br />
org reset ; set reset vector<br />
fdb main<br />
end<br />
Demo für Interrupt an STRA<br />
data equ $2000 ; data area (e-ram)<br />
stak equ $7FFF ; stack area (e-ram)<br />
prog equ $8000 ; programm area (e-eerom)<br />
pvec equ $FFDA ; vector pa7<br />
tvec equ $FFDE ; vector timer<br />
svec equ $FFF2 ; sirq vector<br />
rvec equ $FFFE ; reset vector<br />
pioc equ $1002 ; parallel i/o control<br />
pbdr equ $1004 ; port b data<br />
portcl equ $1005 ; port c data latch<br />
tmsk equ $1024 ; timer mask<br />
tflg equ $1025 ; timer flag<br />
pacr equ $1026 ; pulse accu control<br />
***************************<br />
* data area *<br />
***************************<br />
org data<br />
flag ds.b 1 ; irq flag<br />
***************************<br />
* program area *<br />
***************************<br />
org prog<br />
main lds #stak ; load stackpointer<br />
bsr init ; data init<br />
cli ; enable irq<br />
loop ldaa flag<br />
Mikrocomputertechnik<br />
Komplette Programmbeispiele 180
staa pbdr ; display<br />
bra loop ; close main loop<br />
***************************<br />
* subroutines *<br />
***************************<br />
init clr flag<br />
ldab #$40 ; enable STRA interrupt<br />
stab pioc<br />
rts<br />
***************************<br />
* interrupt handler *<br />
***************************<br />
sirq ldaa pioc ; stra isr<br />
ldaa portcl ; clear interrupt<br />
com flag<br />
rti<br />
***************************<br />
* vectors *<br />
***************************<br />
org svec<br />
fdb sirq ; STRA<br />
org rvec<br />
fdb main ; FE reset<br />
end<br />
Demo für Interrupts an STRA und PA7<br />
data equ $2000 ; data area (e-ram)<br />
stak equ $7FFF ; stack area (e-ram)<br />
prog equ $8000 ; programm area (e-eerom)<br />
pvec equ $FFDA ; vector pa7<br />
tvec equ $FFDE ; vector timer<br />
svec equ $FFF2 ; sirq vector<br />
rvec equ $FFFE ; reset vector<br />
pioc equ $1002 ; parallel i/o control<br />
pbdr equ $1004 ; port b data<br />
pcdl equ $1005 ; port c data latch<br />
tmsk equ $1024 ; timer mask<br />
tflg equ $1025 ; timer flag<br />
pacr equ $1026 ; pulse accu control<br />
baud equ $102B ; SCI-baudrate<br />
sccr1 equ $102C ; SCI-control1<br />
sccr2 equ $102D ; SCI-control2<br />
scsr equ $102E ; SCI-status<br />
scdr equ $102F ; SCI-data<br />
***************************<br />
* data area *<br />
***************************<br />
org data<br />
flag ds.b 1 ; irq flag<br />
***************************<br />
* program area *<br />
***************************<br />
Mikrocomputertechnik<br />
Komplette Programmbeispiele 181
org prog<br />
main lds #stak ; load stackpointer<br />
bsr init ; data init<br />
cli ; enable irq<br />
loop ldaa flag<br />
staa pbdr ; display<br />
bra loop ; close main loop<br />
***************************<br />
* subroutines *<br />
***************************<br />
init clr flag<br />
ldab #$40 ; enable STRA interrupt<br />
stab pioc<br />
ldab #$40 ; enable PA7 interrupt<br />
stab pacr<br />
ldab #$10<br />
stab tmsk<br />
rts<br />
***************************<br />
* interrupt handler *<br />
***************************<br />
sirq ldaa pioc ; stra isr<br />
ldaa pcdl ; clear interrupt<br />
ldaa flag<br />
eora #$0F ; toggle lower nibble<br />
staa flag<br />
rti<br />
pirq ldaa #$10 ; pa7 isr<br />
staa tflg ; clear interrupt<br />
ldaa flag<br />
eora #$F0 ; toggle upper nibble<br />
staa flag<br />
rti<br />
***************************<br />
* vectors *<br />
***************************<br />
org pvec<br />
fdb pirq ; PA7 interrupt<br />
org svec<br />
fdb sirq ; STRA<br />
org rvec<br />
fdb main ; FE reset<br />
end<br />
Demo für Interrupts an STRA, PA7 und Timer<br />
data equ $2000 ; data area (e-ram)<br />
stak equ $7FFF ; stack area (e-ram)<br />
prog equ $8000 ; programm area (e-eerom)<br />
pvec equ $FFDA ; vector pa7<br />
tvec equ $FFDE ; vector timer<br />
svec equ $FFF2 ; sirq vector<br />
rvec equ $FFFE ; reset vector<br />
Mikrocomputertechnik<br />
Komplette Programmbeispiele 182
pioc equ $1002 ; parallel i/o control<br />
pbdr equ $1004 ; port b data<br />
pcdl equ $1005 ; port c data latch<br />
tmsk equ $1024 ; timer mask<br />
tflg equ $1025 ; timer flag<br />
pacr equ $1026 ; pulse accu control<br />
***************************<br />
* data area *<br />
***************************<br />
org data<br />
coun ds.b 1 ; counter<br />
cflg ds.b 1 ; clock flag<br />
updn ds.b 1 ; direction flag<br />
stop ds.b 1 ; stop flag<br />
***************************<br />
* program area *<br />
***************************<br />
org prog<br />
main lds #stak ; load stackpointer<br />
bsr init ; data init<br />
cli ; enable irq<br />
loop ldaa cflg ; get clock flag<br />
cmpa #20 ; trigger point?<br />
bne loop ; no, wait<br />
clr cflg ; yes, clear clock flag<br />
tst stop ; stop active?<br />
bne loop ; yes, wait<br />
bsr count ; update counter<br />
bra loop ; close main loop<br />
***************************<br />
* subroutines *<br />
***************************<br />
count ldaa coun ; load counter<br />
adda updn ; inc/dec counter<br />
staa coun ; save counter<br />
staa pbdr ; display counter<br />
rts<br />
init clr coun ; counter default<br />
clr cflg ; no clock seen<br />
clr stop<br />
ldaa #1<br />
staa updn ; default count up<br />
ldab #$40 ; enable STRA interrupt<br />
stab pioc<br />
ldab #$40 ; enable PA7 interrupt<br />
stab pacr ; enable pulse accu<br />
ldab #$90 ; $80 (Timer) + $10 (PA7)<br />
stab tmsk<br />
rts<br />
***************************<br />
* interrupt handler *<br />
***************************<br />
Mikrocomputertechnik<br />
Komplette Programmbeispiele 183
tirq ldaa #$80 ; timer isr<br />
staa tflg ; clear interrupt<br />
inc cflg ; count interrupts<br />
rti<br />
sirq ldaa pioc ; stra isr<br />
ldaa pcdl ; clear interrupt<br />
neg updn ; toggle direction<br />
rti<br />
pirq ldaa #$10 ; pa7 isr<br />
staa tflg ; clear interrupt<br />
com stop ; toggle stop flag<br />
rti<br />
***************************<br />
* vectors *<br />
***************************<br />
org pvec<br />
fdb pirq ; PA7<br />
org tvec<br />
fdb tirq ; timer overflow<br />
org svec<br />
fdb sirq ; STRA<br />
org rvec<br />
fdb main ; FE reset<br />
end<br />
Zum vorhergehenden Abschnitt Zum Inhaltsverzeichnis Zum nächsten Abschnitt<br />
Copyright © FH München, FB 04, Prof. Jürgen Plate<br />
Letzte Aktualisierung: 02. Jul 2012<br />
Mikrocomputertechnik<br />
Mikrocomputertechnik<br />
Prof. Jürgen Plate, Prof. Peter Schwalb<br />
Komplette Programmbeispiele 184
Praktikum Mikrocomputer<br />
Allgemeines<br />
Im Rahmen dieses Praktikums sollen einfache Programme in Maschinensprache erstellt und auf dem<br />
Mikrocomputer PS11 erprobt werden. Dabei werden neben dem Einüben des Befehlsvorrats eines<br />
typischen Mikroprozessors die Problematiken der Unterprogrammtechnik, Stackbehandlung,<br />
Unterbrechungsbehandlung und Behandlung von parallelen und seriellen Schnittstellen untersucht.<br />
Ergänzende Zusatzschaltungen werden in TTL-Technik aufgebaut.<br />
Der Mikrocomputer PS11 baut auf dem Mikrocontroller M68HC11 (8MHz) von Motorola auf. Er<br />
wird im expanded mode betrieben und ist mit einer PRU M68HC24, 32kByte RAM und 32 kByte<br />
EEPROM als externen Komponenten versehen. Die Programmentwicklung erfolgt auf einem PC unter<br />
Verwendung eines unter Windows XP laufenden Programmpakets (Integrated Development<br />
Environment for M68HC11). Dieses ermöglicht das Editieren, Assemblieren, Simulieren und<br />
Bereitstellen von Programmen für den M68HC11. Der Datentransfer zwischen PC und Zielrechner<br />
erfolgt über eine serielle Schnittstelle (COM-Port COM1 mit 9600 Baud).<br />
Die Angaben zu den einzelnen Versuchen sind als thematischer Rahmen zu sehen. Die<br />
Aufgabenstellung kann durch den betreuenden Dozenten jederzeit modifiziert werden. Im Verlauf des<br />
Versuchs ist auf eine vernünftige Dokumentation zu achten.<br />
Installation der IDE-Software<br />
Die Programme des Pakets HC11-IDE.zip benötigen keine spezielle Installation, sondern laufen unter<br />
Windows (ab XP) wie sie sind. Um sich das Leben zu erleichtern, können Sie das Paket jedoch in die<br />
übliche Windows-Umgebung einbinden:<br />
• Unter C:\Programme (bzw. C:\Program Files) legen Sie ein Verzeichnis namens<br />
"HC11-IDE" an.<br />
• Entpacken Sie alle Programme der ZIP-Datei in dieses Verzeichnis. Das war's eigentlich<br />
schon.<br />
• Erzeugen Sie sich eine Verknüpfung des Programms scite.exe auf dem Desktop für den<br />
schnellen Zugriff. Wer will, kann auch noch eine Verknüpfung in der Taskleiste anlegen.<br />
• Unter Windows 7 erhalten Sie beim Beenden des Simulators eine Fehlermeldung. Das<br />
Problem kann behoben werden, indem Sie auf die Datei wookie182upx.exe mit der rechten<br />
Maustaste klicken und im Menü dann "Behandeln von Kompatibilitätsproblemen" klicken -<br />
Windows erledigt den Rest.<br />
• Anstelle des Windows Hyperterminals kann auch das Programm PuTTY für die serielle<br />
Kommunikation auf der PC-Seite verwendet werden. Sie erhalten die aktuelle Version unter<br />
http://www.putty.org/. Auch dieses Programm benötigt keine spezielle Installation.<br />
Einschalten und Starten<br />
Der Arbeitsplatz ist über den Sicherungsautomaten, der PC über den Netz-Taster am PC-Gehäuse und<br />
das Testobjekt mittels seines Netzschalters in der Rückwand einzuschalten. Achtung: Zum<br />
Ausschalten dient der kleine rechteckige, rote Knopt am Sicherungsautomaten, nicht der<br />
Not-Aus-Taster! Nach dem Start von Windows XP sind Benutzername und Kennwort einzugeben.<br />
Benutzername (user): ide11<br />
Kennwort (password): ide11<br />
Praktikum Mikrocomputer 185
Das Programm HC11-IDE11 wird durch klicken auf das entsprechende Icon gestartet. Wenn Sie<br />
IDE11 mehr als einmal starten, verweigern alle Inkarnationen des Programms den Kontakt zum<br />
M68HC11. In diesem Fall sind alle laufenden Versionen zu schließen und das Programm einmal neu<br />
zu starten.<br />
Programm-Namen und Ordner SAVE<br />
Quellprogramme (Sourcecodes) sind immer mit der Kennung (Extension) ".a" zu versehen (z. B.<br />
"versuch1_1.a"), da Editor und <strong>Assembler</strong> des Systems diese Kennung erwarten.<br />
Die im Laufe eines Praktikums-Versuchs erstellten (name.a) oder erzeugten (name.lst) Dateien sind<br />
über den Ordner (Directory) Eigene Dateien verfügbar. Sie können von dort aus auf Diskette oder<br />
einem USB-Massenspeicher abgespeichert werden. Wenn Sie vorbereitete Programme auf Diskette<br />
oder USB-Massenspeicher mitbringen, dann speichern Sie diese auch immer in diesem Ordner ab.<br />
Beenden und Abschalten<br />
Mikrocomputertechnik<br />
Wurde IDE11 versehentlich beendet, kann es über Doppelklicken des Symbols (Icon) des<br />
Arbeitsplatzes (Desktop) wieder gestartet werden.<br />
Der Praktikumsrechner PS11 ist nicht auszuschalten, sondern nur herunterzufahren:<br />
(START Wurde HC11-IDE11 versehentlich beendet, kann es über Doppelklicken des Symbols (Icon)<br />
des Arbeitsplatzes (Desktop) wieder gestartet werden. Der Praktikumsrechner PS11 ist nicht<br />
auszuschalten, sondern nur herunterzufahren: (START → Computer ausschalten).<br />
Bearbeiten eines Quellprogramms<br />
Einschalten und Starten 186
File → New<br />
Erzeugt ein leeres Editorfenster mit dem Namen "Untitled". Beim ersten Speichern wird ein SAVE AS<br />
ausgeführt.<br />
File → Open<br />
Eine Datei (Quellprogramm) kann aus dem Arbeitsverzeichnis ausgewählt und geöffnet werden. Für<br />
die Bearbeitung der Datei mittels Tasten und Maus (Markieren, Kopieren, Verschieben, etc.) gelten<br />
die üblichen Regeln. Weitere Funktionen werden im Menue "EDIT" angeboten. Es können auch<br />
mehrere Fenster geöffnet werden. Die Bearbeitungsvorgänge beziehen sich immer auf das aktive<br />
(oben liegende) Fenster.<br />
File → Save<br />
Speichert den Inhalt des aktiven (oben liegenden) Editorfensters als Textdatei. Ist der Dateiname noch<br />
nicht festgelegt, wird ein "SAVE AS"-Befehl ausgeführt und der Dateiname erfragt.<br />
File → Save As<br />
Mikrocomputertechnik<br />
Erfragt den gewünschten Dateinamen und speichert den Inhalt des aktiven (oben liegenden) Fensters<br />
als Textdatei (name.a).<br />
Erst nachdem die Datei mit der Erweiterung .a abgespeichert wurde wird das Syntax Highlighting<br />
aktiviert:<br />
Übersetzen eines Quellprogramms (source code)<br />
Bearbeiten eines Quellprogramms 187
Tools → Assemble<br />
Der Start des <strong>Assembler</strong>s erfolgt über das Menü "Tools" im Editor. Ein neues oder verändertes<br />
Quellprogramm im aktiven Fenster wird abgespeichert und anschließend übersetzt. Bei fehlerfreiem<br />
Ablauf der Übersetzung werden ein Zielprogramm (name.s19) und ein Programmlisting (name.LST)<br />
erzeugt. Eine gegebenenfalls erzeugte Fehlerliste wird im Ausgabe-Fenster (unterhalb des<br />
Editor-Fensters) angezeigt. Durch Doppelklick auf den angezeigten Fehler (Error: xxxxx) wird im<br />
Quellprogamm die fehlerhafte Zeile markiert.<br />
Anmerkung: Lassen Sie sich nicht durch die letzte Ausgabezeile des Editors ( → Exit-Code: 0)<br />
täuschen, diese besagt nur, dass das <strong>Assembler</strong>programm nicht abgestürzt ist.<br />
Simulieren eines Zielprogramms (object code)<br />
Tools → Simulate<br />
Mikrocomputertechnik<br />
Der Start des Simulators erfolgt ebenfalls über das Menü "Tools" im Editor. Das Zielprogramm wird<br />
in den Simulator geladen. Hier kann das Programm in einem simulierten PS11 System erprobt werden.<br />
Übersetzen eines Quellprogramms (source code) 188
Mikrocomputertechnik<br />
Der Simulator ist nicht in der Lage, alle Eigenschaften des 68HC11 exakt nachzubilden. So müssen<br />
Sie auf manche Interrupts und einiges andere verzichten. So ist derzeit keine umfassende Simulation<br />
der seriellen Schnittstelle möglich.<br />
Bei der Simulation des STRA-Eingangs mit dem Button [STRA = 0] ist folgendes zu beachten:<br />
• Mit jedem Anklicken wechselt der Zustand der (virtuellen) STRA-Eingansleitung zwischen 0<br />
und 1.<br />
• Um eine Flanke zu erzeugen, wie es der Taster auf dem Steckbrett bewirkt, muss deshalb<br />
zweimal auf den Button geklickt werden.<br />
Ähnlich verhält es sich beim Eingang PA7. Hier holen Sie sich den Port A auf die Arbeitsfläche des<br />
Simulators und klicken auf das höchstwertige Bit (7). Auch hier muss, um eine Flanke zu erzeugen,<br />
wie es der Taster auf dem Steckbrett bewirkt, zweimal auf das Bit geklickt werden.<br />
Je nach verwendetem PC-Modell kann es auch vorkommen, dass Zeitschleifen im Simulator schneller<br />
ablaufen, als dies bei einem realen Prozessor der Fall wäre.<br />
Beachten Sie auch, dass die Simulation des seriellen Terminals sehr einfach gehalten ist. So werden<br />
zum Beispiel alle Zeichen bei der Eingabe geechot, was im realen Betrieb nicht der Fall sein muss.<br />
Zum Starten eines Programms klicken Sie auf "Reset" und dann auf den "Start"-Button, der daraufhin<br />
grün wird. Im gestoppten Zustand kann das Programm im Einzelschritt-Modus durchlaufen werden. In<br />
diesem Fall öffnen Sie durch Klicken auf die entsprechenden Buttons die Fenster mit der<br />
Quellcodeanzeige ("View Code") und der Registeranzeige ("MC68HC11 CPU"). Die gerade<br />
Simulieren eines Zielprogramms (object code) 189
earbeitet <strong>Assembler</strong>zeile wird dann farbig unterlegt und Sie können die aktuellen Registerinhalte<br />
sehen (oder auch ändern). Mit "Browse Memory" werden Sie in die Lage versetzt, Speicherinhalte<br />
anzusehen und zu ändern.<br />
Die zusätzlich zur Binäranzeige vorhandene Siebensegmentanzeige für die Ports B und C bietet eine<br />
undecodierte Anzeige für Port B (alle Segmente einzeln ansteuerbar) und eine decodierte zweistellige<br />
Anzeige für Port C.<br />
Tools → Load in Target<br />
Das Zielprogramm, das zu dem im aktiven Fenster angezeigten Quellprogramm gehört, wird in den<br />
Speicher des Zielrechners übertragen (aber nicht gestartet). Dazu muß der Schalter am Zielsystem auf<br />
"PC" stehen. Zum Programmstart drücken Sie die RESET-Taste am Zielrechner.<br />
Arbeiten mit der seriellen Schnittstelle<br />
Bei Programmen, die die serielle Schnittstelle verwenden, im mit dem Terminalprogramm auf dem PC<br />
(z.B. Hyperterminal oder PuTTY) zu kommunizieren ist der Schalter am Zielsystem auf "Man."<br />
umzustellen, bevor die RESET-Taste gedrückt wird. Das Terminalprogramm muss online sein<br />
(Telefonhöhrer abgehoben).<br />
Beim Laden des Programms ins Zielsystem muss der Schalter wieder auf "PC" gestellt werden.<br />
Achten Sie auch darauf, das ein gegebenenfalls geöffnetes Terminalprogramm auf "aufgelegt =<br />
offline" geschaltet wird, da sonst ein Konflickt beider Programme um die serielle Schnittstelle<br />
entsteht. Das Terminalprogramm muss jedoch nicht geschlossen werden.<br />
In Kurzform:<br />
RUN: Terminal online, Schalter auf "Man."<br />
LOAD: Terminal offline, Schalter auf "PC<br />
Hinweise zur Programmerstellung<br />
Mikrocomputertechnik<br />
Jedes Programm muß folgende Anweisungen enthalten:<br />
stak equ $7FFF ; Stackbereich ab $7FFF (RAM, abwaerts)<br />
prog equ $8000 ; Programmbereich ab $8000 (EEPROM)<br />
data equ $2000 ; Datenbereich ab $2000 (RAM)<br />
rvec equ $FFFE ; Reset-Vektor<br />
. ; ggf. weitere Vektoren<br />
org data ; Beginn Datenbereich<br />
. ; Variablen-Definitionen<br />
.<br />
org prog ; Beginn Programmbereich<br />
main lds #stak ; Stackpointer setzen<br />
.<br />
. ; alle Initialisierungen<br />
.<br />
loop . ; Befehle des Programms<br />
.<br />
.<br />
jmp loop<br />
. ; ggf. fixe Tabellen dahinter<br />
.<br />
. ; ggf. Setzen der Interrupt-Vektoren<br />
Tools → Load in Target 190
. ; (Reihenfolge der Adressen beachten!)<br />
org rvec ; Setzen des Reset-Vektors<br />
fdb main<br />
end<br />
Der RAM-Speicher ab Adresse 0 bis Adresse 255 kann nicht genutzt werden (Bootloader bzw.<br />
Trace).<br />
Tools → Terminal<br />
Mikrocomputertechnik<br />
Der Datenverkehr zwischen dem PC und dem Zielrechner über die serielle Schnittstelle wird mittels<br />
des Terminalprogramms Hyperterm am PC dargestellt. Damit kann der Datenverkehr über die<br />
SCI-Schnittstelle interaktiv erfolgen.<br />
Hinweise zur Programmerstellung 191
Mikrocomputertechnik<br />
Belegung des Experimentier-Boards<br />
Auf dem Experimentierboard steckt eine Anzeigeplatine (die getrennt vom Board mit Strom versorgt<br />
werden muß). Die Platine enthält vier decodierte und eine undecodierte Siebensegmentanzeigen. Ihre<br />
Belegung zeigt die folgene Abbildung:<br />
Das Anschlußkabel zwischen M68HC11 und Experimentierboard endet auf einem Buchsenfeld, von<br />
dem aus die Verbindungen zur Anzeigeplatine bzw. zu den Schaltern, Tastern und LEDs gesteckt<br />
werden müssen.<br />
Belegung des Experimentier-Boards 192
Mikrocomputertechnik<br />
Beachten Sie, daß die LED-Treiber an der Vorderkante des Boards sowie das Board mit den<br />
Siebensegmentanzeigen gesondert mit Spannung versorgt werden muß. Ihr Betreuer zeigt Ihnen die<br />
entsprechenden Verbindungen am ersten Praktikumstag.<br />
Beschaltung der Eingänge des 68HC11<br />
Die Schalter des Experimentier-Boards haben keine aktive Spannungsversorgung sondern schalten<br />
lediglich das Massepotential wechselweise auf zwei Anschlußbuchsen. Verbindet man einen Schalter<br />
mit dem Eingang eines Ports des 68HC11, dann wird - je nach Schalterstellung - der Port mit Masse<br />
verbunden oder der Porteingang ist offen. Aus diesem Grund muß die Leitung vom Schalter zum<br />
Eingangsport des 68HC11 mittels Pull-Up-Widerstand ein 1-Potential erhalten.<br />
Sie finden auf dem Experimentier-Board auf einer der IC-Buchsen ein Widerstandsarray (WID-SIP)<br />
eingesteckt, das acht Widerstände enthält, die auf einer Seite miteinander verbunden sind. Dieser<br />
gemeinsame Anschluß ist auf dem Gehäuse des WID-SIP durch einen Punkt gekennzeichnet. Er wird<br />
mit +5V verbunden. Die anderen Pins des WID-SIP werden einerseits mit einem Schalter verbunden<br />
und andererseits mit einem Eingansport des 68HC11.<br />
Beschaltung der Eingänge des 68HC11 193
Mikrocomputertechnik<br />
Die beiden Taster sind bereits mit einer Entprell-Logik verbunden und liefern korrekte Digitalsignale<br />
für 0 und 1. Sie können daher direkt mit einem Eingangspin des 68HC11 verbunden werden.<br />
Beschaltung der Eingänge des 68HC11 194
Anhang: Binär zu ASCII-Decodierung (hx4a)<br />
Diese Unterprogramme werden beim vierten Praktikumstermin benötigt. Im Speicher liegen die Werte<br />
bekanntermaßen binär vor. Um einen Speicherinhalt oder ene Adresse auf der seriellen Schnittstelle<br />
(Terminal) oder einem LC-Display ausgeben zu können, müsen die Werte als ASCII-Zeichen<br />
dargestellt werden.<br />
Die folgenden vier miteinander verbundenen Unterprogramme wandeln einen 16-Bit-Wert, einen<br />
8-Bit-Wert oder einen 4-Bit-Wert in eine Hexadezimalzahl in ASCII-Darstellung um (4, 2, oder 1<br />
Stelle):<br />
• hx4a wandelt den Inhalt von Akku D in vier ASCII-Zeichen, die in einem 4 Byte langen<br />
Puffer abgelegt werden. Beim Unterprogrammaufruf muß das Indexregister Y auf die letzte<br />
Stelle des Puffers zeigen.<br />
• hx2a wandelt den Inhalt von Akku B in zwei ASCII-Zeichen, die in einem 2 Byte langen<br />
Puffer abgelegt werden. Beim Unterprogrammaufruf muß das Indexregister Y auf die letzte<br />
Stelle des Puffers zeigen.<br />
• hx1a wandelt den Inhalt von Akku B (Bits 0-3) in ein ASCII-Zeichen, das in einem 1 Byte<br />
langen Puffer abgelegt wird. Beim Unterprogrammaufruf muß das Indexregister Y auf den<br />
Puffers zeigen.<br />
hx4a psha ; Akku A auf dem Stack ablegen<br />
bsr hx2a ; Akku B umwandeln (Stelle 3 und 4)<br />
pulb ; Akku A vom Stack holen, in Akku B ablegen<br />
; Nun einfach in hx2a fallen und Akku B<br />
; umwandeln (Stelle 1 und 2)<br />
hx2a pshb ; Akku B auf dem Stack sichern<br />
bsr hx1a ; Bits 0-3 von Akku B umwandeln<br />
pulb ; Original-Akku B wieder holen<br />
lsrb ; viermal schieben (Bits 4-7 --> 0-3)<br />
lsrb<br />
lsrb ; und nun die obere Haelfte umwandeln<br />
lsrb ; indem einfach in hx1a gefallen wird<br />
; Nun wird die eigentliche Arbeit gemacht:<br />
hx1a andb #$0F ; die oberen 4 Bits ausmaskieren<br />
addb #48 ; ASCII-Wert von "0" addieren<br />
cmpb #57 ; groesser als "9"?<br />
bls hx1b ; nein, dann speichern<br />
addb #7 ; sonst die Distanz zwischen "9" und "a" addieren<br />
hx1b stab 0,y ; im Speicher ablegen, auf den Y zeigt<br />
dey ; Y zeigt jetzt auf die Stelle davor<br />
rts ; und weg<br />
Beispielaufruf:<br />
Versuche<br />
ldd #$AFFE ; Hexzahl in Akku D laden<br />
ldy #PUFFER+3 ; Position auf letzte Stelle im Puffer<br />
; der Puffer muss im Datenbereich reserviert sein<br />
bsr hx4a ; do it!<br />
ldy #PUFFER ; y --> Pufferanfang<br />
bsr STOU ; z.B. seriell ausgeben<br />
Copyright © FH München, FB 04, Prof. Jürgen Plate<br />
Letzte Aktualisierung: 20. Feb 2011, 16:49:01<br />
Mikrocomputertechnik<br />
Anhang: Binär zu ASCII-Decodierung (hx4a) 195
Mikrocomputertechnik<br />
Mikrocomputertechnik<br />
Prof. Jürgen Plate<br />
Mikrocomputertechnik 196
Praktikum Mikrocomputer<br />
Versuch 1: Parallel-Ports, Unterprogramme,<br />
Zeitverzögerungen<br />
Bei diesem Versuch soll unter Verwendung der Ports B und C des M68HC11 Datenverkehr mit<br />
externen Komponenten durchgeführt werden. Es soll grundsätzlich im polling mode gearbeitet<br />
werden, d.h. ohne Unterbrechungen. Geeignete Programmteile sind als Unterprogramm zu<br />
formulieren. Zeichnen Sie immer zuerst ein Flussdiagramm und programmieren Sie dann danach.<br />
Die Stellung der Schalter S7 - S4 soll andauernd über Port C [3:0] eingelesen und über Port C [7:4]<br />
auf die LEDs L3 - L0 ausgegeben werden. Die Initialisierung des Ports C soll als Unterprogramm<br />
(Name: PINI) formuliert werden.<br />
Zusätzlich soll ein 8-bit-Lauflicht mit einem Takt von 10 Hz programmiert werden. Seine aktuelle<br />
Stellung soll über Port B [7:0] ausgegeben und mittels der LEDs L15 - L8 angezeigt werden. Der<br />
zeitbestimmende Programmteil sowie das Weiterschalten und Anzeigen des Lauflichts sollen als<br />
Unterprogramme (Namen: DELAY und DISPLAY) formuliert werden.<br />
Nun soll sich der Takt verändern lassen. Der über die Schalter S7 - S4 des Experimentier-Boards<br />
eingestellte und über Port C [3:0] eingelesene Wert stellt die Lauflichtfrequenz in Hz dar, wenn er<br />
grösser als 0 ist. Der Wert 0 führt zu einem Anhalten der Anzeige (Lauflicht bleibt stehen und läuft<br />
erst weiter, wenn der Wert grösser als 0 ist). Siehe Anmerkung unten.<br />
Als Letztes soll noch mittels der Taste T0, die am Eingang STRA des M68HC11 anzuschließen ist,<br />
die Laufrichtung von Linkslauf auf Rechtslauf umgeschaltet werden können und umgekehrt (toggle).<br />
Anmerkung: Es gilt bekanntlich, dass die Frequenz ein Kehrwert der Zeit (Periodendauer) ist (f =<br />
1/t). Für eine Warteschleife, wie sie in der Vorlesung behandelt wurde, muss die Frequenz in eine<br />
Periodendauer umgerechnet werden (1 Hz = 1000 ms, 2 Hz = 500 ms, 3 Hz = 333 ms, 4 Hz = 250 ms<br />
usw.). Das Umrechnen der Frequenz in die Wartezeit kann programmtechnisch auf zweierlei Weise<br />
geschehen, durch (Integer-)Division oder durch eine Tabelle. Verwenden Sie in diesem Fall die<br />
Division (IDIV-Befehl). Schematisch stellt sich die Programmierung wie folgt dar:<br />
1. Entwurf einer Warteschleife für 1 Hz = 1000 ms mit einem möglichst großen Startwert I des<br />
Schleifenzählers.<br />
2. Einlesen der Schalterstellung und Expandieren des Wertes auf eine 16-Bit-Variable K.<br />
3. Division von J = I/K. J ist nun der aktuelle Startwert für die Zählschleife.<br />
Praktikum Mikrocomputer 197
Versuch 2: Parallel-Ports, 7-Segmentanzeige,<br />
Tabellenzugriff<br />
Bei diesem Versuch soll unter Verwendung der Ports B und C des M68HC11 Datenverkehr mit<br />
externen Komponenten durchgeführt werden. Es soll grundsätzlich im polling mode gearbeitet<br />
werden, d.h. ohne Unterbrechungen. Geeignete Programmteile sind als Unterprogramm zu<br />
formulieren. Zeichnen Sie immer zuerst ein Flußdiagramm und programmieren Sie dann danach.<br />
Die Stellung der Schalter S7 - S4 soll andauernd über Port C [3:0] eingelesen, über Port C [7:4]<br />
ausgegeben und als einstellige Sedezimalzahl angezeigt werden. Dazu ist die 7-Segment-Anzeige A3<br />
(mit Decoder) zu verwenden. Die Initialisierung des Ports C soll als Unterprogramm (Name: PINI)<br />
formuliert werden.<br />
Nun werden die 7-Segment-Anzeigen A1 und A2 (mit Decoder) an Port B (A1: [7:4], A2: [3:0])<br />
angeschlossen. Es soll eine 'Digitaluhr' programmiert werden, die Sekunden und Zehntelsekunden<br />
anzeigt (Sekunden Zehner auf A1, Sekunden Einer auf A2 und Zehntelsekunden auf A3). Dazu wird,<br />
wie schon im ersten Versuch, einem Warteroutine DELAY benötigt, die hier eine Periodendauer von<br />
100 ms hat.<br />
Die Digitaluhr soll bei einen vorgegebenen Wert (Programmvariable) starten, bis zum Wert 00.0<br />
herunterzählen und dann anhalten. Mittels der Taste T0, die am Eingang STRA des M68HC11<br />
anzuschließen ist, kann der Zähler mit dem voreingestellten Anfangswert gestartet oder gestoppt<br />
werden.<br />
Über die Schalter S7 - S4 an Port C [3:0] soll die Startzeit des Zählers aus einer Tabelle gewählt<br />
werden, wobei in der Tabelle nur die Sekunden gespeichert werden, die Zehntensekunden starten<br />
immer mit 0. Die Tabelle besitzt somit 16 Einträge. Die in der Tabelle einzutragenden Zeiten sind frei<br />
wählbar.<br />
Hinweis:Optional kann anstelle einer Warteschleife mittels X- oder Y-Register auch der frei laufende<br />
Zähler für die Zeitverzögerung verwendet werden (ohne Interrupt). Dazu sind folgende<br />
Vereinbarungen notwendig:<br />
1. Bei den Konstantendefinitionen<br />
Mikrocomputertechnik<br />
tflag equ $1025 ; Timer Flag Register<br />
tmask equ $1024 ; Timer Mask Register<br />
faktor equ 30 ; Multiplikationsfaktor fuer Timer<br />
; 3 ~ 0,1 s:<br />
; 32,77 * 3 = 98,31 (fast 0,1 s)<br />
; 30 ~ 1 s:<br />
; 32,77 * 30 = 983,1 ms (fast 1 s)<br />
2. Bei den Veriablendefinitionen<br />
org data<br />
...<br />
dlycnt ds.b 1<br />
3. Bei den Unterprogrammen (tinit wird beim Programm-Init aufgerufen)<br />
tinit psha ; Timer Init<br />
clr tmask ; Timer-Prescaler / 1 --> 32,77 ms<br />
ldaa #faktor ; Zeit festlegen<br />
staa dlycnt<br />
pula<br />
rts<br />
Versuch 2: Parallel-Ports, 7-Segmentanzeige, Tabellenzugriff 198
Mikrocomputertechnik<br />
delay psha ; Delay-Routine<br />
delay1 ldaa tflag ; warten auf Timer-Ueberlauf<br />
bpl delay1<br />
ldaa #$80 ; TOFL-Flag zuruecksetzen<br />
staa tflag<br />
dec dlycnt ; delay-counter dekrementieren<br />
tst dlycnt<br />
bne delay1 ; warten auf dlycnt == 0<br />
ldaa #faktor ; dann dlycnt neu setzen<br />
staa dlycnt<br />
pula ; und fertig<br />
rts<br />
Versuch 2: Parallel-Ports, 7-Segmentanzeige, Tabellenzugriff 199
Mikrocomputertechnik<br />
Versuch 3: Serielle Schnittstelle, ASCII-Zeichenketten<br />
Bei diesem Versuch soll unter Verwendung des SCI (Asynchronous Serial Communications Interface)<br />
des M68HC11 Datenverkehr zwischen Prozessor M68HC11 und PC als Terminal durchgeführt<br />
werden. Es soll grundsätzlich im polling mode gearbeitet werden, d.h. ohne Unterbrechungen. Als<br />
String-Terminator dient wie bei C das Nullbyte ($00). Geeignete Programmteile sind als<br />
Unterprogramm zu formulieren. Zeichnen Sie immer zuerst ein Flussdiagramm und programmieren<br />
Sie dann danach.<br />
Wichtig: Zum Terminalbetrieb ist nach dem Terminalbetrieb der Schalter "PC-MAN" am<br />
Praktikumsrechner in Stellung MAN zu bringen. Zum Laden des Programms muss er dann wieder auf<br />
PC gestellt werden. Entsprechend muss beim Hyperterminal zum Programm-Download "aufgelegt"<br />
(Telefon-Icon in der oberen Werkzeugleiste) und zum Betrieb wieder "abgehoben" werden.<br />
Zum Einstieg soll das ASCII-Zeichen 'R' mit einer Wiederholfrequenz von etwa 5 Hz andauernd auf<br />
das Terminalfenster des Hyperterminal-Programms ausgegeben werden. Die Initialisierung des SCI ist<br />
als Unterprogramm (Name: SINIT) zu formulieren. Das Senden des Zeiches soll durch ein<br />
Unterprogramm namens CHOU erfolgen, das das im Akku A übergebene Zeichen (bei freier<br />
Schnittstelle) sendet.<br />
Ein vorbereiteter Text (nullterminierter ASCII-String) ist nun mittels des neu zu schreibenden<br />
Unterprogramms STOU dauernd auf das Terminalfenster auszugeben. Register X enthält die Adresse<br />
des ersten Zeichens des Textes. Das Unterprogramm STOU gibt die ab (X) stehenden ASCII-Zeichen<br />
unter Verwendung des Unterprogramms CHOU aus, bis das Textendezeichen (\0) gefunden wird, das<br />
selbst nicht mit ausgegeben wird. Stattdessen werden die Steuerzeichen CR (Carriage Return) und LF<br />
(Line Feed) ausgegeben.<br />
Ein über die Tastatur eingegebenes Zeichen ist mittels des Unterprogramms CHIN einzulesen und<br />
mittels des Unterprogramms CHOU als Echo auszugeben (Endlos-Schleife). Das Unterprogramm<br />
CHIN übergibt das gelesene Zeichen im Akku A.<br />
Nun soll statt eines einzelnen Zeichens ein String über die Tastatur eingegeben, mittels des<br />
Unterprogramms STIN eingelesen und im Speicher abgelegt werden. STIN verwendet seinerseits<br />
CHIN, um ein Zeichen zu lesen. Zur Kontrolle wird der String mithilfe des Unterprogramms STOU<br />
wieder ausgegeben (Endlos-Schleife). Das Unterprogramm STIN soll folgende Eigenschaften<br />
besitzen:<br />
i. STIN echot die mittels CHIN eingelesenen Zeichen und legt sie im Speicher ab. Die Adresse<br />
des Eingabepuffers wird im Indexregister X übergeben.<br />
ii. Nicht darstellbare Zeichen (alle ASCII-Zeichen < " ") werden bei der Eingabe ignoriert.<br />
iii. Das ASCII-Zeichen CR beendet die Eingabe, es wird ohne Echo als Nullbyte abgelegt.<br />
iv. STIN wird durch die Ausgabe von CR und LF abgeschlossen.<br />
Mittels STIN soll schließlich eine Zeichenkette eingelesen und mit einem im Programm abgelegten,<br />
konstanten String zeichenweise verglichen werden (z. B. als Passwortabfrage). Das Ergebnis des<br />
Vergleichs soll über Port B [6:0] ausgegeben und mittels der 7-Segment-Anzeige A5 (ohne Decoder)<br />
dargestellt werden:<br />
i. Sind die Zeichenketten unterschiedlich, wird ein "F" ausgegeben (für "falsch"). Gleichzeitig<br />
wird ein Fehlerzähler inkrementiert.<br />
ii. Stimmen beide Zeichenketten überein, wird eine "1" ausgegeben. Der Fehlerzähler wird in<br />
diesem Fall zurückgesetzt.<br />
iii. Erfolgt dreimal hintereinander eine falsche Eingabe (Fehlerzähler == 3), wird ein "E"<br />
ausgegeben (für "Error"), das im Rhythmus von 2 Hz blinkt, und keine Eingabe mehr<br />
Versuch 3: Serielle Schnittstelle, ASCII-Zeichenketten 200
angenommen.<br />
Mikrocomputertechnik<br />
Versuch 3: Serielle Schnittstelle, ASCII-Zeichenketten 201
Mikrocomputertechnik<br />
Versuch 4: Zähler, bedingte Unterbrechungen<br />
Bei diesem Versuch sollen ein einfacher Zähler betrieben und verschiedene bedingte Unterbrechungen<br />
aktiviert und bearbeitet werden. Geeignete Programmteile sind als Unterprogramm zu formulieren.<br />
Zeichnen Sie immer zuerst ein Flussdiagramm und programmieren Sie dann danach.<br />
Ein 2-stelliger Sedezimalzähler ist mit einer Frequenz von etwa 10 Hz zu betreiben. Seine aktuelle<br />
Stellung soll über Port C [7:0] ausgegeben und mittels der 7-Segment-Anzeigen A1 und A2 (mit<br />
Decoder) dargestellt werden. Der zeitbestimmende Programmteil soll als Unterprogramm (D100)<br />
unter Verwendung des Registers Y formuliert werden. Orientieren Sie sich an den Programmen aus<br />
den Versuchen 1 und 2.<br />
Modifizieren Sie das Programm nun so, dass beim Starten des Programms der Text "M68HC11<br />
gestartet" auf das Terminalfenster ausgegeben wird. Verwenden Sie dazu die beim Versuch 3<br />
entwickelten Unterprogramme zur Initialisierung der SCI, sowie zur Zeichen- und Stringausgabe<br />
(CHOU und STOU).<br />
Zusätzlich sind nun bedingte Unterbrechungen zu bearbeiten. Mittels der Tasten T0 und T1, die an<br />
den Eingängen STRA und PA7 des M68HC11 anzuschließen sind, können bedingte Unterbrechungen<br />
ausgelöst werden. Als Folge darauf sollen vom Hauptprogramm aus die unten beschriebenen<br />
Aktionen erfolgen.<br />
Die Unterprogramme zur Unterbrechungsbearbeitung sind möglichst kurz zu halten. Zur<br />
Signalisierung von der Unterbrechungsbearbeitung zum Hauptprogramm sollen die Bits 0 und 1 einer<br />
Variablen DFLG (display flag) verwendet werden. Die zum Starten der Unterbrechungsbearbeitungen<br />
nötigen Vektoren nicht vergessen:<br />
org $ffda<br />
dc.w pirq ; pulse accu input (PA7)<br />
org $fff2<br />
dc.w sirq ; IRQ/STRA<br />
org $fffe<br />
dc.w main ; reset<br />
• Beim Auftreten einer Unterbrechung durch T1 an PA7 soll der jeweilige Befehlszählerstand<br />
des unterbrochenen Programms als 4-stellige Hexzahl auf das Terminalfenster ausgegeben<br />
werden ("PC=XXXX"). Verwenden Sie dazu unter anderem das Unterprogramm hx4a (siehe<br />
unten).<br />
Von der Interrupt-Serviceroutine wird nur der Wert des Befehlszählers in der<br />
16-Bit-Variablen PCSTAT ans Hauptprogramm übergeben. Die Tatsache, dass ein Interrupt<br />
auftrat, wird in einer Flag-Variablen namens PFLAG signalisiert. Die Umwandlung Binär →<br />
Hex sowie die Ausgabe erfolgen im Haptprogramm, das auch PFLAG wieder zurücksetzt.<br />
• Beim Auftreten einer Unterbrechung durch T0 an STRA soll jeweils nach dem 3. Impuls am<br />
Interrupteingang (also nach dreimaligem Tastendruck) der Zähler gestoppt und erst nach<br />
weiteren 3 Tastenbetätigungen wieder weiterlaufen. Dies soll sich periodisch wiederholen.<br />
Bearbeiten Sie das Zählen der Tastenbetätigungen innerhalb der Interrupt-Serviceroutine und<br />
signalisieren Sie die Start/Stopp-Information über eine Flag-Variable namens SFLAG. Im<br />
Hauptprogramm wird anhand dieser Variablen entschieden, ob der Zähler läuft oder steht.<br />
Die beiden Unterprogramme hx2a und hx4a können Sie von dieser Angabe per Cut-and-Paste<br />
übernehmen. Dabei ist zu beachten, dass hx2a und hx4a den entstehenden String nach fallenden<br />
Adressen hin aufbauen und dass damit die Übergabeparameter entsprechend gewählt werden müssen.<br />
Sehen Sie sich dazu auch den Quelltext zu den Unterprogrammen am Ende dieses Dokuments an.<br />
Versuch 4: Zähler, bedingte Unterbrechungen 202
Anhang: Binär zu ASCII-Decodierung (hx4a)<br />
Diese Unterprogramme werden beim vierten Praktikumstermin benötigt. Im Speicher liegen die Werte<br />
bekanntermaßen binär vor. Um einen Speicherinhalt oder eine Adresse auf der seriellen Schnittstelle<br />
(Terminal) oder einem LC-Display ausgeben zu können, müsen die Werte als ASCII-Zeichen<br />
dargestellt werden.<br />
Die folgenden vier miteinander verbundenen Unterprogramme wandeln einen 16-Bit-Wert, einen<br />
8-Bit-Wert oder einen 4-Bit-Wert in eine Hexadezimalzahl in ASCII-Darstellung um (4, 2, oder 1<br />
Stelle):<br />
• hx4a wandelt den Inhalt von Akku D in vier ASCII-Zeichen, die in einem 4 Byte langen<br />
Puffer abgelegt werden. Beim Unterprogrammaufruf muss das Indexregister Y auf die letzte<br />
Stelle des Puffers zeigen.<br />
• hx2a wandelt den Inhalt von Akku B in zwei ASCII-Zeichen, die in einem 2 Byte langen<br />
Puffer abgelegt werden. Beim Unterprogrammaufruf muss das Indexregister Y auf die letzte<br />
Stelle des Puffers zeigen.<br />
• hx1a wandelt den Inhalt von Akku B (Bits 0-3) in ein ASCII-Zeichen, das in einem 1 Byte<br />
langen Puffer abgelegt wird. Beim Unterprogrammaufruf muss das Indexregister Y auf den<br />
Puffers zeigen.<br />
hx4a psha ; Akku A auf dem Stack ablegen<br />
bsr hx2a ; Akku B umwandeln (Stelle 3 und 4)<br />
pulb ; Akku A vom Stack holen, in Akku B ablegen<br />
; Nun einfach in hx2a fallen und Akku B<br />
; umwandeln (Stelle 1 und 2)<br />
hx2a pshb ; Akku B auf dem Stack sichern<br />
bsr hx1a ; Bits 0-3 von Akku B umwandeln<br />
pulb ; Original-Akku B wieder holen<br />
lsrb ; viermal schieben (Bits 4-7 --> 0-3)<br />
lsrb<br />
lsrb ; und nun die obere Haelfte umwandeln<br />
lsrb ; indem einfach in hx1a gefallen wird<br />
; Nun wird die eigentliche Arbeit gemacht:<br />
hx1a andb #$0F ; die oberen 4 Bits ausmaskieren<br />
addb #48 ; ASCII-Wert von "0" addieren<br />
cmpb #57 ; groesser als "9"?<br />
bls hx1b ; nein, dann speichern<br />
addb #7 ; sonst die Distanz zwischen "9" und "a" addieren<br />
hx1b stab 0,y ; im Speicher ablegen, auf den Y zeigt<br />
dey ; Y zeigt jetzt auf die Stelle davor<br />
rts ; und weg<br />
Beispielaufruf:<br />
ldd #$AFFE ; Hexzahl in Akku D laden<br />
ldy #PUFFER+3 ; Position auf letzte Stelle im Puffer<br />
; der Puffer muss im Datenbereich reserviert sein<br />
bsr hx4a ; do it!<br />
ldy #PUFFER ; y --> Pufferanfang<br />
bsr STOU ; z.B. seriell ausgeben<br />
[ Praktikumsanleitung ] [ Skript ]<br />
Copyright © FH München, FB 04, Prof. Jürgen Plate<br />
Letzte Aktualisierung: 20. Feb 2011, 16:49:01<br />
Mikrocomputertechnik<br />
Anhang: Binär zu ASCII-Decodierung (hx4a) 203