Aufbau eines Assembler-Programms. Assembler-Anweisungen (Direktiven) Einbindung von include-files Definition von Konstanten, Reservierung von Speicherplatz im RAM, 2. Was tun, wenn C Reset-Signal erhält Einschalten der Spannung, Reset-Knopf drücken,... 3. Was tun, wenn Interrupt eingetroffen IO-Bausteine melden sich, z.b. kommt ein Zeichen an der seriellen Schnittstelle an 4. Anwendungsprogramm-Code Initialisierung Stack, IO-Bausteine Programmierung der Anwendungslogik 5. Was tun, wenn Programm-Code abgearbeitet nichts tun wieder von vorn beginnen Verwendung von Bit-Masken Bits setzen Bits toggeln Bits prüfen
Bits in Registern setzen Bit 3 im Register PORTB setzen - einfach ldi r6, x8 out PORTB, r6 - besser lesbar ldi r6, ( << PORTB3) out PORTB, r6 ; b Konstanten mit gleichen Namen sind im include-file des jeweiligen Prozessors definiert (hier m28def.inc) Datenblatt, Register Summary, S. 363 Bits toggeln Bit 3 in r6 umschalten (alle anderen Bits von r6 ändern sich nicht) -> Exklusiv Oder mit Bitmaske ldi r6, x48 r6 ldi r7, ( << 3); x8 eor r6, r7 eor r6, r7 r7 Bit-Maske eor r6, r7 r6 r7 eor r6, r7 r6 r7 enthält die Bit-Maske, die vorgibt, welche(s) Bit(s) umgeschaltet werden sollen Verwendung von ( << 3) statt x8 für Erhöhung der Lesbarkeit 2
Bits prüfen prüfen, ob Bit 3 in Register r6 gesetzt ist ldi r6, x48 andi r6, (<<3) brne gesetzt nichtgesetzt: ; tu was bei nicht ; gesetztem Bit rjmp weiter gesetzt: ; tu was bei gesetztem ; Bit weiter: Bit 3 ist gesetzt r6 Bit-Maske andi r6, (<<3) r6 r6 ist nicht Bit 3 ist NICHT gesetzt r6 Bit-Maske andi r6, (<<3) r6 r6 ist Programmierung der Parallel-IO- Ports Anzeige auf LEDs Tasteneingabe Beispiel 3
Grundsätzlicher Ablauf Ausgabe Port initialisieren in C #include <avr\io.h> DDRB=xff; in Assembler.include m28def.inc ldi r6, xff out DDRB, r6 IO-Daten-Register initialisieren PORTB=xff; out PORTB, r6 Daten berechnen und ausgeben //LED3 leuchtet char led=<<pinb3; PORTB= ~led; ;LED3 leuchtet ldi r6, (<<PINB3) com r6 out PORTB, r6 IO-Adressen und IO-Befehle RAM-Adresse: x RAM-Offset der x2 IO-Adressen x6 Befehl: sts, lds Register I/O ext. I/O RAM IO-Adresse x IO-Adresse x3f Befehl: out, in RAM-Adresse IO-Adresse Datenblatt: Register Summary RAMEND IO-Adressen sind in m28def.inc mit Namen versehen worden (bessere Lesbarkeit), Ausschnitt:.equ PORTC = $5 ;x5.equ DDRC = $4.equ PINC = $3.equ PORTD = $2.equ DDRD = $.equ PIND = $ RAMAdresse=IOAdresse+x2 4
IO-Befehle in/out und lds/sts bei Verwendung von in/out kann die in m28def.inc definierte IO- Adresse direkt verwendet werden, z.b. ldi r7, (<<PINB3) ;LED3 einschalten com r7 out PORTB, r7 bei Verwendung von sts / lds muss der RAM-Offset zur IO- Adresse hinzuaddiert werden, z.b..equ IO_RAMOFFSET= x2.equ MEM_PORTC=PORTC+IO_RAMOFFSET ldi r7, (<<PINB3) com r7 sts MEM_PORTC, r7 lds/sts können im gesamten Bereich des RAM verwendet werden, in/out funktionieren nur im Bereich der IO-Adressen 5
Bits in Registern setzen Bit 3 im Register PORTB setzen - einfach ldi r6, ~x8 out PORTB, r6 - besser lesbar ldi r6, ~( << PORTB3) out PORTB, r6 ; b Konstanten mit gleichen Namen sind im include-file des jeweiligen Prozessors definiert (hier m28def.inc) Datenblatt, Register Summary, S. 363 Berechnung der Wartezeit Summieren der Anzahl der Takte N clk, die die CPU für die Abarbeitung der Befehle der Warteschleife benötigt Multiplizieren mit der aktuell eingestellten Takt-Periodendauer der CPU für f CPU = MHz CPU-Takt t f CPU allebefehle N clk t s 6 2 65535 4,262s 262ms Einfachste, aber unpraktischste Methode! Neue Berechnung erforderlich, wenn Programm der Warteschleife geändert wird. Programmänderungen erforderlich, wenn anderer CPU-Takt eingestellt wird oder andere Wartezeit erforderlich ist. Relativ großer Aufwand für Zeitbestimmung erforderlich. 6
Warten r26 N= führt N*M Warteschleifen aus r25:24 M= outer_loop äußere Warteschleife inner_loop innere Warteschleife M-- [M==] [sonst] N-- [sonst] [N==] Warten (innere Schleife) in C #define M x3e8 in Assembler.equ M=x3e8 ;d // Zählvariable (6 Bit) unsigned int nwait=m; ;Zählvariable (6 Bit) ldi r25, HIGH(M) ldi r24, LOW(M) do{ nwait--; } while(nwait!= ); wait: sbiw r24, brne wait Tue nichts bis der Wert der Zählvariable ist! 7