Documente Academic
Documente Profesional
Documente Cultură
Laborator 2
2. Întreruperile
2.1. Caracteristici generale
Scopul acestei lecții este familiarizarea studenților cu funcțiile de întreruperi externe ale
microcontrolerului.
Tratarea întreruperii are ca efect suspendarea firului normal de execuție al unui program și
lansarea în execuție a unei rutine de tratare a întreruperii (ISR: Interrupt Service Routine). Întreruperile
hardware au fost introduse pentru a se elimină buclele pe care un procesor ar trebui să le facă in
așteptarea unui eveniment de la un periferic. Folosind un sistem de întreruperi, perifericele pot
atenționa procesorul in momentul producerii unei întreruperi (IRQ: Interrupt request), acesta din urmă
fiind liber să-și ruleze programul normal în restul timpului și să își întrerupă execuția doar atunci când
este necesar. Înainte de a lansa în execuție o ISR, procesorul trebuie să aibă la dispoziție un mecanism
prin care să salveze starea în care se află în momentul apariției întreruperii. Aceasta se face prin
salvarea într-o memorie, de cele mai multe ori organizata sub forma unei stive, a registrului contor de
program (Program Counter), a registrelor de stare precum și a tuturor variabilelor din program care
sunt afectate de execuția ISR. La sfârșitul execuției ISR starea anterioară a registrelor este refăcută și
programul principal este reluat din punctul de unde a fost întrerupt.
Pentru a asocia o întrerupere cu o anumită rutină din program, procesorul folosește tabela
vectorilor de întrerupere. Fiecărei întreruperi îi este asociată o adresă la care programul va face salt în
cazul apariției acesteia. Aceste adrese sunt predefinite și sunt mapate in memoria de program într-un
spațiu continuu care alcătuiește tabela vectorilor de întrerupere. Adresele întreruperilor în tabela
vectorilor de întrerupere sunt setate în funcție de prioritatea lor, cu cât adresa este mai mică cu atât
prioritatea este mai mare. Pentru ATMega328, tabela vectorilor de întrerupere este dată în tabelul I.
2.2. Butonul
De cele mai multe ori o întrerupere externă este activată de un buton. Un buton simplu este format
din două contacte metalice care se ating sub acțiunea utilizatorului. Aceste contacte metalice închid
circuitul și transmit unei componente electronice (în cele mai multe cazuri un microcontroler) starea
butonului. La apăsarea butonului apare fenomenul denumit „contact imperfect” (bouncing). Acesta se
manifestă prin oscilații electrice în schemă, de perioadă variabilă și pentru o durată de timp depinzând
de o serie de factori, cum ar fi: imperfecțiunile și impuritățile de pe suprafețele de contact, timpii de
răspuns ai materialelor, modul de încapsulare, puterea pe care o poate suporta suprafața de contact
ş.a. Pentru butonul folosit în cadrul laboratorului, această durată este în general mai mică de 10 ms.
Numai după această perioadă contactul realizat este sigur.
Deoarece aceste contacte imperfecte pot produce modificări însemnate în funcționarea normală
a schemei în care apar, este necesară eliminarea lor (debouncing). Acest lucru se poate realiza prin
metode hardware sau software. Butoanele pot transmite nivel de tensiune diferit, făcând ca sistemul
să fie binar, ON sau OFF. Astfel, aceste niveluri de tensiune (de exemplu, 5 volți = ridicat = ON = circuit
închis și 0 volți = scăzut = dezactivat = circuit deschis) ne ajută să reprezentăm logica binară de 0 și 1.
În Fig. 1 este reprezentat un exemplu de acest tip de circuit. În urma fluctuațiilor apărute la apăsarea
butonului, microcontrolerul poate înregistra mai multe apăsări și, într-un final, mai multe semnale de
0 și 1 consecutiv. Acest fenomen poate introduce erori în sistem. Pentru a menține tensiunea de ieșire
la un nivel constant 1 și pentru a nu apărea un scurt circuit la apăsarea butonului, se conectează o
rezistență de Pullup conform Fig. 1.
Figura 1. Schema electrică de acționare a unui buton și reprezentarea semnalului apărut la apăsarea acestuia
În categoria soluțiilor hardware, printre cele mai simple se regăsesc introducerea unui filtru
RC sau a unui circuit bistabil (CBB) tip R-S sau D.
Filtrele sunt circuite utilizate la prelucrarea semnalelor, prin care pot trece doar semnalele de
anumite frecvențe, impuse. În Fig. 2 este reprezentată schema electrică a unui circuit ce are
implementat un filtru trece jos format dintr-o rezistență și un condensator (R-C), cu scopul de a elimina
frecvențele înalte ale semnalului ce pot apărea în urma apăsării butonului. Pragul de filtrare se
numește frecvența de tăiere (fc) și este calculată conform formulei:
1
=
2
Semnalele cu frecvențe până la frecvența de tăiere sunt lăsate să treacă neatenuate, sau atenuate
foarte puțin, iar pe cele cu frecvențe superioare frecvenței de tăiere le atenuează foarte puternic.
De asemenea, există numeroase circuite integrate dedicate disponibile pe piață special realizate
pentru eliminarea fluctuațiilor de semnal (de ex. circuitul Trigger Schmitt).
2.3. Întreruperile externe în limbaj Arduino
Placa de dezvoltare Arduino are disponibili 2 pini pentru întreruperi externe: pinul 2 (PD2) și pinul 3
(PD3). O variantă de schema electrică de conectare a unui buton la un pin de întreruperi a plăcii de
dezvoltare Arduino este prezentată în Fig. 3. Este implementat astfel circuitul de tip RC prezentat în
Fig. 2. Folosind o rezistență R=4.7kΩ si un condensator C=0.1µF, rezultă o frecvență de tăiere de
aproximativ 338Hz. Rezistența de Pullup poate fi aleasă de ordinul kΩ, de exemplu Rp= 4.7kΩ.
Butonul are o schemă electrică conform Fig. 4. La apăsare, pinii 1 și 2 sunt conectați cu pinii 3 și 4.
Din punct de vedere al sintaxei Arduino, cel mai uzual, întreruperile pot și activate folosind următoarea
funcție:
attachInterrupt(digitalPinToInterrupt(pin), ISR, mode);
cu următorii parametrii:
pin: numărul pinului care este folosit pentru întrerupere (pentru Arduino UNO este pinul 2
sau pinul 3);
ISR: Interrupt Service Routine – numele funcției apelate care în momentul în care apare
întreruperea (această funcție nu are parametrii și nu returnează nimic);
mode: definește modul de activare a întreruperii astfel:
LOW activează întreruperea când semnalul este 0 (low);
CHANGE activează întreruperea când semnalul de la pin își schimbă valoarea (din 1 în
0 sau din 0 în 1)
RISING activează întreruperea pe frontul crescător al semnalului (când semnalul pe la
pin se modifică din 0 în 1)
FALLING activează întreruperea pe frontul descrescător al semnalului (când semnalul
pe la pin se modifică din 0 în 1)
În exemplul de mai jos este activată o întrerupere folosind pinul 2 pe front crescător al
semnalului (la trecerea din 0 în 1). Funcția care se execută la activarea întreruperii poartă numele de
blink și schimbă valoarea parametrului stării LED-ului conectat la pinul 13.
void setup() {
pinMode(13, OUTPUT); //setare direcție pin 13 - ieșire
pinMode(2, INPUT_PULLUP); //setare direcție pin 2 – intrare cu activare rezistență de Pullup
void loop() {
digitalWrite(13, state); //setare stare pin 13
}
Exercițiul 1: Modificați circuitul astfel încât să își schimbe starea un LED conectat la pinul 13 atunci când
apare o întrerupere activată de un semnal cu front crescător.
Exercițiul 2: Modificați programul și circuitul astfel încât să își schimbe starea un LED conectat la pinul
10 atunci când apare o întrerupere activată de un semnal cu front descrescător.
În Fig. 5 este dat ca exemplu conectarea unui LED extern la pinul 13.
Pentru a activa posibilitatea de a folosi întreruperile este utilizat registrul Status (SREG) prin setarea
bitului 7 (Global Interrupt Enable - I) cu valoarea 1. Dezactivarea întreruperilor se realizează prin
setarea acestui bit cu valoarea 0.
Pentru modificarea unui singur bit dintr-un registru se aplică operații logice (“SAU” sau “SI”) cu măști
de biți care să afecteze doar acel bit, prin schimbarea lui în 1 sau în 0 (0b1000000, respectiv
0b01111111).
De exemplu, schimbarea stării doar a bitului I din registrul SREG se poate face aplicând operația SAU (
| ) pe bit cu o mască de biți care are doar bitul 7 cu valoarea 1. Astfel, în registrul SREG bitul I va lua
valoarea 1 (“SAU” cu 1 rezultă 1), restul rămânând nemodificați (“SAU” cu 0):
SREG |= 0b10000000;
Întreruperile sunt activate setând registrul External Interrupt Mask Register (EIMSK).
Când bitul INT1 din EIMSK si bitul I din registrul SREG sunt setați 1, este activat pinul de întrerupere
extern. De asemenea, similar se procedează si pentru întreruperea INT0. Activitatea pe pini va
provoca o solicitare de întrerupere chiar dacă INT1 sau INT0 sunt configurați ca ieșire. Setarea biților
se realizează prin operații logice cu măști de biți.
Modul în care se activează întreruperilor externe se face cu ajutorul registrul External Interrupt
Control Register A (EICRA) care are forma din Fig. 7.
De asemenea, întreruperea Externa 0 este activata de pinul extern INT0 daca fanionul I al registrului
SREG si masca de întrerupere corespunzătoare sunt setate. Nivelurile si fronturile pinului INT0 care
activează întreruperile sunt definite mai jos:
Daca o cerere de întrerupere este activata pe un pin, registrul External Interrupt Flag (EIFR)
se modifica: bitul INTF0 sau INTF1 devin 1, in funcție de pinul folosit. Daca bitul I din SREG si bitul
INT0 sau INT1 din EIMSK sunt setați 1, microcontrolerul va sari la vectorul de întrerupere
corespondent. Iar fanionul din EIFR va fi resetat.
switch (interruptNum) {
case 0:
EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
EIMSK |= (1 << INT0);
break;
case 1:
EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
EIMSK |= (1 << INT1);
break;
case 2:
break;
}
}
}
Se apelează practic regiștrii ce setează întreruperile. În exemplul de mai jos este implementat
programul de schimbare a stării LED-ului conectat la pinul 13 în urma activării pe front crescător a
întreruperii prin apăsarea butonului legat la pinul 2.
#include <avr/io.h>
#include <avr/interrupt.h>
void setup() {
DDRD &= 0b11111011; //Setare pin întreruperi PD2 ca pin de intrare ~(1 << DDD2);
PORTD |= 0b00000100; //Activare rezistență de Pull-up (1 << PORTD2)
void loop() {
PORTB = state; //implementarea schimbării stării LED-ului conectat la PB5
}
Exercițiu: Modificați programul astfel încât să își schimbe starea un LED conectat la pinul 10 atunci când
apare o întrerupere activată de un semnal pe front descrescător pe pinul 3 al plăcii de dezvoltare
Arduino.