Mikrocontroller-Programmierung
Anhand des HC12
Fabian Wiesel
Überblick
● Überblick Mikrocontroller● Überblick HC12
– CPU– Peripherie des DG128
● Assemblerprogrammierung
Mikrocontroller
● Leistungsfähigkeit:– zwischen PICs– Und Desktop-Prozessoren
● Hochintegriert– Serielle Schnittstellen– A/D Wandler– Netzwerk– PWM
● Spezialisiert● Kostengünstig
– In großen Stückzahlen
Einsatzgebiete
● Automobilindustrie● Unterhaltungsindustrie● Mobilkommunikation● Netzwerk● Robotik
HC12-Familie
● CPU– 16bit– CISC– Multi-Cycle– Akkumulator Register (1 16bit / 2 8bit)– 2 Index-Register– 1 Stack-Pointer Register– Control Register– Ein Adressraum für I/O und RAM– Paging für >64kB
Eckdaten des DG128(A)
● CPU– 8MHz– 128kB Flash– 8kB RAM– 2kB EEPROM
● Peripherie– >32 Digitalports– 2 Serielle Schnittstellen– I²C-Bus– CAN-Bus– 16 A/D-Wandler-Kanäle– 4 PWM-Kanäle
Microcontroller
Assemblerprogrammierung
Motivation
● Timing– Taktgenaue Signale (µs bis ns)
● Speicherknappheit● Systemnahe Programmierung● Spezielle Befehle
– Fuzzy-Logic Instruktionen
Register
● 1 General-Purpose Register– A,B– D
● 2 Index-Register– IX– IY
● 1 Stack-Pointer-Register– SP
● 1 Zustandsregister– CCR
● 1 Programm-Counter– PC
Befehlsüberblick
● CISC: Also viele Befehle● Befehle stehen im Handbuch (CPU12RG/D)● Assembler+IDE (MiniIDE)● Simulator (HC12Sim)
Assembler-Datei
● Assembler-Direktiven org $2000 ; Place the following ; starting at address 0x2000source: db “abcd“ ; Define Bytes as sourcetarget: ds.b 4 ; Define Storage Bytes (4 bytes)
org $4000 ; CodeStart: MOVB #0, $16 ; Disable watchdog LDS #Start ; Load Stack Pointer
Speicherlayout
Adressierungsarten
● Immediate– BEFEHL #1000
● Direkt– BEFEHL 1000
● Indiziert– BEFEHL 1,SP
● Indiziert Indirekt– BEFEHL [0,SP]
● Indiziert Post/Pre-Increment– BEFEHL 1,X+– BEFEHL 1,+X
● Analog: Decrement
Load/Store
● Speicher-Register– LDX: Lade in Register X– Ausnahme 8bit:
● LDAA: Lade in Register A● Register-Speicher
– Analog: STX: Speicher aus Register X● Register-Register
– Exchange● z.B: EXG A,B
● Speicher-Speicher– MOVB: Move Byte– MOVW: Move Word
Load/Store-Beispiel
● Memcopy-light, die Erste; \param X address of the source; \param Y address of the targetmemcpyl1: LDAA 1,X+ STAA 1,Y+ LDAA 1,X+ STAA 1,Y+
● Memcopy-light, die Zweitememcpyl2: MOVB 1,X+, 1,Y+ MOVB 1,X+, 1,Y+
Arithmetik
● Addition/Substraktion– ABA: Addiere A zu B– ADDD: Addiere Datum zu D– Substraktion analog
● Inkrementierung/Dekrementierung– DEC Q: Dekrementiere Datum an Adresse Q– DEX: Dekrementiere Register X– Inkrementierung Analog
● Desweiteren– Multiplikation, Division– Bitoperationen: Shift, Logik
Arithmetik-Beispiel
● Akkumuliere 2 Werte addiere 10; \param X pointer to the first value; \return result in Dsum4: LDD 2,X+ ADDD 2,X+ ADDD #10
● Teile durch 256=2^8; \brief Argument and result in Ddiv256: TBA CLRB
Vergleichsoperationen
● CBA: Vergleiche A mit B● CPD: Vergleiche Datum mit D● TST: Ist Datum kleiner 0 (oder größer oder
gleich 0?)
Branching
● Kurze Sprünge– (-128)..127 Bytes von Aufruf enfternt– Unbedingte Sprünge
● BRA: Branch Always● BSR: Branch Subroutine
– Bedingte Sprünge● BEQ: Branch if Equal● DBNE: Decrease and Branch if Not Equal (Zero)
● Weite Sprünge– (-32kB)..32kB – Analog zu Kurzen:
● LBRA: Langer relativer Sprung
Branching-Beispiele
● Endlos-Schleifeforever: BRA forever
● Memcopy revisited– Neuer Befehl: DBNE ; \param D holds number of bytes; \param X source; \param Y targetmemcpyr:
MOVB 1,X+, 1,Y+ DBNE D, memcpyr
Funktionsaufrüfe
● Spezielles Branching– JSR: Jump Subroutine– RTS: Return to Stack
● „Woher“ muss gespeichert werden● Speicherung der Adressen auf Stack
– Stackpointer zeigt auf unterste belegte Adresse
Assembler-Datei
● Assembler-Direktiven org $2000 ; Place the following ; starting at address 0x2000source: db “abcd“ ; Define Bytes as sourcetarget: ds.b 4 ; Define Storage Bytes (4 bytes)
org $4000 ; CodeStart: MOVB #0, $16 ; Disable watchdog LDS #Start ; Load Stack Pointer
Aufruf-Konventionen
● Parameter Übergabe und Rückgabe– Implizit– Pseudoregister– Per Register– Stack
Aufrufs-Beispiele
● Parameterübergabe per Registermain: LDS #$4000 LDX #source LDY #target LDD #10 JSR memcpyr STOP
; \param D holds number of bytes; \param X source; \param Y targetmemcpyr:
MOVB 1,X+, 1,Y+ DBNE D, memcpy RTS
Aufrufs-Beispiele
● Parameterübergabe über Stackmain: LDS #$4000 LEAS -6,SP ; 6 Bytes on stack MOVW #10, 0,SP MOVW #source, 2,SP MOVW #target, 4,SP JSR memcpys ; Places PC on stack STOP
; void memcpys(void *target, const void *src,; size_t len)memcpys: LDD 2,SP LDX 4,SP LDY 6,SPmemcpysL: MOVB 1,X+, 1,Y+ DBNE D, memcpysL RTS
Aufrufs-Beispiele
● Metrowerks C-Compiler Aufrufskonventionmain: LDS #$4000 LEAS -4,SP ; 4 Bytes on stack LDD #10 MOVW #source, 0,SP MOVW #target, 2,SP JSR memcpy ; Places PC on stack STOP
; void *memcpy(void *target, const void *src,; size_t len)memcpy: LDX 2,SP LDY 4,SPmemcpyL: MOVB 1,X+, 1,Y+ DBNE D, memcpyL LDD 2,SP RTS