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.
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.
PČ | 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 |
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š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:
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()
{
...
}
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