Interrupts
Worum geht's?
[Bearbeiten]Die Verwendung von Interrupts ist ein gängiges Konzept um zeitkritische Aufgaben zu bearbeiten. Sie ist nicht speziell für die Programmierung von Microcontrollern.
In einem "gewöhnlichen" PC ist es die Aufgabe des Betriebssystem sich mit der Bearbeitung von Interrupts zu beschäftigen. Die Vorgänge sind hier zwar im wesentlichen die gleichen, als Programmierer kommt man mit ihnen aus dem genannten Grund in der Regel aber nicht in Kontakt.
Anders liegen die Dinge bei der Programmierung eines Microcontrollers. Hier gibt es kein Betriebssystem, das diese Aufgabe abnimmt. Man muss sich bei der Programmierung also selbst darum kümmern.
Da es sich beim Arbeiten mit Interrupts um ein ungewohntes Tätigkeitsfeld handeln kann, ist ihnen hier ein eigenes Kapitel gewidmet.
Interrupts
[Bearbeiten]Mit Interrupts ist es möglich auf Ereignisse zu reagieren, die nicht durch den Programmablauf hervorgerufen werden. Dabei kann es sich z.B. um den Ablauf eines Timers, eine Zustandsänderung eines Pins, etc. handeln.
Die besonderen Ereignisse sind durch die Hardware des Microcontrollers vorgegeben. Jedem Ereignis ist eine eindeutige Zahl zugeordnet.
Für jedes besondere Ereignis kann eine Routine eingerichtet werden, die beim Eintreffen des Ereignisses aufgerufen wird. Eine solche Routine wird auch als Interrupt Service Routine oder kurz ISR bezeichnet.
AVR Micorcontroller
[Bearbeiten]Alle Interrupts haben enable bits.
Interrupt Vektoren liegen direkt nach RESET am Beginn des Programmspeichers.
Je geringer die Adresse, desto höher die Priorität.
Die Header Datei <avr/interrupts.h> der AVR Libc enthält Funktionen und Makros um mit Interrupts zu arbeiten.
Vorsicht! Das Statusregister SREG wird beim Betreten von Interrupt Routinen nicht automatisch von der Hardware gesichert und am Ende wieder hergestellt. Das muss in Software gemacht werden. Diese Aufgabe übernimmt der Compiler. Mit dem Makro ISR_NAKED
In der Regel findet immer zuerst eine Rückkehr ins Hauptprogramm statt, bevor auf andere Interrupts geprüft wird. Mit dem Makro ISR_NOBLOCK kann dafür gesorgt werden, dass nach dem Betreten der ISR die Zustellung von Interrupts so schnell wie möglich wieder aktiviert wird. Auf diese Weise können geschachtelt ablaufende Interrupts realisiert werden. Achtung!: Stacküberlauf, etc ...
Typen
[Bearbeiten]Es gibt 2 Typen von Interrupts.
- Interrupts, die durch Flags gesteuert werden
- Interrupts, die durch Zustände gesteuert werden
Bei Interrupts, die durch Flags gesteuert werden, wird das zugehörige Flag beim Ausführen der Service Routine gelöscht. Flags können auch durch Schreiben von 1 in das zugehörige Bit gelöscht werden.
Wenn eine Interrupt-Bedingung eintrifft während der Interrupt nicht aktiviert ist, wird das zugehörige Flag gesetzt. Das Interrupt Request wird in diesem Fall ausgelöst, sobald der Interrupt wieder aktiviert wird.
Für Interrupts, die durch Zustände gesteuert werden, muss es nicht notwendiger Weise auch ein Flag geben. Wenn der Interrupt beim Eintreten der Bedingung deaktiviert ist, wird er nicht behalten.
atomare Zugriffe
[Bearbeiten]Bei der Programmierung von Interrupt Service Routinen müssen einige Dinge beachtet werden.
Übersicht
[Bearbeiten]Für einen AtMega28p gibt es die folgenden Interrupts
Quelle | AVR Libc Makro | Interrupt Enable | Interrupt Flag | |
---|---|---|---|---|
1 | RESET | - | ||
2 | INT0 | INT0_vect | EIFR.INTF0 | |
3 | INT1 | INT1_vect | EIFR.INTF1 | |
4 | PCINT0 | PCINT0_vect | PCMSK0.PCINT7...PCINT0 | PCIFR.PCIF0 |
5 | PCINT1 | PCINT1_vect | PCMSK1.PCINT14...PCINT8 | PCIFR.PCIF1 |
6 | PCINT2 | PCINT2_vect | PCMSK0.PCINT23...PCINT16 | PCIFR.PCIF2 |
7 | WDT | WDT_vect | ||
8 | TIMER2 COMPA | TIMER2_COMPA_vect | TIMSK2.OCIEA | TIFR2.OCFA |
9 | TIMER2 COMPB | TIMER2_COMPB_vect | TIMSK2.OCIEB | TIFR2.OCFB |
10 | TIMER2 OVF | TIMER2_OVF_vect | TIMSK2.TOIE | TIFR2.TOV |
11 | TIMER1 CAPT | TIMER1_CAPT_vect | TIMSK1.ICIE | TIFR1.ICF |
12 | TIMER1 COMPA | TIMER1_COMPA_vect | TIMSK1.OCIEA | TIFR1.OCFA |
13 | TIMER1 COMPB | TIMER1_COMPB_vect | TIMSK1.OCIEB | TIFR1.OCFB |
14 | TIMER1 OVF | TIMER1_OVF_vect | TIMSK1.TOIE | TIFR.TOV |
15 | TIMER0 COMPA | TIMER0_COMPA_vect | TIMSK0.OCIEA | TIFR0.OCFA |
16 | TIMER0 COMPB | TIMER0_COMPB_vect | TIMSK0.OCIEB | TIFR0.OCFB |
17 | TIMER0 OVF | TIMER0_OVF_vect | TIMSK0.TOIE | TIFR0.TOV |
18 | SPI, STC | SPI_STC_vect | ||
19 | USART, RX | USART_RX_vect | UCSR0B.RXCIE0 | UCSR0A.RXC0 |
20 | USART, UDRE | USART_UDRE_vect | UCSR0B.UDRIE0 | UCSR0A.UDRE0 |
21 | USART, TX | USART_TX_vect | UCSR0B.TXCIE0 | UCSR0A.TXC0 |
22 | ADC | ADC_vect | ||
23 | EE READY | EE_READY_vect | ||
24 | ANALOG COMP | ANALOG_COMP_vect | ||
25 | TWI | TWI_vect | TWCR.TWIE | TWCR.TWINT |
26 | SPM READY | SPM_READY_vect |
Fußnoten
[Bearbeiten]