Reklama

Externí přerušení nejen s ATtiny24 – 1. Díl Teoretický popis

Úvod

V článku budu předpokládat, že máte jisté minimální zkušenosti s programováním AVR v jazyce C, dále předpokládám, že zvládáte ovládání I/O portů a že máte představu co je to přerušení. Zdrojové kódy budou psány pro AVR studio. Kdo programuje například v Codevision, bude mít jiné názvy rutin přerušení a typicky využije Codewizzard, který za něj externí přerušení nastaví. Bude-li chtít kód použít, bude si jej muset upravit. Ukázky budu provádět na čipu Attiny24A, protože jsou levné a mám jich slušnou zásobu. Ovládání bude ale principiálně podobné jako na většině čipů řady Atmega (ty budou ale bohatěji vybaveny).

K čemu slouží přerušení?

Napíšu to jen ve zkratce. V principu k tomu samému jako jakékoli jiné přerušení. Umožňuje mikrokontroléru (zkráceně čipu) reagovat na asynchronní událost. Kdyby nebylo přerušení, čip by vykonával program instrukci za instrukcí, a pokud byste chtěli nějak reagovat na vnější událost, museli byste neustále kontrolovat, zda nenastala. V případě časovače byste se pořád museli dívat na vlajku, zda nepřetekl, u AD převodníku byste stále museli kontrolovat, zda nedokončil převod, u přijímání dat sériovou linkou byste neustále museli sledovat, zda vám nedorazila nová data. Takový styl programování je nejen komplikovaný, ale také nespolehlivý. Představte si, že máte provádět relativně náročný výpočet, na který sice nespěcháte, ale trvá vám třeba 5 ms. Ale zároveň chcete kontrolovat příchod dat z vnějšku (třeba z počítače po sériové lince). Sledujte modelovou situaci, zahájíte výpočet, během něj vám přijde první znak zprávy a čeká na vás, vy ale počítáte, chvíli nato přijde druhý znak zprávy a vy stále počítáte. Přirozeně druhý příchozí znak smaže ten první, protože jste si ho nevyzvedli. Vy totiž počítáte. Abyste se toho vyvarovali, museli byste do výpočtu vkládat kód, který bude sledovat příchod dat po sériové lince. Zdrojový kód takového výpočtu by byl úplným rodištěm různých chyb, byl by neuvěřitelně nepřehledný, těžko modifikovatelný a typicky i nespolehlivý. A přesně proto je tu institut přerušení. Po vyvolání přerušení program odskočí do jiné části vašeho kódu, kde vykoná vše potřebné a pak se vrátí na své místo a pokračuje, kde přestal (ve vašem případě ve výpočtu).

K čemu může být externí přerušení?

