This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revision | |||
| de:avr:interrupts [2011/08/11 15:11] – wittkoepper | de:avr:interrupts [2020/07/20 12:00] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== Interrupts ====== | ||
| + | Interrupts können im AVR – je nach Controller - durch Zähler, Kommunikations-Interfaces, | ||
| + | |||
| + | Jeder Interrupt des AVR Microcontrollers ist an ein bestimmtes Ereignis gebunden. Jedes Ereignis hat einen Flag-Bit im Status-Register, | ||
| + | |||
| + | <box 100% round # | ||
| + | |||
| + | Um Interrupts mit der AVR LibC Bibliothek zu nutzen, ist es notwendig interrupt.h einzubinden. Der Code der ausgeführt wird, wenn der Interrupt stattfindet, | ||
| + | |||
| + | <code c> | ||
| + | #include < | ||
| + | |||
| + | ISR(XXX_vect) | ||
| + | { | ||
| + | // Anweisungen | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | </ | ||
| + | |||
| + | Die generelle Erlaubnis sämtlicher Interrupts wird vom Control- und Statusregister SREG konfiguriert. Die Option, alle Interrupts sofort zu erlauben oder zu verbieten existiert zum Schutz von Daten. Da Interrupts das Ausführen eines Programms unterbrechen, | ||
| + | |||
| + | < | ||
| + | |||
| + | <box 100% round # | ||
| + | |||
| + | Angenommen, in diesem Programm wird eine 16-Bit Variable verwendet, welche sowohl von dem Hauptprogramm, | ||
| + | |||
| + | <code c> | ||
| + | #include < | ||
| + | |||
| + | // Globale 16-Bit Variable x und y | ||
| + | unsigned short x, y; | ||
| + | |||
| + | // Ein zufälliger Interrupt der den Wert von x ändert. | ||
| + | ISR(XXX_vect) | ||
| + | { | ||
| + | x = 0x3333; | ||
| + | } | ||
| + | |||
| + | int main() | ||
| + | { | ||
| + | // x einen Wert geben | ||
| + | x = 0x1111; | ||
| + | |||
| + | // Interrupts generell erlauben | ||
| + | sei(); | ||
| + | |||
| + | // y erhält Wert von x | ||
| + | y = x; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | |||
| + | Das Programm selbst ist sehr einfach - zuerst bekommt die Variable x den Wert 0x1111 und später wird dieser an y weitergegeben. Wenn ein Interrupt zwischen diesen beiden Operationen auftritt, bekommt x einen Wert von 0x3333. Logisch gesehen kann y somit zwei mögliche Werte am Ende des Programms haben, allerdings existiert bei einem 8-Bit AVR noch eine dritte Möglichkeit. Hierzu kommt es, da die 8-Bit Architektur zur Verarbeitung von 16-Bit Daten 2 Taktzyklen braucht. Daher kann ein Interrupt durch schlechtes Timing die Integrität dieser Daten beschädigen. Dadurch kann y am Ende des Programms den Wert 0x1111 oder 0x3333, aber auch 0x3311 haben Um den dritten und ungewollten Wert zu verhindern, sollten alle Interrupts temporär verboten werden wenn eine Operation mehr als einen Taktzyklus umfasst. | ||
| + | |||
| + | Im folgenden Beispiel wird eine sichere Methode benutzt um y den Wert von x zu geben: | ||
| + | |||
| + | |||
| + | <code c> | ||
| + | // Interrupts generell verbieten | ||
| + | cli(); | ||
| + | |||
| + | // y erhält Wert von x | ||
| + | y = x; | ||
| + | |||
| + | // Sämtliche Interrupts wieder zulassen | ||
| + | sei(); | ||
| + | </ | ||
| + | |||
| + | </ | ||