Tag 2 Eingabe und Interrupts 08/30/10 Fachbereich Physik Institut für Kernphysik Bastian Löher, Martin Konrad 1
Taster Direkt an Portpin angeschlossen (etwa PINB0, PIND3) Pull-Up-Widerstände einschalten! Gedrückt: PINxn == 0, losgelassen: PINxn == 1 Auf myavr-board Taster an Port K (+ Joystick ) 08/30/10 Fachbereich Physik Institut für Kernphysik Bastian Löher, Martin Konrad 2
Tastenabfrage 1. Polling: Status des PINx wird in Schleife dauernd abgefragt Vorteil: Einfach Nachteile: langsam und ineffizient funktioniert nicht während der Controller andere Dinge erledigt 2. Interrupts: Wenn Taster gedrückt, wird Interrupt ausgelöst Vorteil: Unabhängig vom restlichen Code Nachteil: Größerer Aufwand 08/30/10 Fachbereich Physik Institut für Kernphysik Bastian Löher, Martin Konrad 3
Polling Innerhalb einer while-schleife wird immer wieder der Status abgefragt Wichtig: Zum Lesen immer PINx abfragen, nicht PORTx Programm (teil3_taster1): while(1) // Endlosschleife { // Frage, ob Taster gedrückt ist if( PINK!= 0x0) PORTD = ~PINK; // Immer PINx abfragen! } Datum Fachbereich Physik Institut für Kernphysik C-Kurs 4
Interrupts Unterbrechen sofort aktuelle Codeausführung Spezielle Interruptroutine (ISR) wird ausgeführt Adressen der ISRs werden in Interrupt Vector Tabelle definiert ISRs sollten möglichst kurz sein Rückkehr zum eigentlichen Code nach Ende der ISR.org 0x000 rjmp RESET rjmp EXT_INT0 rjmp EXT_INT1 rjmp TIM2_COMP rjmp TIM2_OVF rjmp TIM1_CAPT rjmp TIM1_COMPA rjmp TIM1_COMPB... ; kommt ganz am Anfang des Speichers ; Interruptvektoren überspringen ; und zum Hauptprogramm ; IRQ0 Handler ; IRQ1 Handler Wird in C automatisch generiert! ; Timer1 Capture Handler ; Timer1 CompareA Handler ; Timer1 CompareB Handler 08/30/10 Fachbereich Physik Institut für Kernphysik Bastian Löher, Martin Konrad 5
Interruptbehandlung Interruptquelle konfigurieren: Spezieller Pin wird geändert: etwa PORTK0 Timer läuft ab (wie bei Windows) Externer Interrupt Register im ATmega640: PCICR: Pin Change Interrupt Control Register Die drei verschiedenen PC-Interrupts ein (PCINT0:2) Jedes Interrupt kann von 8 verschiedenen Pins getriggert werden PCMSKx: Pin Change Interrupt Mask Register 0 bis 2 Legt fest, welche der 8 Pins das Interrupt auslösen Interrupts generell einschalten: sei(); (set enable interrupt) Wichtig: #include <avr/interrupt.h> Datum Fachbereich Physik Institut für Kernphysik C-Kurs 6
Die Interrupt Service Routine Eine ISR kann nicht unterbrochen werden Syntax (teil3_taster2): kurz halten ISR(PCINT2_vect) { uint8_t in = ~PINK; // Status von PIN K auslesen PORTD = in; // Port D setzen PORTL++;// hochzählen } Makro ISR erwartet als Argument den Interruptvektor ATmega640 hat 57 verschiedene Interruptvektoren Beispiel: TIMER0_OVF_vect, PCINT0_vect,... Definiert in den Headerdateien von WinAVR Datum Fachbereich Physik Institut für Kernphysik C-Kurs 7
Problematik Prellen Beispiel: Zählen mit schlechtem Taster (Büroklammer) Beim Schaltvorgang wird mehr als einmal geschaltet (unsauber) Zähler würde jeden Schaltvorgang einzeln zählen Abhilfe: Entprellung des Tasters Zwischen Schaltvorgängen muss mindestens Δt vergehen Implementierung durch unabhängigen Timer des ATmega640 Datum Fachbereich Physik Institut für Kernphysik C-Kurs 8
Timer/Counter Ein vom restlichen Programm unabhängiger Zähler Entweder 8 oder 16 bit Größe ATmega640 besitzt 6 verschiedene Timer/Counter Default: Ausgeschaltet Konfigurationsregister: TCCRxA/B/C: Timer Counter Control Register x A, B und C Einstellen der Zählfrequenz als Bruchteil der Taktfrequenz des Controllers TIMSKx: Timer Interrupt Mask x z.b. Einschalten des Überlauf- Interrupts Datum Fachbereich Physik Institut für Kernphysik C-Kurs 9
Entprellung Idee: Timer gibt feste Zeitintervalle vor, die durch Interrupt gezählt werden Werden innerhalb des Intervalls (z.b. 50 ms) Taster mehrmals gedrückt, nur 1 Tastendruck zählen Beispielcode (teil3_taster3): while(1) // Endlosschleife { // Wenn timer mehr als CNTDEBOUNCE mal ausgelöst hat if(gkeycounter > CNTDEBOUNCE && gkeycounter < CNTREPEAT) { gkeycounter = CNTREPEAT; PORTD = 0x1; // LED einschalten _delay_ms(dlyled); // Warten PORTD = 0x0; // LED ausschalten PORTL++; // Hochzählen } } Datum Fachbereich Physik Institut für Kernphysik C-Kurs 10
Aufgaben DIP-Schalter abfragen und auf LEDs abbilden Einfachen Taschenrechner programmieren Ein Taster zählt hoch, einer herunter, der dritte führt die Operation aus, die über DIP-Schalter eingestellt wird, Ergebnis auf 8 LED Tipp: Taster des MK3 prellen nicht merklich Ampel -Steuerung programmieren (Timer + 3 LED) Datum Fachbereich Physik Institut für Kernphysik C-Kurs 11