Mikrocontroller HC12
Ein Mikrocontroller ist ein vollständiges Computersystem auf einem Chip. Der Vorgänger des 68HC12 Mikrocontrollers war der 68HC11, der über eine 8 Bit Architektur verfügte. Die Struktur der CPU-Register, die Assemblerbefehle und die Adressierungsarten sind um neue Features erweitert worden.
Zunächst werde ich auf Register eingehen. Register sind interne Speicherstellen, die direkt bei der CPU liegen und Ergebnisse und Berechnungen aufnehmen können. Fast alle CPU Operationen funktionieren nur mit Registern. Man hat mit Assembler direkten Zugriff darauf.
Registersatz
Der Registersatz des 68HC12 Mikrocontrollers sieht folgendermaßen aus:
Bit | 15 | 0 | |
Akkumulator A und B | A | B | |
Akkumulator D | D | ||
Index Register X | X | ||
Index Register Y | Y | ||
Stackpointer | SP | ||
Program Counter | PC |
1 | 0 | |||||||||
Stop Display | S | |||||||||
XIRQ-Maskierung | X | |||||||||
Half Carry | H | |||||||||
Interrupt-Maskierung | I | |||||||||
Negativ | N | |||||||||
Zero | Z | |||||||||
Overflow | V | |||||||||
Carry | C |
Der Stackpointer zeigt auf die Adresse des letzten gültigen Eintrags im Stack. Der Program Counter hingegen, zeigt auf die Adresse des nächsten Befehls.
Maschinenbefehle
Wie bereits erwähnt habst du mit Assembler direkten Zugriff auf die Register. Die Maschinenbefehle kannst du aus dem Bedienungshandbuch CPU12 Refernece Manual, Rev. 4.0 entnehmen. Hier ein kleiner Ausschnitt grundlegender Maschinenbefehle, die für unsere Beispielprogramme ausreichen sollten.
Mnemonic | Operation/Function | Addr. Mode | Machine Coding(hex) | Takte |
ADCA opr | (A) + (M) + (C) → A Add with Carry to A | IMM EXT | 89 ii B9 hh ll | 1 3 |
ADCB opr | (B) + (M) + (C) → B Add with Carry to B | IMM EXT | C9 ii F9 hh ll | 1 3 |
ADDA opr | (A) + (M) → A Add without Carry to A | IMM EXT | 8B ii BB hh ll | 1 3 |
JMP opr | Subroutine address → PC Jump | EXT | 06 hh ll | 1 |
LDAA opr | (M) → A Load Accumulator A | IMM EXT | 86 ii B6 hh ll | 1 3 |
LDAB opr | (M) → B Load Accumulator B | IMM EXT | C6 ii F6 hh ll | 1 3 |
STAA opr | (A) → M Store Accumulator A to Memory | DIR EXT | 5A dd 7A hh ll | 2 3 |
LDS opr | (M : M+1) → SP Loads the most significant byte of the SP | IMM EXT | CF jj kk F6 hh ll | |
LEAS opr | Effective address → SP Load Stack Pointer with Affective Address | IDX | 1B xb | |
LDD opr | (M : M+1) → A : B Load Double Accumulator | IMM EXT | CC jj kk FC hh ll | |
PSHD opr | M(SP):M(SP+1) → A : B SP - 2 → SP Push Double Accumulator onto Stack | INH | 3B | |
JSR opr | SP - 2 → SP Jump to Subroutine | DIR EXT | 17 dd 16 hh ll | |
RTS | SP + 2 → SP M(SP):M(SP+1) → PC Return from Subroutine | INH | 3D |
Adressierungsarten
Bei Anwendung der Maschinenbefehle sind verschiedene Adressierungsarten vonnöten.
Unmittelbare Adressierung (immediate) IMM
LDAA #255 A ← 255 ADDA #7 A ← A + 7
Die unmittelbare Adressierung wird häufig zur Initialisierung der Register benutzt.
Direkte Adressierung (direct, extended) DIR, EXT
LDAA 0008 A ← M(0008) STAA $0802 M($802) ← A
Wird für statische Adressierung von Daten und statischen Sprüngen verwendet.
Object Code Notation
- dd → 8-bit direct address $0000 to $00FF
- ii → 8-bit immediate data value
- hh → High-order byte of a 16-bit address
- ll → Low-order byte of a 16-bit address
Beispiel eines HC12 Assemblerprogramms
org &fffe ; Exception (RESET)
dc.w main ; auf Startadresse main
org $800 ; Speicher im RAM
var1 ds 1 ; Variable1 im RAM
erg ds 1 ; Variable2 im RAM
org $f000 ; Programm ins EEPROM
main ldaa const ; Lade Accumulator A mit const
staa var1 ; Schreibt Accumulator A in var1 (initialisierung von var1)
ldaa #200 ; Lade Accumulator A mit Wert 200
adda var1 ; addiere var1 zum Accumulator
staa erg ; Schreibt Accumulator A in erg
stop
const dc.b 45 ; Konstante EEPROM
Speicher des HC12 Assemblerprogramms
Beginnen wir mit dem eigentlichen Programm, dem main Teil. Der Befehl ldaa const, lädt den Akkumulator A mit der Konstanten const, und zwar mit direkter Adressierung (DIR, EXT). Die Maschinenbefehle können Sie sich aus der obigen Tabelle entnehmen. In diesem Fall wäre das B6 hh ll. Die Konstante const steht an Speicheradresse $F010. Folglich ist der Maschinencode des Befehls ldaa const = B6 F0 10
In der nächsten Zeile wird Akkumulator A in die Variable var1 geschrieben. Somit wird var1 mit dem aktuellen Wert des Akkumulators A initialisiert. Die Adressierung geschieht hier ebenso direkte. Also folgt der Maschinencode 7A 08 00, da var1 an Speicheradresse $0800 im RAM steht.
Kommen wir zum Befehl ldaa #200. Wieder soll der Akkumulator A geladen werden. Diesmal allerdings durch unmittelbare Adressierung, da ein direkter Wert (200) übergeben werden muss. Aus der obigen Tabelle ist der Maschinencode 86 ii zu entnehmen. ii soll den Wert 200 annehmen, allerdings als Hexadezimalzahl.
200 : 16 = 12 Rest 8
12 : 16 = 0 Rest 12
Gelesen wird von unten nach oben, Zahlen von 10 bis 15 werden als Buchstaben dargestellt (A=10, B=11...). Somit ist die Zahl 200 im Dezimalsystem, eine C8 im Hexadezimalsystem. Maschinencode → 86 C8
Mnemonic | Speicheradresse | Inhalt (Maschinencode) |
org $800 | $0800 | |
var1 | $0800 | |
erg | $0801 | |
ldaa const | $F000 | B6F010 |
staa var1 | $F003 | 7A0800 |
ldaa #200 | $F006 | 86C8 |
adda var1 | $F008 | BB0800 |
staa erg | $F00B | 7A0801 |
stop | $F00E | 183E |
dc.b 45 | $F010 | 2D |
Unterprogramme
Unterprogramme können an beliebiger Stelle eines übergeordneten Programms wiederholt aufgerufen werden. Um zum Unterprogramm zu gelangen gibt es den Befehl
JSR - Jump to Subroutine
Dieser Befehl dekrementiert den Stack-Pointer um 2
SP <- SP - 2
um die Return-Adresse auf den Stack zu legen.
RTS - Return from Subroutine
Der RTS-Befehl rekonstruiert den Program-Counter
PC <- M(SP):M(SP+1)
inkrementiert den Stack-Pointer um 2
SP <- SP + 2
und springt zur Rücksprungadresse.
Assemblerprogrammierungx86-Prozessoren, Register, Interrupts, wichtige Maschinenbefehle | keyboard_arrow_right |
TASM - Turbo AssemblerEinrichtung und Installation des TASM - Turbo Assemblers | keyboard_arrow_right |