Zdrojů přerušení, tedy i událostí, jež mohou nějaké přerušení vyvolat, má čip hodně. Jedním z nich je externí přerušení a jak už název napovídá, bude sloužit k reakci na vnější událost. Modelových situací je mnoho. Začneme nějakou rozumnou. Měříme zrychlení čidlem ADXL345. Než abychom se čidla stále dokola doptávali, zda už má k dispozici nová data (tzv polling), nakonfigurujeme ho tak, aby nám na jednom drátě poslalo logickou úroveň (typicky 0V) ve chvíli, kdy bude mít data připravena. My si nakonfigurujeme externí přerušení a kdykoli jsou data připravena, můžeme je okamžitě z čidla vyčíst a zpracovat. Jiný příklad. Používáte teploměr LM75 k detekci přehřátí, když ho vhodně nakonfigurujete, bude také schopen jedním vývodem signalizovat přehřátí (nebo podchlazení). Váš čip se opět nebude muset ptát na teplotu a kontrolovat ji sám, pouze počká na přerušení. Podobná situace může nastat s obvody RTC (hodiny, kalendáře). RTC může pomocí jednoho výstupu čipu signalizovat třeba naprogramovaný alarm (čas vstávat do práce/školy !). Další využití najde externí přerušení v časově kritických aplikacích. V příkladu s RTC vám je celkem jedno, jestli budík zazvoní o pár milisekund dříve či později. Můžete mít ale například aplikaci, která přepíná zdroj napájení. Jakmile detekuje, že primární zdroj přestává dodávat energii (například pokles napětí, nebo signalizace o poruše), budete potřebovat rychle přepnout na záložní zdroj. Externí přerušení je schopno reagovat už během mikrosekundy. Další užitečné použití externího přerušení najdete u “low power” aplikací. Čip můžete uspat, abyste snížili odběr (klidně na zlomky uA). A jen čas od času ho ze spánku probrat a provést nějakou akci. Čip může spát, čekat na stisk tlačítka (který vyvolá externí přerušení), probrat se a vykonat nějakou akci. Například po stisku změří hodnotu, zobrazí ji na displeji a zase usne. Případně čip čeká v režimu spánku na vyvolání alarmu pomocí externího přerušení, po probuzení aktivuje GSM modul a pošle vám SMSku. V poslední řadě bych zmínil ještě třeba obsluhu rotačního enkodéru (“potenciometr” co se může točit pořád dokola a má “kroky”). Kdo nevíte, o co se jedná, vyhledejte si v googlu “rotary encoder”. U některých typů enkodérů vám stačí jeden jeho kanál připojit na externí přerušení a v rutině přerušení pak jen sledovat úroveň druhého kanálu a přičítat nebo odečítat kroky.

Co máme na Attiny24 k dispozici?

K dispozici máme jedno plnohodnotné přerušení na pinu PB2 (INT0). Mikrokontrolér Atmega32 má tři, Atmega128A dokonce osm. Čip umí na INT0 detekovat čtyři různé události. Prvně může detekovat přítomnost logické úrovně 0. Přerušení je pak voláno stále, dokud není na INT0 zpět log. 1. V tomto režimu (a pouze v tomto) je možné budit čip z hlubokého spánku (z režimů POWER DOWN a STAND BY, které mají největší úsporu energie). Dále je možné pomocí INT0 detekovat nástupnou hranu (přechod z log. 0 do log. 1), sestupnou hranu a jakoukoli změnu (tedy jakoukoli hranu). V těchto třech případech je rutina přerušení zavolána vždy jen jednorázově. Další volání rutiny přerušení proběhne až po detekování další události. Jisté trable mohou nastat, pokud přijdou události v rychlém sledu za sebou. To si ale rozebereme později. Kromě INT0 nám čip nabízí ještě takzvané “Pin Change Interrupt – PCINT”. Pomocí něj může čip reagovat na změnu logické hodnoty na libovolné skupině vstupů. PCINT nemá takový komfort jako INT0, můžeme detekovat jen změnu na vstupu, nikoli třeba konkrétně sestupnou hranu. Chcete-li tedy reagovat pouze na sestupnou hranu pomocí PCINT, musíte si v rutině přerušení situaci ošetřit a sestupnou hranu rozpoznat, přerušení totiž bude vyvoláno i nástupnou hranou. Pozitivní na celé věci je to, že PCINT může hlídat libovolné piny procesoru. Chcete-li tedy detekovat změnu na PB1, PA2 a PA3, máte možnost. Piny pro PCINT jsou rozděleny do dvou skupin. První skupinou jsou piny 0 až 7, ve druhé skupině pak piny 8 až 11 (v případě jiných čipů může být skupin více). Každá skupina má svoji vlastní rutinu přerušení. Tady vás opět může čekat komplikace. Spustíte-li externí přerušení na PA1,PA2 a PA3 (tedy PCINT1, PCINT2 a PCINT3), zavolá se jedna jediná rutina přerušení a vy budete muset sami rozpoznat, který z pinů ji vyvolal. Není to až tak obtížné, ale stojí to za trochu rozmyšlení, které nechám na vás :) Ve stručnosti je to asi tak vše, co vám systém externího přerušení na Attiny24 nabízí.

