ITG-ABI 09/10

19.4.2010

Korrekturhinweise / Lösungsvorschlag

Teil 1 Aufgabe 1

Verwendeter µC: ATMEL AVR 8 Bit RISC.

Mögliche Pin-Belegung

PA = P1; PB = P2; PD = P3

Aufgabe 1.3

Globale Variable stufe : GZ mit Werten von 0..9.

Aufgaben 1.4 bis 1.6

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

Aufgabe 1.5

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.

Aufgabe 1.6

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
  

Aufgabe 1.7