Popis funkcie prerušenia, práca s externým prerušením.
Prerušenie
Prerušovací podsystém umožňuje efektívnu obsluhu nepravidelných udalostí, na ktoré má mikrokontrolér reagovať. V prípade výskytu definovanej udalosti mikokontrolér preruší beh programu a venuje sa programovej obsluhe udalosti, ktorá dané prerušenie vyvolala. Po skončení tejto programovej obsluhy mikrokontrolér pokračuje vo výkone hlavného programu. Význam prerušení je hlavne v zrýchlení a zefektívnení behu programu.
V jednej chvíli (t.j. v jednom strojovom cykle) sa môžu vyskytnúť viaceré prerušenia a mikrokontrolér musí rozhodnúť, ktorá žiadosť bude vykonaná ako prvá. Na to je potrebné definovať akési poradie dôležitosti – prioritu prerušení.
Na základe priority prerušení sa určí postupnosť spracovania žiadostí v tom istom strojovom cykle. Tabuľka zdrojov prerušení pre ATmega8 je uvedená na str.46. Platí teda, že čím menšie číslo vektora prerušenia, tým ma prerušenie vyššiu prioritu. Z tabuľky teda vidíme že najväčšiu prioritu ma prerušenie od RESET a najmenšiu od SPM_RDY.
Pred použitím akéhokoľvek prerušenia sa musia prerušenia najskôr globálne povoliť. To dosiahneme pomocou funkcie sei();
Naopak v niektorých kritických častiach programu chceme prerušenie globálne zakázať. Na to slúži funkcia cli();
Vidíme teda že ATmega8 má celkovo 19 zdrojov prerušenia. V tejto časti sa budeme venovať externým prerušeniam - INT0, INT1. Z využitým ďalších zdrojov prerušenia sa zoznámime v ďalších častiach seriálu.
Zápis obsluhy prerušenia:
Na začiatku programu pridáme hlavičkový súbor #include <avr/interrupt.h> , ktorý nám zabezpečí prácu s prerušeniami.
Samotnú funkciu prerušenia potom deklarujeme takto:
ISR (vektor prerušenia) {
// ... akcia prerušenia ... //
}
Program s prerušením môže teda vyzerať takto:
Podľa možnosti sa snažíme obslužnú funkciu prerušenia spraviť čo najkratšiu (zmeniť premennú a pod.). Robíme to preto, aby zbytočne dlhá obsluha prerušenia nebrzdila hlavný program alebo prípadne ďalšie prerušenia, ktoré môžu nastať.
Zdielané premenné:
Ak potrebujeme v obsluhe prerušenia meniť hodnotu globálnej premennej, musí byť táto premenná deklarovaná s kľúčovým slovom volatile. V opačnom prípade sa zmena hodnoty premennej vykonaná v obsluhe prerušenia neuchová po skončení obsluhy. Príklad: volatile uint8_t abc;
Externé prerušenia:
Využívame ich vtedy, ak chceme prerušenie vyvolať zvonku (napr. stlačenie tlačidla). ATmega8 má dva externé zdroje prerušenia nazvané INT0 (na pine PD2) a INT1 (na pine PD3).
Na ich obsluhu využívame dva registre (pozri datasheet strana 66):
MCUCR – pomocou bitov ISC11, ISC10, ISC01 a ISC00 v tomto registri nastavíme spôsob aktivácie externého prerušenia od INT0 a INT1.
Na výber máme tieto možnosti:
- Reakcia na nízku úroveň napätia na pine
- Zmena logického stavu na pine
- Reakcia na nábežnú hranu (rising edge)
- Reakcia na dobežnú hranu (falling edge)
Príklad:
Nastavíme reakciu INT0 na nábežnú hranu a INT1 na dobežnú hranu:
MCUCR |= (1 << ISC01) | (1 << ISC00) ; // INT0 na nábežnú hranu
MCUCR |= (1 << ISC11); //INT1 na dobežnú hranu
GICR - pomocou bitov INT1 a INT0 v tomto registri povolíme prerušenia od INT0 a INT1.
Príklad:
Povolenie prerušenia od INT1:
GICR |= (1 << INT1);
Ukážkový program:
Zapnutie LED na pine PD7 pomocou INT0 a vypnutie pomocou INT1. Reakcia prerušenia na dobežnú hranu (zmenu z log. 1 na log. 0).
Schéma zapojenia:
Zdrojový kód:
Zdrojový kód – použitie globálnej premennej:
To isté ako prvý ukážkový program, ale s použitím globálnej premennej. Tip: vyskúšajte si program bez kľúčového slova „volatile“. Youtube video:
V ďalšej časti sa pozrieme na prácu s čítačom/časovačom a oboznámime sa s možnosťami jeho použitia.
Ďakujem za pomoc všetkým, čo sa podieľali na tvorbe tejto časti.