31. Lektion: Interrupts: Unterschied zwischen den VersionenAus Attraktor Wiki
Aktuelle Version vom 30. Januar 2024, 12:54 UhrInhaltsverzeichnisInterruptsDie Interrupts funktionieren NICHT mit der REPL. Also immer aus dem Editor starten! Wenn ein Programm mit Ctrl-C oder dem STOP-Button abgebrochen wird, läuft der Interrupt weiter. Also dann den Reset-Button auf dem Demoboard drücken oder den Stecker ziehen! Was ist ein Interrupt?Interrupt bedeutet unterbrechen. Genau das macht ein Interrupt. Er unterbricht das laufende Programm und führt stattdessen eine Interrupt-Service-Routine aus. Anschließend wird das zuvor unterbrochene Programm fortgesetzt. Interrupts werden in der Regel von einer Hardware ausgelöst. Z.B.
Micropython kennt 2 Interruptquellen:
Micropython stellt für die Pins Interrupts bereit. Dazu dient die Methode Pin.irq(). >>> from m5import import * >>> from machine import Pin >>> dir(Pin) ['__class__', '__name__', 'value', '__bases__', '__dict__', 'IN', 'IRQ_FALLING', 'IRQ_RISING', 'OPEN_DRAIN', 'OUT', 'PULL_DOWN', 'PULL_HOLD', 'PULL_UP', 'WAKE_HIGH', 'WAKE_LOW', 'init', 'irq', 'off', 'on'] Interrupts einrichtenDie Interruptfunktion ist eine Methode der Klasse Pin.
Pin.irq(handler=None, trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, *, priority=1, wake=None, hard=False)
BeispielHier mit Lambda-Funktion als Interrupt-Handler. (s. Timer) # int_test_01.py from machine import Pin int_pin = Pin(14, Pin.IN, Pin.PULL_DOWN) led_pin = Pin(22, Pin.OUT) led_pin.value(1) int_pin.irq(handler=lambda t:led_pin.toggle(), trigger=int_pin.IRQ_RISING) Interrupt TriggerFür den Pico stehen nur diese beiden Trigger zur Verfügung: Pin.IRQ_FALLING Pin.IRQ_RISING Trigger können auch ODER (|) verknüpft werden (Pin.IRQ_FALLING | Pin.IRQ_RISING) . Interrupts Ein-/AusschaltenInterrupts können ein- und ausgeschaltet werden. Das ist z.B. wichtig, wenn eine Programmsequenz nicht unterbrochen werden darf. int_state speichert den Interrupt Status.
import machine int_state = machine.disable_irq() machine.enable_irq(int_state) Der IRQ-Status des Programms muss .enable() übergeben werden, sonst gibt es eine Fehlermeldung! Interrupt HandlerWährend die Einrichtung eines Interrupts einfach ist, unterliegt das Schreiben des Handlers einigen Einschränkungen. Wenn man diese nicht berücksichtigt wird man auf mysteriöses Fehlverhalten stoßen. Einschränkungen für Interrupt-HandlerInterrupt Handler können keinen Speicher benutzen. Deshalb ist ihre Anwendung eingeschränkt.
Interrupt Handler schreibenISR’s sollten immer so kurz wie möglich gehalten werden. Nur Aktivitäten sie sofort ausgeführt werden müssen (z.B. Notstop) sollten in der ISR ausgeführt werden. Alles, was etwas warten kann sollte erst in der Hauptschleife bearbeitet werden. Dort gelten auch die eben dargestellten Einschränkungen nicht. Dazu ist in der ISR ein Flag zu setzen und in der Hauptschleife abzufragen. Probleme bei InterruptsInterrupts arbeiten auf Maschinencode Ebene. Deshalb kann es passieren, das ein Pythonbefehl mitten in seiner Ausführung unterbrochen wird und erst die ISR abgearbeitet wird bevor der Pythonbefehl zu Ende ausgeführt wird. Das kann zu Fehlern führen wenn die ISR etwas verändert, das vom Hauptprogramm bearbeitet wird. Dadurch können Fehler entstehen, die nur sporadisch auftreten und sehr schwer zu finden sind. Parameter des HandlersDem Interrupt-Handler wird beim Aufruf ein Parameter übergeben. Es ist wichtig, das dieser bei der Definition berücksichtigt wird. Es gibt keinen Zwang diesen auch zu benutzen.
BeispieleHandler mit globaler Variablen und print()Um im Interrupt-Handler Variablen verwenden zu können sind globale Variablen erforderlich. Diese werden im Hauptprogramm initialisiert und können dann vom Handler benutzt werden. # int_test_03.py from machine import Pin from time import sleep_ms main_loop_zahl = 0 interrupt_zahl = 0 int_pin = Pin(11, Pin.IN, Pin.PULL_DOWN) # Pin von Taster A mit Pullup-R def int_handler(int_info): # muss einen Parameter haben global interrupt_zahl interrupt_zahl += 1 print('Interrupt:', str(interrupt_zahl)) int_pin.irq(trigger=Pin.IRQ_RISING, handler=int_handler) while True: main_loop_zahl += 1 print('Mainloop:',str(main_loop_zahl)) sleep_ms(1000) Handler mit Aufruf einer FunktionHier wird vom Handler eine im Hauptprogramm definierte Funktion aufgerufen. # int_test_04.py from machine import Pin from time import sleep_ms main_loop_zahl = 0 interrupt_zahl = 0 int_pin = Pin(11, Pin.IN, Pin.PULL_DOWN) def inc_zahl(zahl): zahl += 1 return zahl def int_handler(int_info): # muss einen Parameter haben global interrupt_zahl interrupt_zahl = inc_zahl(interrupt_zahl) print('Interrupt:', str(interrupt_zahl)) int_pin.irq(trigger=Pin.IRQ_RISING, handler=int_handler) while True: main_loop_zahl += 1 print('Mainloop:',str(main_loop_zahl)) sleep_ms(1000) Parameter auswertenHier wird die Auswertung des an den Handler übergebenen Parameters getestet. # int_test_05.py from machine import Pin from time import sleep_ms main_loop_zahl = 0 interrupt_zahl = 0 int_pin = Pin(11, Pin.IN, Pin.PULL_DOWN) def int_handler(int_info): # muss einen Parameter haben print(int_info) if int_info == int_pin: print('Es ist b_up') int_pin.irq(trigger=Pin.IRQ_RISING, handler=int_handler) while True: main_loop_zahl += 1 print('Mainloop:',str(main_loop_zahl)) sleep_ms(1000) ToDo
Zurück zur "Micropython Kurs 2023 Teil 2" Startseite |