A teď trochu detailněji

Tak jako všechny periferie mikrokontroléru i externí přerušení se řídí nastavováním a čtením bitů ve speciálních registrech. Používat budete tyto:

Tab. 1: Popis registru MCUCR – MCU Control Register

Pozice bitu Označení
7 – (nejvyšší váha) BODS
6 PUD
5 SE
4 SM1
3 SM0
2 BODSE
1 ICS01
0 – (nejnižší váha) ICS00

Zde pomocí dvojice bitů ICS01 a ICS00 konfigurujete přerušení z ICT0. Všechny čtyři již výše zmiňované kombinace jsou shrnuty v následující tabulce.

Tab. 2: Konfigurace INT0

ISC01 ISC00 Popis
0 0 Log. 0 na INT0 vyvolá přerušení
0 1 Jakákoli změna na INT0 vyvolá přerušení
1 0 Sestupná hrana na INT0 vyvolá přerušení
1 1 Nástupná hrana na INT0 vyvolá přerušení

V registru GIMSK pomocí bitů INT0, PCIE1 a PCIE0 konfigurujete, které z přerušení chcete povolit nebo zakázat. Zapsáním log. 1 příslušné přerušení povolujete, zapsáním log. 0 zakazujete. I když přerušení zakážete, může detekce události (tedy například sestupné hrany na ICT0) běžet. Projeví se pak v registru GIFR. O přerušení z pinů 0 až 7 (PCINT0PCINT7) se stará bit PCIE0 o piny 8 až 11 pak bit PCIE1. Bit INT0 povoluje a zakazuje přerušení od INT0.

Tab. 3: Popis registru GIMSK – General Interrupt Mask Register

Pozice bitu Označení
7 – (nejvyšší váha) -
6 INT0
5 PCIE1
4 PCIE0
3 -
2 -
1 -
0 – (nejnižší váha) -

Registr GIFR signalizuje stav vlajek přerušení. Jestliže je detekována vybraná událost (například nástupná hrana), dojde k nastavení vlajky v tomto registru. Pokud není přerušení povoleno ať už v registru GIMSK nebo jsou všechna přerušení globálně zakázána (existuje na to příkaz cli()), skončí celá akce pouze nastavením vlajky. Nastavením vlajky rozumíme nastavení příslušného bitu do log. 1. Váš program může z tohoto registru číst a stav vlajek sledovat a dle potřeby na to reagovat. Pokud jsou přerušení povolena, tak jakmile dojde k nastavení vlajky, je ihned volána rutina přerušení. Jakmile do ní program vstoupí, vlajka se automaticky smaže (nastaví do log. 0). Od tohoto okamžiku je možné detekovat další událost. Události vám mohou přijít ale v tak rychlém sledu, že na ně čip nebude schopen zareagovat. Prvním příkladem může být situace, kdy chcete pomocí externího přerušení počítat, kolik vám přišlo pulzů. Což není elegantní, na to máte čítač. Přijde vám první pulz, dojde k nastavení vlajky a než se procesor dostane do rutiny přerušení, stihne vám přijít ještě jeden pulz. A ten vám unikne. Přišel totiž v době, kdy byla ještě stále nastavena vlajka indikující příchod prvního pulzu. Procesoru může několik mikrosekund trvat, než se dostane do rutiny přerušení a po celou tu dobu je vlajka nastavena a čip není schopen rozpoznat další událost. Situace může být o to horší, pokud procesor zrovna zpracovává rutinu jiného přerušení, pak si typicky musíte počkat, než ji dokončí (ale tohle jde změnit). Jestliže povolíte přerušení a zůstala vám vlajka z nějakého důvodu nastavena, dojde ihned k zavolání rutiny přerušení. To se typicky stává, když celý systém inicializujete. Spustíte procesor, začnete nastavovat porty, časovače a kdo ví co ještě a mezi tím se mimo procesor může dít spoustu věcí. Třeba mu můžou na vstup přicházet signály. Takže před inicializací externích přerušení může být vhodné si vlajku pro jistotu smazat. Vlajku můžete mazat tím, že do ní zapíšete log. 1. Tohle platí, až na výjimky, obecně o všech vlajkách všech periferií. Přirozeně můžete mazat více vlajek najednou zápisem příslušné binární hodnoty do registru. Jak rychle reaguje procesor na externí událost, zmíním dále v textu. Bit INTF0 indikuje log. 1 detekci nastavené události na INT0, bit PCIF1 změnu na povolených pinech v rozsahu PCINT8PCINT11. Analogicky bit PCIF0 signalizuje log. 1, že nastala změna na povolených pinech z rozsahu PCINT0PCINT7.

