Microcontrolere PIC on-line GRATIS!

 
 
 
   
Pagina anterioară Conţinut Pagina următoare

 

2.6 Întreruperi

Întreruperile sunt un mecanism a unui microcontroler ce îi permit să răspundă la unele evenimente la momentul când se întâmplă, indiferent de ce face atunci microcontrolerul. Aceasta este o parte foarte importantă, pentru că permite conexiunea microcontrolerului cu lumea de afară. În general, fiecare întrerupere schimbă debitul programului, îl întrerupe şi după executarea unui subprogram (rutine de întrerupere), continuă din acelaşi punct.

Registrul de control al unei întreruperi se numeşte INTCON şi se găseşte la adresa 0Bh. Rolul lui este de a permite sau interzice cererile de întreruperi, şi în caz că nu sunt permise, înregistrează cererile de întrerupere singulare prin biţii lui.

Registru INTCON

bit 0 RBIF (RB Port Change Interrupt Flag bit-bit Steguleţ de Întrerupere a Schimbării Portului RB) Bit ce informează despre schimbările de la pinii 4, 5, 6 şi 7 ai portului B.
1=cel puţin un pin şi-a schimbat starea
0=nu s-a întâmplat nici o schimbare la vreun pin

bit 1 INTF (INT External Interrupt Flag bit-bit Steguleţ de Întrerupere Externă INT) A avut loc o întrerupere externă.
1=a avut loc o întrerupere
0=nu a avut loc o întrerupere
Dacă s-a detectat un front crescător sau descrescător la pinul RB0/INT, (ce este definit cu bitul INTEDG în registrul OPTION), bitul INTF este setat. Bitul trebuie să fie şters în subprogramul întrerupere pentru a detecta următoarea întrerupere.

bit 2 T0IF (TMR0 Overflow Interrupt Flag bit-bit Steguleţ Depăşire Întrerupere TMRO) Depăşirea contorului TMRO.
1=contorul şi-a schimbat starea de la FFh la 00h.
0=depăşirea nu a avut loc
Bitul trebuie să fie şters în program pentru ca o întrerupere să fie detectată.

bit 3 RBIE (RB port change Interrupt Enable bit-bit Permite Întreruperea schimbării portului RB) Permite să aibă loc întreruperi la schimbarea stării pinilor 4, 5, 6, şi 7 ai portului B. 
1=permite întreruperi la schimbarea stării 
0=întreruperi interzise la schimbarea stării
Dacă RBIE şi RBIF au fost simultan setate, va avea loc o întrerupere.

bit 4 INTE (INT External Interrupt Enable bit-bit Permite Întrerupere externă INT) Bit ce permite întreruperea externă de la pinul RB0/INT.
1=întrerupere externă permisă
0=întrerupere externă interzisă
Dacă INTE şi INTF au fost setate simultan, va avea loc o întrerupere.

bit 5 T0IE (TMR0 Overflow Interrupt Enable bit-bit Permite Depăşire Întrerupere TMRO) Bit ce permite întreruperile în timpul depăşirii contorului TMRO.
1=întrerupere permisă
0=întrerupere interzisă
Dacă T0IE şi T0IF au fost simultan setate, va avea loc întreruperea.

Bit 6 EEIE (EEPROM Write Complete Interrupt Enable bit-bit Permite Întrerupere Completă a Scrierii EEPROM) Bit ce permite o întrerupere la sfârşitul unei rutine de scriere în EEPROM
1= întrerupere permisă
0= întrerupere interzisă
Dacă EEIE şi EEIF (ce este în registrul EECON1) au fost simultan setate, va avea loc o întrerupere.

Bit 7 GIE (Global Interrupt Enable bit-bit Permite Întrerupere Globală) Bit ce permite sau interzice toate întreruperile.
1=toate întreruperile sunt permise
0=toate întreruperile sunt interzise


PIC16F84 are patru surse de întrerupere:

1. Terminarea scrierii datelor în EEPROM
2. Întrerupere TMR0 cauzată de depăşirea timer-ului
3. Întrerupere în timpul schimbării la pinii RB4, RB5, RB6 şi RB7 ai portului B.
4. Întrerupere Externă de la pinul RB0/INT al microcontrolerului

În general, fiecare sursă de întrerupere are doi biţi legaţi la ea. Unul permite întreruperea, iar celălalt detectează când au loc întreruperi. Există un bit comun numit GIE ce poate fi folosit pentru a interzice sau permite toate întreruperile simultan. Acest bit este foarte folositor când se scrie un program pentru că permite ca toate întreruperile să fie interzise pentru o perioadă de timp, aşa ca execuţia unei părţi importante a programului să nu fie întreruptă. Când instrucţiunea ce resetează bitul GIE a fost executată (GIE=0, toate întreruperile interzise), fiecare întrerupere ce rămâne nerezolvată trebuie ignorată.

