Documente noi - cercetari, esee, comentariu, compunere, document
Documente categorii

Microcontroler - Intreruperi

Microcontroler -  Intreruperi

Intreruperile sunt un mecanism a unui microcontroler ce ii permit sa raspunda la unele evenimente la momentul cand se intampla, indiferent de ce face atunci microcontrolerul. Aceasta este o parte foarte importanta, pentru ca permite conexiunea microcontrolerului cu lumea de afara. In general, fiecare intrerupere schimba debitul programului, il intrerupe si dupa executarea unui subprogram (rutine de intrerupere), continua din acelasi punct.



Registrul de control al unei intreruperi se numeste INTCON si se gaseste la adresa 0Bh. Rolul lui este de a permite sau interzice cererile de intreruperi, si in caz ca nu sunt permise, inregistreaza cererile de intrerupere singulare prin bitii lui.

Registru INTCON

bit 0 RBIF (RB Port Change Interrupt Flag bit-bit Stegulet de Intrerupere a Schimbarii Portului RB) Bit ce informeaza despre schimbarile de la pinii 4, 5, 6 si 7 ai portului B.
1=cel putin un pin si-a schimbat starea
0=nu s-a intamplat nici o schimbare la vreun pin

bit 1 INTF (INT External Interrupt Flag bit-bit Stegulet de Intrerupere Externa INT) A avut loc o intrerupere externa.
1=a avut loc o intrerupere
0=nu a avut loc o intrerupere
Daca s-a detectat un front crescator sau descrescator la pinul RB0/INT, (ce este definit cu bitul INTEDG in registrul OPTION), bitul INTF este setat. Bitul trebuie sa fie sters in subprogramul intrerupere pentru a detecta urmatoarea intrerupere.

bit 2 T0IF (TMR0 Overflow Interrupt Flag bit-bit Stegulet Depasire Intrerupere TMRO) Depasirea contorului TMRO.
1=contorul si-a schimbat starea de la FFh la 00h.
0=depasirea nu a avut loc
Bitul trebuie sa fie sters in program pentru ca o intrerupere sa fie detectata.

bit 3 RBIE (RB port change Interrupt Enable bit-bit Permite Intreruperea schimbarii portului RB) Permite sa aiba loc intreruperi la schimbarea starii pinilor 4, 5, 6, si 7 ai portului B. 
1=permite intreruperi la schimbarea starii 
0=intreruperi interzise la schimbarea starii
Daca RBIE si RBIF au fost simultan setate, va avea loc o intrerupere.

bit 4 INTE (INT External Interrupt Enable bit-bit Permite Intrerupere externa INT) Bit ce permite intreruperea externa de la pinul RB0/INT.
1=intrerupere externa permisa
0=intrerupere externa interzisa
Daca INTE si INTF au fost setate simultan, va avea loc o intrerupere.

bit 5 T0IE (TMR0 Overflow Interrupt Enable bit-bit Permite Depasire Intrerupere TMRO) Bit ce permite intreruperile in timpul depasirii contorului TMRO.
1=intrerupere permisa
0=intrerupere interzisa
Daca T0IE si T0IF au fost simultan setate, va avea loc intreruperea.

Bit 6 EEIE (EEPROM Write Complete Interrupt Enable bit-bit Permite Intrerupere Completa a Scrierii EEPROM) Bit ce permite o intrerupere la sfarsitul unei rutine de scriere in EEPROM
1= intrerupere permisa
0= intrerupere interzisa
Daca EEIE si EEIF (ce este in registrul EECON1) au fost simultan setate, va avea loc o intrerupere.

Bit 7 GIE (Global Interrupt Enable bit-bit Permite Intrerupere Globala) Bit ce permite sau interzice toate intreruperile.
1=toate intreruperile sunt permise
0=toate intreruperile sunt interzise


PIC16F84 are patru surse de intrerupere:

1. Terminarea scrierii datelor in EEPROM
2. Intrerupere TMR0 cauzata de depasirea timer-ului
3. Intrerupere in timpul schimbarii la pinii RB4, RB5, RB6 si RB7 ai portului B.
4. Intrerupere Externa de la pinul RB0/INT al microcontrolerului

