Interrupts

Inhalte

  • Interrupts als Trigger um Funktionen sofort aufzurufen

Einführung

Viele Anwendungen sind so konzipiert, dass sie die meiste Zeit eine bestimmte Funktion erfüllen und nur beim Eintritt eines definierten Ereignisses eine bestimmte andere Funktion ausführen müssen (Ein Beispiel hierfür wäre ein Kaffeeautomat, der die meiste Zeit im Leerlauf ist, aber bei einem Münzeinwurf in einen anderen Modus wechselt).

Für manche Anwendungen ist es wichtig, dass sie – egal was sie gerade ausführen – unterbrochen werden können (etwa um einen Not-Stopp einer Anlage ausführen zu können).

Da diese Art von Unterbrechungen oder Wechsel sehr gerne zum Einsatz kommen, haben viele Mikrocontroller eine spezielle Routine hierfür vorgesehen: Interrupts.

Interrupts an Pins

Interrupts sind Funktionen, beim Eintreffen eines bestimmten Ereignisses sofort ausgeführt werden (egal, wo man sich in der Ausführung eines Programms gerade befindet). Das Arduino hat die Eigenschaft, dass die Auslösung eines Interrupts an bestimmte digitale Pins gekoppelt werden können (am Arduino UNO sind dies Pins 2 und 3). Diese Pins werden überwacht und können den Prozessor unterbrechen um eine definierte Methode, die Interrupt Service Routine (ISR), auszuführen. Diese ISRs müssen sehr kurz und schnell ausführbar gehalten werden um den Prozessor nicht zu lange zu blockieren. Dafür sind sie aber auch für Anwendungen mit sehr schnellen Zustandswechsel wie Drehencoder geeignet.

Beispiel 1: Interrupts an digitalen Pins anwenden

Folgender Code demonstriert die Einbindung einer ISR und die Verbindung der Routine mit dem digitalen Pin. Beim Anhängen an der Routine an den Pin wird außerdem definiert, welches Ereignis die ISR auslösen soll. Dieses Ereignis bezieht sich auf die Flanke des Pins. Zur Wahl stehen

  • RISING (steigende Flanke)
  • FALLIN (fallende Flanke)
  • CHANGE (also bei steigender oder fallender Flanke) und
  • LOW (ISR wird immer ausgeführt, solange der Pin LOW ist).

Das Programm an sich macht nichts anderes, als einen Pin zu überwachen und bei einem Wechsel des Zustands, die ISR aufzurufen. Diese wiederrum invertiert nur den Zustand einer Variable, die auf den ledPin 13 geschrieben wird.

Code-Analyse

Die Variable int state  wird als volatile  definiert. Dies sollte für alle Variablen gemacht werden, die in einer ISR verändert werden (sie werden hierfür in einem speziellen Speicherbereich abgelegt und können somit auf jeden Fall korrekt upgedatet werden).

Die Methode attachInterrupt(digitalPinToInterrupt(interruptPin), myISR, CHANGE) definiert den Interrupt-Pin, die ISR für diesen Pin und auf welchen Zustand geachtet werden soll:

  • Interrupt-Pin: Hierbei wird empfohlen, dass die Pin-Nummer nicht direkt angegeben wird, sondern stattdessen die Pin-ID über die Methode digitalPinToInterrupt(interruptPin)  herausgefunden wird. Grund hierfür ist, dass bei verschiedenen Arduino Plattformen (neben dem UNO existieren noch weitere) die Prozessoren möglicherweise andere  Bezeichnungen für diese Pins haben. Mit dem Aufruf dieser Methode ist garantiert, dass der Code auch auf anderen Boards wie erwartet läuft.
  • ISR: Der Name der Methode (hier myISR ) wird als Parameter angegeben.
  • Zustand: Durch die Angabe von CHANGE  wird die vorhin angegebene Methode immer dann aufgerufen, wenn der Zustand wechselt (egal ob von LOW zu HIGH oder umgekehrt).

In der loop  Methode geschieht nichts, außer dass der Zustand der Variable state  auf einen Pin geschrieben wird.

Die Methode myISR  ist eine sehr kurz gehalten und erfüllt hier nur die Funktion, dass der Zustand der Variable state  gewechselt wird. Da myISR  durch den Interrupt immer dann aufgerufen wird, wenn sich der Zustand des Interrupt-Pin ändert, ist es nicht notwendig die Funktion irgendwo anders im Code aufzurufen.

PinChangeInterrupts (PCI)

Am Arduino können für die alle Pins (nicht nur 2 und 3 wie beim UNO) mit einem PinChangeInterrupt belegt werden. Diese lösen sowohl bei RISING als auch FALLING aus, allerdings werden die ISRs immer in Gruppen von Pins definiert (d.h. mehrere Pins haben dieselbe Interrupt-Routine). Für manche Anwendungen wie z.B. Drehencoder ist dies egal, für andere muss eventuell weitere Funktionalität eingefügt werden um zwischen den Pins unterscheiden zu können.

Einen guten Überblick über PCIs gibt dieser Artikel.

Zusammenfassung

Interrupts am Arduino bieten die Möglichkeit eine ISR sofort und sehr schnell auszuführen. Mittels der Funktion attachInterrupt  wird die ISR Funktion, der Pin und der Zustandswechsel definiert. Nick Gammon empfiehlt für den Code in der ISR folgendes:

 

  • Code kurz halten
  • delay -Funktion nicht verwenden
  • Keine Serial prints
  • Variablen, die im Hauptcode und der ISR verwendet werden müssen volatile  sein
  • Interrupts sollen nicht ein- und ausgeschalten werden

 

Weiterführende Links

  • https://www.arduino.cc/en/Reference/Volatile
  • https://www.arduino.cc/en/Reference/AttachInterrupt
  • http://gammon.com.au/interrupts
  • http://playground.arduino.cc/Main/PinChangeInterrupt

 

Ein Gedanke zu „Interrupts“

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.