Tab. 4: Popis registru GIFR – General Interrupt Flag Register

Pozice bitu Označení
7 – (nejvyšší váha) -
6 INTF0
5 PCIF1
4 PCIF0
3 -
2 -
1 -
0 – (nejnižší váha) -

Jistě si dovedete představit, že musí existovat způsob, jak si vybrat, na kterých pinech chceme PCINT sledovat. Pokud bychom ho sledovali na všech, tak by jakákoli změna jakéhokoli pinu z jakéhokoli důvodu měla za následek vyvolání přerušení. Takže byste například vysílali data z čipu ven, procesor by měnil hodnotu třeba na PA2 (což je PCINT2) a s každou změnou by mu přišlo přerušení, že na pinu došlo ke změně. To by bylo šílené. Abyste si mohli filtrovat, které piny chcete sledovat, slouží vám k tomu dva registry PCMSK1 a PCMSK0. Jejich obsah je přesně takový, jaký byste očekávali. Zapsáním log. 1 do příslušného bitu zapínáte sledování na příslušném pinu. Zapsáním log. 0 jej vypínáte.

Tab. 5: Popis registru PCMSK1 – Pin Change Mask Register 1

Pozice bitu Označení
7 – (nejvyšší váha) -
6 -
5 -
4 -
3 PCINT11
2 PCINT10
1 PCINT9
0 – (nejnižší váha) PCINT8

Tab. 5: Popis registru PCMSK0 – Pin Change Mask Register 0

Pozice bitu Označení
7 – (nejvyšší váha) PCINT7
6 PCINT6
5 PCINT5
4 PCINT4
3 PCINT3
2 PCINT2
1 PCINT1
0 – (nejnižší váha) PCINT0

Pro kompletní povolení externích přerušení na pinech PA2 a PA3 tedy potřebujete nastavit jedničky do bitů PCINT2 a PCINT3, dále musíte povolit přerušení bitem PCIE0. Obecně pak musíte mít ještě globálně povolená přerušení (pomocí fce sei()), ale to už byste měli znát. Všechna tři přerušení by měla být schopna probrat čip z režimu spánku. INT0 to dokáže, ale jen pokud je nastaveno jako detekce log.0.

V následujícím díle se podíváme na praktické ukázky použití externího přerušení INT0.

 
Autor: Michal Dudka

 

[1] ATMEL. 8-bit Microcontroller with 2K/4K/8K Bytes In-System Programmable Flash ATtiny24A ATtiny44A ATtiny84A.[online] citováno 24. července 2017. Dostupné na www: http://www.atmel.com/images/doc8183.pdf
Následující a předchozí příspěvek v kategorii:

 
Následující: Externí přerušení nejen s Attiny24 – 2. Díl Praktické ukázky s přerušením od INT0
Předchozí: Výměna hodnot dvou proměnných bez nutnosti využití třetí proměnné

 
Tajned facebook
 

Za případné chyby v textu, ve zdrojovém kódě, nebo ve schématickém zapojení se omlouváme.
AUTOŘI NEBEROU ŽÁDNOU ODPOVĚDNOST ZA PŘÍPADNÉ ÚJMY NA ZDRAVÍ ČI MAJETKU.