ITG-ABI 09/10 |
19.4.2010 |
Korrekturhinweise / Lösungsvorschlag |
---|
Verwendeter µC: ATMEL AVR 8 Bit RISC.
Globale Variable stufe : GZ mit Werten von 0..9.
Globale Variable zaehl: GZ (unsigned char) für Assembler eine reservierte lokale Variable itmp
C-Lösung | Assembler |
---|---|
// 1.4 ISR(INT0_vect){ if (zaehl < 99) zaehl++; } |
ISR_int0: ; Aufgabe 1.4 in itmp,SREG ; Statusregister laden push itmp ; Statusregister retten cpi zaehl,99 brge ende ; Sprung wenn goesser oder gleich inc zaehl ; sonst erhoehe zaehl ende: pop itmp ; Statusregister holen out SREG,itmp ; Statusregister zurueckschreiben reti ; return from Interrupt |
Problem 1 Sekunde und Timer hat maximal 16 Bit. 1MHz, mögliche Vorteiler 1,8,64,256,1024
Vorteiler | Lösungen |
---|---|
1 | Alle 50 ms Interrupt (von 15535 bis 65535 zählen) und dann in ISR bis 20 zählen |
64 | Alle 64 µs Timerinkrement, von 49910 bis 65535 zählen. |
Globale Variable anzeige: GZ (unsigned char)
C-Lösung | Assembler |
---|---|
// 1.5 ISR(TIMER1_OVF1_vect){ TCNT1 = 49910; // Zeit einstellen anzeige = zaehl; // Messung zur Anzeige speichern zaehl = 0; // Sensorzaehler zurueck setzen } |
ISR_ovf1: ; Aufgabe 1.5 ldi itmp,HIGH(49910) ; obere Bits laden out TCNT1H,itmp ; oben setzen ldi itmp,LOW(49910) ; untere Bits laden out TCNT1H,itmp ; unten setzen Uebernahme mov anzeige,zaehl ; Messung speichern ldi zaehl,0 ; Sensorzaehler zurueck setzen reti ; return from Interrupt |
Hinweis zur Assembler-Lösung: Da keiner der Befehle die Flags des Statusregisters ändern kann seine Rettung und Wiederherstellung unterbleiben.
C-Lösung | Assembler |
---|---|
// 1.6 volatile unsigned char stufe=0,zaehl=0,anzeige=0; // glob. Var. void init(){ DDRA = 0xFF; // PA als Ausgang DDRB = 3; // PB0 und PB1 als Ausgang MCUCR |= 1 << ISC01; // fallende Flanke GIMSK |= 1 << INT0; // INT0 frei schalten TCNT1 = 49910; // Zeit einstellen TCCR0 = 3; // Systemtakt / 64 TIMSK |= 1 << TOIE1; // Timer1 Overflow Interrupt Enable sei(); // globale Interruptfreigabe } int main(){ init(); while (1){ A_SG_T(); } return 0; // damit Compiler nicht meckert } |
.def tmp = R16 ; Hilfsregister .def itmp =R17 ; Hilfsregister in Interrupts .def stufe = R18 .def zaehl = R19 .def anzeige = R20 rjmp reset .org INT0addr ; Interruptvektoradresse rjmp ISR_int0 .org OVF1addr rjmp ISR_ovf1 .org INT_VECTORS_SIZE ; nach Interrupts init: ldi tmp,RAMEND out SPL,tmp ; Stackpointer initialisieren ldi tmp,0xFF out DDRA,tmp ; PA als Ausgang ldi tmp,3 out DDRB,tmp ; PB0 und PB1 als Ausgang in tmp, MCUCR sbr tmp,ISC01 ; setze ISC01 Bit out MCUCR,tmp ; fallende Flanke in tmp,GIMSK sbr tmp, INT0 ; INT0 frei schalten out GIMSK,tmp ldi itmp,HIGH(49910) ; obere Bits laden out TCNT1H,itmp ; oben setzen ldi itmp,LOW(49910) ; untere Bits laden out TCNT1H,itmp ; unten setzen Uebernahme ldi tmp,3 out TCCRO,tmp ; Systemtakt / 64 in tmp,TIMSK sbr tmp,TOIE1 ; OVF1 frei schalten out TIMSK, tmp sei ; globale Interruptfreigabe ret reset: rcall init loop: rcall A_SG_T rjmp loop |