PŘERUŠENÍ
Procesor pracuje tak, že načítá z paměti jednotlivé instrukce a ty následně zpracovává. Instrukce se zpracovávají v pořadí v jakém jsou uloženy v paměti. Vezměme jednoduchý program, který v nekonečném cyklu inkrementuje proměnnou ,tedy dokola přičítá jedničku k proměnné ( i = i + 1)
int I; setup() { I = 0; } loop() { I = I + 1; } Vznikne tak nekonečný program, modifikujme ho tak aby se zastavil po stisku tlačítka na pinu 1.
int I; boolean RUN; setup() { I = 0; RUN = true; pinMode(1, INPUT); }
// deklarace
//inicializace poč.stavu // true = nestisknuto
loop() { if(run) i = i + 1; if(digitalRead(buttonPin) = HIGH) run = false; }
Co když ale bude program v hlavní smyčce časově náročnější? Například: int I; boolean RUN;
setup() { I = 0; RUN = true; pinMode(buttonPin, INPUT); } loop() { if(run) i = i + 1; nejakaAkce(); if(digitalRead(buttonPin) = HIGH) run = false; } Předpokládejme, že funkce nejakaAkce() dělá něco smysluplného a její provedení trvá 15 vteřin.
To ale znamená, že program bude kontrolovat stav tlačítka pouze každou 15 (a nějaké drobné) vteřinu, což určitě není ideální přístup.
Řešení?
= HARDWAROVÉ PŘERUŠENÍ Přerušení je způsob jak asynchronně obsloužit důležité události. Tedy, pokud se vyskytne událost, na kterou musí procesor okamžitě reagovat, tak procesor přeruší načítání instrukcí Hlavního programu a začne načítat program určený pro zpracování té prioritní události, říkáme, že vykoná obsluhu přerušení. Jakmile obsluha přerušení skončí, procesor se opět vrátí k původní činnosti do místa, kde jí opustil(přerušil). Aby bylo možno tuto vlastnost použít musí mít procesor přerušení hardwarově implementované.
Existuje několik různých druhů přerušení, na které je možné reagovat. V příkladu výše by se hodilo použít externí hardwarové přerušení. Aby procesor reagoval na přerušení, musí to mít povoleno. Někdy může totiž provádět tak důležitou operaci , že nechceme, aby byla přerušena. V takovém případě se přerušení může vypnout a procesor bude všechny žádosti o spuštění přerušení ignorovat. Pokud je ale přerušení povoleno, pak procesor v okamžiku, kdy nastane důležitá událost zastaví načítání instrukcí hlavního programu, uloží hodnoty pracovních registrů do zásobníku a přejdena adresu na níž se nachází náš podprogram pro přerušení. Této adrese se říká vektor přerušení.
Arduino - celkem dvě externí přerušení. Jsou očíslovány 0 a 1 a jsou na digitálních pinech 2 a 3 .Na těchto pinech můžeme sledovat celkem 4 různé druhy událostí: • • • •
LOW — přerušení nastane vždy, když je pin v logické nule. CHANGE — přerušení nastane při změně logické hodnoty na daném pinu. RISING — přerušení s příchodem vzestupné hrany. FALLING — přerušení s příchodem sestupné hrany.
• Pokud chceme například reagovat na zmáčknutí tlačítka, budeme sledovat vzestupnou nebo sestupnou hranu signálu.
Arduino má čtyři funkce, které slouží pro práci s hardwarovým (tedy externím) přerušením. Tyto funkce jsou: – – – –
• • • • •
attachInterrupt() detachInterrupt() interrupts() noInterrupts()
interrupts() zapíná přerušení noInterrupts() vypíná přerušení. výchozí nastavení Arduina = externí přerušení vypnuté. Tedy chci ho použít = musím ho povolit, attachInterrupt() registruje (připojuje) a definuje funkce pro obsluhu přerušení. • Př.: Předpokládejme že máme funkci tlacitko() a chceme aby ji mikrokontrolér zavolal pokaždé, když uživatel zmáčkne tlačítko na digitálním pinu číslo 2. Budeme tedy reagovat na přerušení číslo 0 a na vzestupnou hranu:
void setup() { attachInterrupt(0, tlacitko, RISING); } void loop() { // HLAVNÍ // PROGRAM }
void tlacitko() { // Reakce na stisknutí tlačítka = obsluha přerušení }
• Při příchodu vzestupné hrany na pinu číslo 2 se okamžitě přeruší vykonávání programu ve funkci loop(), dočasně se zakáže přerušení, provede se funkce tlacitko (), opět se přerušení povolí a začne se vykonávat funkce loop() od místa, kde došlo k přerušení. • Vzhledem k tomu, že při obsluze přerušení (tedy v našem příkladě ve funkci tlacitko()) jsou všechna přerušení zakázána, je vhodné aby funkce provedla svou činnost co nejrychleji. Během vykonávání obsluhy přerušení totiž procesor nebude reagovat na žádnou jinou externí událost
int I; boolean RUN; void setup() { I = 0; attachInterrupt(0, button, RISING); } void loop() { i = i + 1; nejakaAkce(); } void button() { I=0; }
// stiskem tlacitka na PINu 2 se I vynuluje
noInterrupts() zakazuje přerušení, které lze pomocí interrupts() opět povolit
void setup() { // zde je potřebný SETUP včetně připojení přerušení } void loop() { // ČÁST PROGRAMU noInterrupts(); // kritický kus kódu který nelze přerušením rušit interrupts(); // ZBYTEK PROGRAMU } void přerušeni() { // zde obsluha přerušení }