MikroprozessorenGrundlagen
Aufbau, BlockschaltbildGrundlegende Datentypen
AVR-ControllerAnatomieBefehlssatzAssemblerSpeicherzugriffAdressierungsartenKontrollstrukturenStack
Input / Output (I/O)Parallel I/OSeriell I/OTimerZusammenfassung I/O
InterruptMathematische Operationen
Speicher
Direktiven: Anweisungen an den Assembler
Assemblerführt Direktiven aus
Flash-ROMProgrammspeicher
MCUführt Maschinenbefehle aus
RAMDatenspeicher
EEPROMKonfigurations-datenspeicher
Source-Code
Maschinencode
Beispiele: arithmetischer/logischer AusdruckZuweisungFunktion (LOW ▼(0x1234), HIGH▼(0x1234)) �String-Kostante ("ABC"), ASCII-Zeichen ('a') �
num. Konstante (0x0a, $0a, 0b00001010) �Liste von Ausdrücken, Namen, Konstanten
Direktiven (Syntax)�
[label: ] Direktive [Parameter]
Name
▼GNU-Asm: lo8(),hi8() �
Direktiven Auswahl AVR-Studio�
gibt einem Ausdruck einen Namen.EQU
bindet Source-Code von einem anderen File ein.INCLUDE
gibt einem Register einen anderen Namen.DEF
definiert absolute Adresse innerhalb eines Segments.ORG
definiert Word-Konstante(n) (2 Byte) �.DW
definiert Byte-Konstante(n) �.DB
reserviert Speicherplatz (im SRAM) für Variablen.BYTE
EEPROM-Segment.ESEG
Daten-Segment.DSEG
Code-Segment.CSEG
Direktiven Auswahl (GNUASM)�
.text Nachfolgend die Programm Sektion (Flash)
.data Nachfolgend die Daten Sektion (SRAM)
.byte Bytes anlegen (je 8 Bit)
.word Worte anlegen (je 16 Bit)
.ascii ASCII Zeichen anlegen (ohne '\0' am Ende)
.asciz ASCII Zeichen anlegen (mit '\0' am Ende)
.byte (AVR-Studio)�• Der Assembler reserviert Speicherplatz im Daten-Segment
(RAM) für Variablen, die durch das Programm verändert w erden können
• Name (label) enthält die erste Adresse dieses Speicherplatzes [label: ] .byte Ausdruck
• Beispiele: .equ tabsize = 1000
.dseg
short_var: .byte 2
char_var: .byte 1
table: .byte tabsize ; Feld (1000 Bytes) �
• im Listing.dseg
000060 short_var: .byte 2
000062 char_var: .byte 1
000063 table: .byte tabsize ; Feld (1000 Bytes) �
Speicher
Segment-Direktiven• Die folgenden Direktiven gelten für den angegebnen
Speicherbereich. • Direktiven funktionieren oft nur für einen bestimmten
Speicherbereich.
Flash-ROMProgrammspeicher
RAMDatenspeicher
EEPROMKonfigurations-datenspeicher
.CSEG/▼.text .ESEG .DSEG/▼.data
.equ (AVR-Studio)equal
• Der Assembler ersetzt vor dem Assemblieren den Namen im Programmcode durch das Ergebnis des Ausdrucks
• .equ name = Ausdruck• Beispiel:
.equ SREG = 0x3f ; gibt der Adresse des Status-; registers den Namen SREG
.equ TEILER = 10
.equFCPU=1000000
.equFREQUENZ=2*FCPU/TEILER ; 16-Bit-Konstante!
main:
ldi r16, TEILER
ldi r17, LOW ▼(FREQUENZ) ; FREQUENZ->r18:r17
ldi r18, HIGH ▼(FREQUENZ)
.equ (GNUASM)�
• Der Assembler ersetzt vor dem Assemblieren den Namen im Programmcode durch das Ergebnis des Ausdrucks
• .equ name,Ausdruck oder name=Ausdruck• GNUASM kann auch #define wie in C
• Beispiel: .equ SREG,0x3f ; gibt der Adresse des Status-
; registers den Namen SREG
.equ TEILER,10
.equFCPU,1000000
.equFREQUENZ,2*FCPU/TEILER ; 16-Bit-Konstante!
main: ldi r16, TEILER
ldi r17, lo8 ▼(FREQUENZ) ;FREQUENZ->r18:r17
ldi r18, hi8 ▼(FREQUENZ)
.include(AVR-Studio)�• Der Assembler bindet Code aus einem anderen
Assembler-File anstelle der include-Direktive in den aktuellen Code ein
.include "filename"
.equ FCPU=1000000
.equ RBAUD=FCPU/1000
.include "const.asm" main:
ldi r16,RBAUD
.equ FCPU=1000000
.equ RBAUD=FCPU/1000main:
ldi r16,LOW(RBAUD) �
ldi r17,HIGH(RBAUD) �
const.asmmain.asm
vor dem Assemblieren von main.asm
.include für ATMega128 (AVR-Studio)�
• Der Assembler braucht Definitionen für den speziellen Prozessor, der im Projektes verwendet wird:
.include "m128def.inc"
....equ PORTB=0x38
...
.include " m128def.inc" main:
lds r16,PORTB
....equ PORTB=0x38
...main:
lds r16,PORTB �
�
const.asmmain.asm
vor dem Assemblieren von main.asm
#include(GNUASM)�• Der Assembler bindet Code aus einem anderen
Assembler-File anstelle der include-Direktive in den aktuellen Code ein
.include "filename"
.equ FCPU,8000000
.equ RBAUD,FCPU/1000
#include "const.asm" main:
ldi r16,RBAUD
.equ FCPU,8000000 ¹
.equ RBAUD,FCPU/1000main:
ldi r16,lo8(RBAUD) �
ldi r17,hi8(RBAUD) �
const.asmmain.asm
vor dem Assemblieren von main.asm
¹ FCPU durch Eclipse IDE schon gesetzt
.def (AVR-Studio)define
• Der Assembler ersetzt angegebenen Namen durch das Register.
.def name = register• Beispiel:
.def TEMP = r16 ; gibt dem Register r16 den ; Namen TEMP
main: ...
mov TEMP,r17 ;Inhalt von r17 nach r16
.db und .dw (AVR-Studio)define byte, define word
• Der Assembler definiert Byte- bzw. Word-Konstanten (2Byte) im Code- oder EEPROM-Segment
• über den Namen des Labels kann man auf die Adresse des Beginns des Speicherbereiches zugreifen[label: ] .db ( Liste von) Ausdrücken, Konstanten, Strings[label: ] .dw ( Liste von) Ausdrücken, Konstanten
• Beispiele: CODE: .db 0x30, 0x31, '2', '3'TEILER: .dw 1000
• im Listing00000d 3130
00000e 3332 CODE: .db 0x30 , 0x31 , '2', '3'
00000f 03e8 K1: .dw 1000
.byte (AVR-Studio)�• Der Assembler reserviert Speicherplatz im Daten-Segment
(RAM) für Variablen, die durch das Programm verändert w erden können
• Name (label) enthält die erste Adresse dieses Speicherplatzes [label: ] .byte Ausdruck
• Beispiele: .equ tabsize = 1000
.dseg
short_var: .byte 2
char_var: .byte 1
table: .byte tabsize ; Feld (1000 Bytes) �
• im Listing.dseg
000060 short_var: .byte 2
000062 char_var: .byte 1
000063 table: .byte tabsize ; Feld (1000 Bytes) �
.comm (GNUASM) �• Der Assembler reserviert Speicherplatz in der Sektion. Dies
können Variablen sein, die durch das Programm verändert werden. Generell aber nur Platzhalter, also uninitialisiert !
• Name (label) enthält die erste Adresse dieses Speicherplatzes (aus dem Lokation-Zähler des Assemblers) �
.comm Name, Ausdruck• Beispiele:
.data ; Soll in die Daten Sektion (SRAM) �
.equ tabsize,1000 ; Assemblersymbol, Wert 1000
.comm short_var,2 ; Variable 2 Byte
.comm char_var,1 ; Variable 1 Byte
.comm table,tabsize ; Feld (1000 Bytes) �
.org (AVR-Studio)organize
• Der Assembler setzt den Adressenzähler in dem vorher durch .xSEG definierten Segment auf eine angegebene Adresse
• [label: ] .org Ausdruck• Beispiel:
.equ MEINE_KONSTANTEN = 0x0000c8
.CSEG ; im Flash-ROM
.org MEINE_KONSTANTEN
K1:.db 0x14, 102/3
K2:.dw 0x0123
• im Listing:.CSEG
0000c8 1422
0000c9 0123
.org (GNUASM)organize
• Der Assembler setzt den Location-Zähler in dem vorher durch .text definierten Segment auf eine angegebene Adresse
• .orgAusdruck• Beispiel:
MEINE_KONSTANTEN = 0x0000c8 .text ; im Flash-ROM
.org MEINE_KONSTANTEN
K1:.byte 0x14, 102/3
K2:.word 0x0123
– Das Symbol K1 bekommt den Wert 0xc8, K2 0xca
Speicherzugriff
Wir unterscheiden (Harvard Architektur):
• Datenadressraum und den
•Programmadressraum
LDS / STSLoad / Store Data
• Dient zum Laden / Speichernim Datenbereich(0..$ffff) �
• Geht nur für Bytes als Quelle
• Geht für R0 .. R31
• Syntax Beispiel :
lds R13,0x0123sts 0x0021,R13
LD: Load Indirect
ld r0,x ; r0=mem[ x ]ld r0,x +¹ ; r0=mem[ x++ ];ld r0, - x¹ ; r0=mem[ --x ];
• Lade Register (0..31) mit Speicherzelle, deren Datenadresse in x oder y oder z ist
• x = r27:r26• y = r29:r28• z = r31:r30
¹Autoinkrement/Autodekrement
LDDLoad Indirect With Displacement
ldd r0,y+1 ; r0=mem[ y+1 ]ldd r0,z+63 ; r0=mem[ z+63 ];
• Lade Register (0..31) mit Speicherzelle, deren Datenadresse y+d oder z+d ist
• d = displacement ∈ { 0 .. 63}
LPM: Load Program Memory (Indirect)�
ld r0,z ; r0=Pmem[ z ]ld r0,z +¹ ; r0=Pmem[ z++ ];ld r0, -z ¹ ; r0=Pmem[ --z ];
• Lade Register (0..31) mit Speicherzelle (Flash)deren Programmadressein x oder y oder z ist
• Geht nur über z = r31:r30 als Indirekt-Quelle• Alle Register r0..r31 möglich
¹Autoinkrement/Autodekrement
ADIW / SBIWAdd/Subtract Immediate from/to Word
• Addiere / Subtrahiere Zahl von / zu Register(Immediate)
• Geht für die Registerpaare:R25:24 R27:26 R29:28 R31:30
• Addierte / Subtrahierte Zahl: 0..63
• Syntax Beispiel:
adiw r25:24,63
IJMPIndirect Jump
• Sprung = Lade Program Countermit neuem Wert aus R31:R30 (Z-Register)�
ldi r31,high ▼(ziel) �
ldi r30,low ▼(ziel) �
ijmpnop
ziel: nop
▼GNU-Asm: lo8(),hi8() �
ICALLIndirect Call
icall = call (Z)�
main:mov R31, high(sub1) �
mov R30, low (sub1) �
icallrjmp main
sub1: ret
Anwendung ijmp: switch()�
switch( a) �
{case 10:
do10();break;case 11:
do11();break;case 12:
do12();break;default:break;}
Anwendung: Switch
#include <stdio.h>void uart_init();
void sub10() {printf("Hello 10\n");}void sub11() {printf("Hello 11\n");}void sub12() {printf("Hello 12\n");}
void to_switch(int index);
int main(int arg, char *arv[]) {uart_init();printf("pgm starts\n");to_switch(11);
}
ICALL Teil 1#include <avr/io.h>.global to_switchto_switch:;Parameter is passed in r25:r24
cpi r24,10 ;kleiner alsbrlo default ;10 ergibt default-Fallcpi r24,13 ;grösser gleichbrsh default ;13 ergibt default Fallsubi r24,10 ;relativiert auf 0lsl r24 ;*2, da Adressen 16 Bit langldi ZL,lo8(Liste) ;high Byte von Listenadresseldi ZH,hi8(Liste) ;low Byte von Listenadresse
ICALL, Teil 2clr r16 ;Null für adc
add ZL,r24 ;Offset für Liste addierenadc ZH,r16 ;mögliches Carry zu
High Bytelpm r0,Z+ ;r0 Low Byte der Fct-
Adresselpm r1,Z ;r1:r0 -> Fct-Adressemovw r30,r0 :Fct-Adr. Nach Z
kopierenicall ;UP aufrufen
default:ret ;zum Aufrufer zurück
Liste: ;Liste der Funktionen-Adressen.word sub10,sub11,sub12
MikroprozessorenGrundlagen
Aufbau, BlockschaltbildGrundlegende Datentypen
AVR-ControllerAnatomieBefehlssatzAssemblerSpeicherzugriffAdressierungsartenKontrollstrukturenStack
Input / Output (I/O)Parallel I/OSeriell I/OTimerZusammenfassung I/O
InterruptMathematische Operationen
Top Related