Întreruperile ce rămân nerezolvate şi ce au fost ignorate, sunt procesate când bitul GIE (GIE=1, toate întreruperile sunt permise) va fi şters. Când i s-a răspuns întreruperii, bitul GIE a fost şters, aşa că orice întreruperi adiţionale vor fi interzise, adresa de întoarcere a fost trimisă în stivă, iar adresa 0004h a fost scrisă în contorul programului – numai după aceasta începe răspunsul la o întrerupere! După ce este procesată întreruperea, bitul a cărui setare a cauzat o întrerupere trebuie şters, sau rutina de întrerupere va fi procesată automat tot mereu în timpul întoarcerii la programul principal.

Păstrarea conţinutului regiştrilor importanţi

Doar valoarea de întoarcere a contorului programului este înmagazinată într-o stivă în timpul unei întreruperi (prin valoare de întoarcere a contorului programului înţelegem adresa instrucţiunii ce trebuie executată, dar nu a fost executată pentru că a avut loc întreruperea). Păstrând doar valoarea contorului programului adesea nu este suficient. Unii regiştri ce sunt în uz în programul principal pot fi de asemenea în uz în rutina de întrerupere. Dacă ei nu sunt reţinuţi, programul principal va obţine valori complet diferite în acei regiştri în timpul întoarcerii dintr-o rutină de întrerupere, ceea ce va cauza erori în program. Un exemplu de asemenea caz este conţinutul registrului de lucru W. Dacă presupunem că programul principal a folosit registrul de lucru W pentru unele din operaţiile sale, şi că a păstrat în el o valoare ce este importantă pentru următoarea instrucţiune, atunci o întrerupere ce se va întâmpla înainte de acea instrucţiune va schimba valoarea registrului de lucru W, ce va influenţa direct programul principal.

Procedura de înregistrare de regiştri importanţi înainte de a merge la o rutină de întrerupere se numeşte PUSH, în timp ce procedura ce aduce valorile înregistrate înapoi, se numeşte POP. PUSH şi POP sunt instrucţiuni ale altor microcontrolere (Intel), dar sunt atât de larg acceptate că o întreagă operaţie este numită după ele. PIC16F84 nu are instrucţiuni ca PUSH şi POP, şi ele trebuie să fie programate.

Datorită simplităţii şi folosirii frecvente, aceste părţi ale programului pot fi făcute ca macro-uri. Conceptul unui Macro este explicat în "Limbaj de asamblare program". În următorul exemplu, conţinuturile regiştrilor W şi STATUS sunt memorate în variabilele W_TEMP şi STATUS_TEMP înainte de rutina de întrerupere. La începutul rutinei PUSH trebuie să verificăm bancul selectat în prezent pentru că W_TEMP and STATUS_TEMP nu se găsesc în bancul 0. Pentru schimbul de date între aceşti regiştri, instrucţiunea SWAPF se foloseşte în loc de MOVF pentru că nu afectează starea biţilor registrului STATUS.

Exemplul este un program asamblor pentru următorii paşi :
1. Testarea bancului curent 
2. Stocarea registrului W indiferent de bancul curent
3. Stocarea registrul STATUS în bancul 0
4. Executarea rutinei de întrerupere pentru procesul de întrerupere (ISR)
5. Restaurează registrul STATUS
6. Restaurează registrul W

Dacă mai sunt şi alte variabile sau regiştri ce trebuie stocaţi, atunci ei trebuie să fie păstraţi după stocarea registrului STATUS (pasul 3), şi aduşi înapoi înainte ca registrul STATUS să fie restaurat (pasul 5).

Acelaşi exemplu se poate realiza utilizând macro-uri, făcând astfel programul mai eligibil. Macro-urile ce sunt deja definite, pot fi folosite pentru scrierea de noi macro-uri. Macro-urile BANK1 şi BANK0 ce sunt explicate în capitolul "Organizarea memoriei" sunt folosite cu macro-urile 'push' şi 'pop'.

Întrerupere externă la pinul RB0/INT al microcontrolerului  