In general, fiecare sursa de intrerupere are doi biti legati la ea. Unul permite intreruperea, iar celalalt detecteaza cand au loc intreruperi. Exista un bit comun numit GIE ce poate fi folosit pentru a interzice sau permite toate intreruperile simultan. Acest bit este foarte folositor cand se scrie un program pentru ca permite ca toate intreruperile sa fie interzise pentru o perioada de timp, asa ca executia unei parti importante a programului sa nu fie intrerupta. Cand instructiunea ce reseteaza bitul GIE a fost executata (GIE=0, toate intreruperile interzise), fiecare intrerupere ce ramane nerezolvata trebuie ignorata.



Intreruperile ce raman nerezolvate si ce au fost ignorate, sunt procesate cand bitul GIE (GIE=1, toate intreruperile sunt permise) va fi sters. Cand i s-a raspuns intreruperii, bitul GIE a fost sters, asa ca orice intreruperi aditionale vor fi interzise, adresa de intoarcere a fost trimisa in stiva, iar adresa 0004h a fost scrisa in contorul programului - numai dupa aceasta incepe raspunsul la o intrerupere! Dupa ce este procesata intreruperea, bitul a carui setare a cauzat o intrerupere trebuie sters, sau rutina de intrerupere va fi procesata automat tot mereu in timpul intoarcerii la programul principal.

Pastrarea continutului registrilor importanti

Doar valoarea de intoarcere a contorului programului este inmagazinata intr-o stiva in timpul unei intreruperi (prin valoare de intoarcere a contorului programului intelegem adresa instructiunii ce trebuie executata, dar nu a fost executata pentru ca a avut loc intreruperea). Pastrand doar valoarea contorului programului adesea nu este suficient. Unii registri ce sunt in uz in programul principal pot fi de asemenea in uz in rutina de intrerupere. Daca ei nu sunt retinuti, programul principal va obtine valori complet diferite in acei registri in timpul intoarcerii dintr-o rutina de intrerupere, ceea ce va cauza erori in program. Un exemplu de asemenea caz este continutul registrului de lucru W. Daca presupunem ca programul principal a folosit registrul de lucru W pentru unele din operatiile sale, si ca a pastrat in el o valoare ce este importanta pentru urmatoarea instructiune, atunci o intrerupere ce se va intampla inainte de acea instructiune va schimba valoarea registrului de lucru W, ce va influenta direct programul principal.

Procedura de inregistrare de registri importanti inainte de a merge la o rutina de intrerupere se numeste PUSH, in timp ce procedura ce aduce valorile inregistrate inapoi, se numeste POP. PUSH si POP sunt instructiuni ale altor microcontrolere (Intel), dar sunt atat de larg acceptate ca o intreaga operatie este numita dupa ele. PIC16F84 nu are instructiuni ca PUSH si POP, si ele trebuie sa fie programate.



Datorita simplitatii si folosirii frecvente, aceste parti ale programului pot fi facute ca macro-uri. Conceptul unui Macro este explicat in 'Limbaj de asamblare program'. In urmatorul exemplu, continuturile registrilor W si STATUS sunt memorate in variabilele W_TEMP si STATUS_TEMP inainte de rutina de intrerupere. La inceputul rutinei PUSH trebuie sa verificam bancul selectat in prezent pentru ca W_TEMP and STATUS_TEMP nu se gasesc in bancul 0. Pentru schimbul de date intre acesti registri, instructiunea SWAPF se foloseste in loc de MOVF pentru ca nu afecteaza starea bitilor registrului STATUS.

Exemplul este un program asamblor pentru urmatorii pasi :
1. Testarea bancului curent 
2. Stocarea registrului W indiferent de bancul curent
3. Stocarea registrul STATUS in bancul 0
4. Executarea rutinei de intrerupere pentru procesul de intrerupere (ISR)
5. Restaureaza registrul STATUS
6. Restaureaza registrul W

Daca mai sunt si alte variabile sau registri ce trebuie stocati, atunci ei trebuie sa fie pastrati dupa stocarea registrului STATUS (pasul 3), si adusi inapoi inainte ca registrul STATUS sa fie restaurat (pasul 5).

Acelasi exemplu se poate realiza utilizand macro-uri, facand astfel programul mai eligibil. Macro-urile ce sunt deja definite, pot fi folosite pentru scrierea de noi macro-uri. Macro-urile BANK1 si BANK0 ce sunt explicate in capitolul 'Organizarea memoriei' sunt folosite cu macro-urile 'push' si 'pop'.

Intrerupere externa la pinul RB0/INT al microcontrolerului

