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:

Bit150
Akkumulator A und BAB
Akkumulator DD
Index Register XX
Index Register YY
StackpointerSP
Program CounterPC
10
Stop DisplayS
XIRQ-MaskierungX
Half CarryH
Interrupt-MaskierungI
NegativN
ZeroZ
OverflowV
CarryC

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.

MnemonicOperation/FunctionAddr. ModeMachine 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 oprSubroutine address → PC
Jump
EXT06 hh ll1
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 oprEffective address → SP
Load Stack Pointer with Affective Address
IDX1B xb 
LDD opr(M : M+1) → A : B
Load Double Accumulator
IMM
EXT
CC jj kk
FC hh ll
 
PSHD oprM(SP):M(SP+1) → A : B
SP - 2 → SP
Push Double Accumulator onto Stack
INH3B 
JSR oprSP - 2 → SP
Jump to Subroutine
DIR
EXT
17 dd
16 hh ll
 
RTSSP + 2 → SP
M(SP):M(SP+1) → PC
Return from Subroutine
INH3D 

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

MnemonicSpeicheradresseInhalt (Maschinencode)
org $800$0800 
var1$0800 
erg$0801 
ldaa const$F000B6F010
staa var1$F0037A0800
ldaa #200$F00686C8
adda var1$F008BB0800
staa erg$F00B7A0801
stop$F00E183E
dc.b 45$F0102D

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.

 


Werbung