Întreruperea externă la pinul RB0/INT este triggerată de frontul crescător (dacă bitul INTEDG=1 în registrul OPTION<6>), sau de frontul descrescător (dacă INTEDG=0). Când apare semnalul corect la pinul INT, bitul INTF este setat la registrul INTCON. Bitul INTF (INTCON<1>) trebuie resetat în rutina de întrerupere, aşa ca întreruperea să nu aibă loc din nou în timpul întoarcerii la programul principal. Acesta este un pas important al programului pe care programatorul nu trebuie să-l uite, sau programul va merge constant în rutina de întrerupere. Întreruperea poate fi închisă prin resetarea bitului de control INTE (INTCON<4>).

Întreruperea în timpul depăşirii contorului TMRO  

Depăşirea contorului TMRO (de la FFh la 00h) va seta bitul T0IF (INTCON<2>). Aceasta este o întrerupere foarte importantă pentru că multe probleme reale se por rezolva folosind această întrerupere. Unul din exemple este măsurarea timpului. Dacă ştim cât timp are nevoie contorul pentru a completa un ciclu de la 00h to FFh, atunci numărul de întreruperi înmulţit cu acea durată de timp va da timpul total scurs. În rutina de întrerupere unele variabile vor fi incrementate în memoria RAM, valoarea acelei variabile înmulţite cu timpul de care are nevoie contorul pentru a contoriza într-un ciclu întreg, va da timpul total scurs. Întreruperea poate fi pornită/oprită prin setarea/resetarea bitului T0IE (INTCON<5>). 

Întrerupere pe timpul unei schimbări la pinii  4, 5, 6 şi 7 ai portului B

Schimbarea semnalului de intrare la PORTB <7:4> setează bitul RBIF (INTCON<0>). Patru pini RB7, RB6, RB5 şi RB4 ai portului B, pot triggera o întrerupere ce are loc când starea la ei se schimbă de la unu la zero logic, sau viceversa. Pentru ca pinii să fie sensibili la această schimbare, trebuie definiţi ca intrare. Dacă oricare din ei este definit ca ieşire, întreruperea nu va fi generată la schimbarea stării. Dacă ei sunt definiţi ca intrare, starea lor curentă este comparată cu vechea valoare ce a fost stocată la ultima citire de la portul B. Întreruperea poate fi pornită/oprită prin setarea/resetarea bitului RBIE în registrul INTCON.

Întreruperea la terminarea subrutinei write în EEPROM

Această întrerupere este doar de natură practică. Pentru că scrierea într-o locaţie EEPROM durează cam 10ms (care este o durată lungă în termenii microcontrolerului), nu este rentabil de a aştepta până la capăt scrierea. Este adăugat astfel mecanismul de întrerupere ceea ce permite microcontrolerului să continue executarea programului principal, în timp ce scrierea în EEPROM este făcută în plan secundar. Când scrierea este terminată, întreruperea informează microcontrolerul că scrierea s-a terminat. Bitul EEIF, prin care se face această informare, se găseşte în registrul EECON1. Producerea unei întreruperi poate fi interzisă prin resetarea bitului EEIE în registrul INTCON. 

Iniţializarea întreruperii  

Pentru a folosi un mecanism de întrerupere a unui microcontroler, trebuie făcute unele sarcini pregătitoare. Aceste proceduri sunt pe scurt numite "iniţializare". Prin iniţializare definim la ce va răspunde microcontrolerul, şi ce va ignora. Dacă nu setăm bitul ce permite o anumită întrerupere, programul nu va executa un subprogram întrerupere. Prin aceasta putem obţine controlul asupra producerii întreruperii, ceea ce este foarte folositor.

Exemplul de mai sus arată iniţializarea unei întreruperi externe la pinul RB0 al microcontrolerului. Unde se vede unu setat, înseamnă că întreruperea este permisă. Producerea altor întreruperi nu este permisă, şi toate întreruperile împreună sunt interzise până ce bitul GIE este ţinut în unu.

Următorul exemplu arată o cale tipică de a dirija întreruperile. PIC16F84 are doar o locaţie unde adresa unui subprogram întrerupere este memorată. Aceasta înseamnă că mai întâi trebuie să detectăm ce întrerupere este la îndemână (dacă mai mult de o sursă de întreruperi este disponibilă), şi apoi putem executa acea parte a programului ce se referă la acea întrerupere.

Reîntoarcerea dintr-o rutină de întrerupere poate fi făcută cu instrucţiunile RETURN, RETLW şi RETFIE. Se recomandă ca să fie utilizată instrucţiunea RETFIE pentru că acea instrucţiune este singura ce setează automat bitul GIE, ceea ce permite să se producă o nouă întrerupere.

 

Pagina anterioară Conţinut Pagina următoare
 

© Copyright 2003. mikroElektronika. All Rights Reserved. For any comments contact webmaster.