Prerušenia
Prerušenie (z angl. interrupt) umožňuje mikrokontroléru reagovať na udalosť, napr. stlačenie tlačidla, bez toho, aby program neustále kontroloval stav pinu. Keď udalosť nastane, mikrokontrolér preruší vykonávanie programu a zavolá funkciu na obsluhu prerušenia, tzv. ISR (z angl. Interrupt Service Routine). Princíp prerušení je vysvetlený v prednáške o spotrebe energie. Táto kapitola ukazuje, ako sa s prerušeniami pracuje v jazyku MicroPython.
Externé prerušenie na pine
Externé prerušenie sa nastavuje nad objektom triedy machine.Pin
metódou .irq(). Tá má dva hlavné parametre:
trigger– udalosť, pri ktorej sa prerušenie vyvolá,handler– funkcia, ktorá prerušenie obslúži; ako parameter dostane objekt pinu, na ktorom prerušenie vzniklo.
Nasledujúca ukážka vypíše správu pri každom stlačení tlačidla.
Tlačidlo je pripojené k pinu 20 a k zemi, a preto pin používa
pull-up rezistor. V kľude je na pine úroveň HIGH a
stlačenie tlačidla vyvolá dobežnú hranu:
from machine import Pin
def handle_button(pin):
print('>> Button was pressed.')
button = Pin(20, Pin.IN, Pin.PULL_UP)
button.irq(trigger=Pin.IRQ_FALLING, handler=handle_button)Vypisovanie správy vo vnútri ISR slúži len na ukážku. V skutočnom programe sa výpisom vo vnútri ISR vyhnite (pozri pravidlá pre ISR).
Poznámka
Takto sú zapojené napríklad tlačidlá na doske Robo Pico. Ak
je tlačidlo zapojené s pull-down rezistorom
(Pin.PULL_DOWN), je v kľude na pine úroveň LOW
a jeho stlačenie vyvolá nábežnú hranu.
Prerušenie na pine zrušíte tak, že metóde .irq()
odovzdáte namiesto funkcie hodnotu None:
button.irq(handler=None)Hodnoty parametra
trigger
Hodnoty parametra trigger sú konštanty triedy
Pin a dajú sa kombinovať operátorom |:
| Hodnota | Prerušenie sa vyvolá |
|---|---|
Pin.IRQ_RISING |
pri nábežnej hrane (z LOW na
HIGH) |
Pin.IRQ_FALLING |
pri dobežnej hrane (z HIGH na
LOW) |
Pin.IRQ_RISING | Pin.IRQ_FALLING |
pri každej zmene úrovne |
Niektoré porty jazyka MicroPython poznajú aj prerušenia na
úrovni signálu (Pin.IRQ_LOW_LEVEL a
Pin.IRQ_HIGH_LEVEL). Na doske Raspberry Pi Pico 2
W s mikrokontrolérom RP2350 však nie sú k dispozícii.
Podporované hodnoty zistíte v dokumentácii
alebo priamo na zariadení:
>>> from machine import Pin
>>> [name for name in dir(Pin) if name.startswith('IRQ')]
['IRQ_FALLING', 'IRQ_RISING']Pravidlá pre ISR
Funkcia na obsluhu prerušenia preruší hlavný program v ľubovoľnom okamihu, preto pre ňu platia prísnejšie pravidlá ako pre bežné funkcie. Dokumentácia jazyka MicroPython odporúča [1]:
- kód ISR má byť čo najkratší a najjednoduchší,
- vo vnútri ISR nealokovať pamäť, teda nepridávať prvky do zoznamov ani slovníkov a nepoužívať desatinné čísla,
- na prenos viacerých hodnôt medzi ISR a hlavným programom
používať vopred vytvorené objekty typu
bytearrayaleboarray.array, - pri práci so zdieľanými údajmi v hlavnom programe dočasne zakázať prerušenia,
- vyhradiť pamäť pre výpis výnimiek, ktoré vzniknú vo vnútri ISR.
Ak je potrebné pri prerušení vykonať zložitejšiu činnosť,
ISR ju môže pomocou funkcie micropython.schedule()
naplánovať. Naplánovaná funkcia sa vykoná až po skončení prerušenia, keď
už pre ňu tieto obmedzenia neplatia:
import micropython
from machine import Pin
micropython.alloc_emergency_exception_buf(100)
count = 0
def report(pin):
print('Button pressed', count, 'times.')
def handle_button(pin):
global count
count += 1
micropython.schedule(report, pin)
button = Pin(20, Pin.IN, Pin.PULL_UP)
button.irq(trigger=Pin.IRQ_FALLING, handler=handle_button)Funkcia micropython.alloc_emergency_exception_buf()
vyhradí pamäť, do ktorej sa zapíše výnimka vzniknutá vo vnútri
ISR. Bez nej by ju nebolo možné vypísať, pretože vo vnútri
ISR nie je možné alokovať pamäť.
Upozornenie
Mechanické tlačidlo pri stlačení zvyčajne niekoľkokrát zakmitá, takže jedno stlačenie môže vyvolať viacero prerušení. Ak to vadí, je potrebné prerušenia, ktoré prídu krátko po sebe, ignorovať (z angl. debouncing).
Ďalšie zdroje
- MicroPython: Writing interrupt handlers – pravidlá a odporúčania pre obsluhu prerušení
- MicroPython:
machine.Pin.irq()– dokumentácia metódy.irq()