Prerušenia

Page

Stránky / Arduino / Pod kapotou Arduina /

Väčšina mikrokontrolérov používa prerušenia. Prerušenia umožňujú reagovať na externé podnety, zatiaľ čo sa hlavná aplikácia venuje svojej činnosti. Externý podnet môže prísť napríklad ako signál na pine, že došlo ku zmene úrovne z low na high, alebo ako signál z timera.

Druhy prerušení

Základný zoznam prerušení je približne rovnaký pre každý mikrokontrolér. Rozdiely sú spôsobené najmä množstvom pinov, ktoré má daný mikrokontrolér k dispozícii. Mikrokontroléry s väčším množstvom pinov majú z rovnakého druhu aj viac prerušení, pretože ich nastavovanie je obvykle obmedzené 8-bitovou šírkou registrov. V nasledovnom texte sa budeme venovať ATmega328P, pretože je základom Arduina.

Prerušenie Definícia
1 RESET Reakcia na reset mikrokontroléra.
2 INT0 Externé prerušenie 0. Pin D2.
3 INT1 Externé prerušenie 1. Pin D3.
4 PCINT0 Pin Change (zmena logickej úrovne) prerušenie 0. Pin D8-13.
5 PCINT1 Pin Change (zmena logickej úrovne) prerušenie 1. Pin A0-5.
6 PCINT2 Pin Change (zmena logickej úrovne) prerušenie 2. Pin D0-7.
7 WDT Watchdog.
8 TIMER2 COMPA Timer/Counter2 Compare match A
9 TIMER2 COMPB Timer/Counter2 Compare match B
10 TIMER2 OVF Timer/Counter2 Overflow
11 TIMER1 CAPT Timer/Counter1 capture event
12 TIMER1 COMPA Timer/Counter1 Compare match A
13 TIMER1 COMPB Timer/Counter1 Compare match B
14 TIMER1 OVF Timer/Counter1 Overflow
15 TIMER0 COMPA Timer/Counter0 Compare match A
16 TIMER0 COMPB Timer/Counter0 Compare match B
17 TIMER0 OVF Timer/Counter0 Overflow
18 SPI, STC SPI serial transfer complete
19 USART, RX USART RX complete
20 USART, UDRE USART data register empty
21 USART, TX USART TX complete
22 ADC ADC conversion complete
23 EE READY EEPROM Ready
24 ANALOG COMP Analog comparator
25 TWI 2-wire serial interface
26 SPM READY Store program memory ready

Zakázanie prerušenia

Niekdy nie je vhodná situácia, aby prerušenie nastalo. Vtedy je potrebné si tento zákaz vynútiť dvojicou funkcií noInterrupts a interrupts. Napríklad vtedy, keď re rozpracovaná nejaká činnosť, ktorý môže trvať viac taktov a musí byť vykonaná naraz. Nasledovný príklad nastavuje premennú typu long. Tá ma 4 bajty, čiže ju 8-bitový mikrokontrolér nie je schopný naplniť počas jedného taktu. Preto ak chceme mať istotu, že je stále v konzistentnom stave, musíme ju obaliť zákazom prerušenia.

noInterrupts();
long xxx = ...
interrupts ();

Externé prerušenie

Externé prerušenia umožňujú reagovať na konkrétnu formu signálu. Napríklad na zmenu z LOW na HIGH alebo naopak. Arduino IDE má na tieto prerušenia pripravené dve funkcie attachInterrupt a detachInterrupt. Pozor na to, že pin v týchto funkciách má iné číslovanie, než digitálne piny. Používajú sa čísla 0 a 1, ale bezpečnejšie je použiť na to funkciu digitalPinToInterrupt.

Príklady použitia:

Pin change

Toto je podobné prerušenia ako predošlé, akurát reaguje pri hocijakej zmene úrovne na pine a môže byť nastavené na každom pine. Využijete to vtedy, keď vám stačí informácia, že došlo ku nejakej zmene. Ak potrebujete vedieť aj to, akú aktuálnu hodnotu máte na pine, musíte si ju prečítať v nasledovnom kroku. Tá najväčšia výhoda je ale v tom množstve pinov, na ktorých sa môže kontrolovať. Na tieto prerušenia ale tvorcovia Arduina nijako nemysleli a je potrebné ich nastavovať priamo v registroch.

Z tabuľky prerušení je vidno, že všetky piny obsluhujú až tri prerušenia PCINT0-2. Podľa toho, ktorý pin chceme sledovať, musíme použiť správne prerušenie a správne aj nastaviť bity v registroch, ktoré zapnú sledovanie prerušenia. Pomôckou môže byť nasledovná tabuľka, ktorá obsahuje všetky možné kombinácie.

Pin PCINT PCMSK PCIF PCIE
D0 PCINT16 PCMSK2 PCIF2 PCIE2
D1 PCINT17 PCMSK2 PCIF2 PCIE2
D2 PCINT18 PCMSK2 PCIF2 PCIE2
D3 PCINT19 PCMSK2 PCIF2 PCIE2
D4 PCINT20 PCMSK2 PCIF2 PCIE2
D5 PCINT21 PCMSK2 PCIF2 PCIE2
D6 PCINT22 PCMSK2 PCIF2 PCIE2
D7 PCINT23 PCMSK2 PCIF2 PCIE2
D8 PCINT0 PCMSK0 PCIF0 PCIE0
D9 PCINT1 PCMSK0 PCIF0 PCIE0
D10 PCINT2 PCMSK0 PCIF0 PCIE0
D11 PCINT3 PCMSK0 PCIF0 PCIE0
D12 PCINT4 PCMSK0 PCIF0 PCIE0
D13 PCINT5 PCMSK0 PCIF0 PCIE0
A0 PCINT8 PCMSK1 PCIF1 PCIE1
A1 PCINT9 PCMSK1 PCIF1 PCIE1
A2 PCINT10 PCMSK1 PCIF1 PCIE1
A3 PCINT11 PCMSK1 PCIF1 PCIE1
A4 PCINT12 PCMSK1 PCIF1 PCIE1
A5 PCINT13 PCMSK1 PCIF1 PCIE1

Takže ak chceme sledovať napríklad pin D9, kód bude vyzerať takto.

ISR (PCINT0_vect)
{
...
}

void setup() 
{
// pin change interrupt
PCMSK0 |= bit(PCINT1);  // want pin D9
PCIFR  |= bit(PCIF0);   // clear any outstanding interrupts
PCICR  |= bit(PCIE0);   // enable pin change interrupts for D8 to D13
}

void loop() 
{
...  
}

Prerušenie z časovača

Každé Arduino obsahuje aj niekoľko časovačov. Arduino Uno, ktoré je založené na mikrokontroléri ATmega328P má 3 časovače. Časovače sa dajú použiť na rôzne funkcie. Jednou zo zaujímavých funkcií je aj vyvolanie prerušenia v danom časovom intervale.

Ak sme pohodlní, môžeme na to využívať knižnicu TimerOne. Ale samotné nastavenie časovača tak, aby pravidelne vyvolával prerušenie nie je zložité. Môžete na to použiť aj moju aplikáciu AVR Timer Interrupts Calculator, ktorá vám vygeneruje priamo zdrojový kód.


19.12.2015


Menu