Intreruperea externa la pinul RB0/INT este triggerata de frontul crescator (daca bitul INTEDG=1 in registrul OPTION<6>), sau de frontul descrescator (daca INTEDG=0). Cand apare semnalul corect la pinul INT, bitul INTF este setat la registrul INTCON. Bitul INTF (INTCON<1>) trebuie resetat in rutina de intrerupere, asa ca intreruperea sa nu aiba loc din nou in timpul intoarcerii la programul principal. Acesta este un pas important al programului pe care programatorul nu trebuie sa-l uite, sau programul va merge constant in rutina de intrerupere. Intreruperea poate fi inchisa prin resetarea bitului de control INTE (INTCON<4>).

Intreruperea in timpul depasirii contorului TMRO

Depasirea contorului TMRO (de la FFh la 00h) va seta bitul T0IF (INTCON<2>). Aceasta este o intrerupere foarte importanta pentru ca multe probleme reale se por rezolva folosind aceasta intrerupere. Unul din exemple este masurarea timpului. Daca stim cat timp are nevoie contorul pentru a completa un ciclu de la 00h to FFh, atunci numarul de intreruperi inmultit cu acea durata de timp va da timpul total scurs. In rutina de intrerupere unele variabile vor fi incrementate in memoria RAM, valoarea acelei variabile inmultite cu timpul de care are nevoie contorul pentru a contoriza intr-un ciclu intreg, va da timpul total scurs. Intreruperea poate fi pornita/oprita prin setarea/resetarea bitului T0IE (INTCON<5>). 

Intrerupere pe timpul unei schimbari la pinii  4, 5, 6 si 7 ai portului B

Schimbarea semnalului de intrare la PORTB <7:4> seteaza bitul RBIF (INTCON<0>). Patru pini RB7, RB6, RB5 si RB4 ai portului B, pot triggera o intrerupere ce are loc cand starea la ei se schimba de la unu la zero logic, sau viceversa. Pentru ca pinii sa fie sensibili la aceasta schimbare, trebuie definiti ca intrare. Daca oricare din ei este definit ca iesire, intreruperea nu va fi generata la schimbarea starii. Daca ei sunt definiti ca intrare, starea lor curenta este comparata cu vechea valoare ce a fost stocata la ultima citire de la portul B. Intreruperea poate fi pornita/oprita prin setarea/resetarea bitului RBIE in registrul INTCON.

Intreruperea la terminarea subrutinei write in EEPROM

Aceasta intrerupere este doar de natura practica. Pentru ca scrierea intr-o locatie EEPROM dureaza cam 10ms (care este o durata lunga in termenii microcontrolerului), nu este rentabil de a astepta pana la capat scrierea. Este adaugat astfel mecanismul de intrerupere ceea ce permite microcontrolerului sa continue executarea programului principal, in timp ce scrierea in EEPROM este facuta in plan secundar. Cand scrierea este terminata, intreruperea informeaza microcontrolerul ca scrierea s-a terminat. Bitul EEIF, prin care se face aceasta informare, se gaseste in registrul EECON1. Producerea unei intreruperi poate fi interzisa prin resetarea bitului EEIE in registrul INTCON. 

Initializarea intreruperii

Pentru a folosi un mecanism de intrerupere a unui microcontroler, trebuie facute unele sarcini pregatitoare. Aceste proceduri sunt pe scurt numite 'initializare'. Prin initializare definim la ce va raspunde microcontrolerul, si ce va ignora. Daca nu setam bitul ce permite o anumita intrerupere, programul nu va executa un subprogram intrerupere. Prin aceasta putem obtine controlul asupra producerii intreruperii, ceea ce este foarte folositor.



Exemplul de mai sus arata initializarea unei intreruperi externe la pinul RB0 al microcontrolerului. Unde se vede unu setat, inseamna ca intreruperea este permisa. Producerea altor intreruperi nu este permisa, si toate intreruperile impreuna sunt interzise pana ce bitul GIE este tinut in unu.

Urmatorul exemplu arata o cale tipica de a dirija intreruperile. PIC16F84 are doar o locatie unde adresa unui subprogram intrerupere este memorata. Aceasta inseamna ca mai intai trebuie sa detectam ce intrerupere este la indemana (daca mai mult de o sursa de intreruperi este disponibila), si apoi putem executa acea parte a programului ce se refera la acea intrerupere.