Întreruperea controlerului AVR din Atmel AVR Studio. Întreruperi - Studierea AVR - Catalog de articole - Microcontrolere - este ușor! În ce mediu să programați întreruperile microcontrolerului

Sistemele de întrerupere sunt o parte importantă a oricărui sistem de control.

Cât de eficient își îndeplinește funcțiile sistemul cu microprocesor depinde în mare măsură de funcționarea acestuia. Structura generală a sistemului de întrerupere MK-51 este prezentată în Fig. 14.3.

Microcontrolerele din familia MK-51 oferă suport pentru cinci surse de întrerupere:

* două întreruperi externe care sosesc prin intrările INT0 și INT1 (liniile de port P3: P3.2 și respectiv P3.3);

* doua intreruperi de la temporizatoare/contoare T/C0 si T/C1;

* întreruperea portului serial.

Cererile de întrerupere sunt înregistrate în registrele de funcții speciale ale microcontrolerului: steagurile IE0, IE1, TF0, TF1 cererile de întrerupere de la INT0, INT1, T/C0 și T/C1 sunt conținute în registrul de control TCON (Tabelul 14.4), iar steagurile RI iar TI solicită o întrerupere de la portul serial - în registrul SCON pentru controlul portului serial.

Tabelul 14.4. Format de registru TCON

0 IT0 Setarea tipului de întrerupere INT0

1 IE0 Indicatorul cererii de întrerupere INT0

2 IT1 Setarea tipului de întrerupere INT1

3 IE1 Indicatorul cererii de întrerupere INT1

4 TR0 Activare cronometru/contor 0

5 TF0 Indicator de depășire (cerere de întrerupere) temporizator/contor 0

6 TR1 Activare cronometru/contor 1

7 TF1 Flag Overflow (cerere de întrerupere) a temporizatorului/contorului 1

Flag-urile TF0 și TF1 sunt setate de hardware atunci când cronometrul/contorul corespunzător depășește (mai precis, când T/Cx trece de la starea „toate cele” la starea „toate zerourile”).

Flag-urile IE0 și IE1 sunt setate de hardware de la întreruperile externe IT0 și, respectiv, IT1. O solicitare externă poate determina setarea indicatorului fie atunci când nivelul semnalului la intrarea corespunzătoare este scăzut, fie când acest semnal trece de la nivelul înalt la nivelul scăzut (cu o frecvență care nu depășește jumătate din frecvența ceasului extern a MK).

Tipul de solicitare este configurat prin setarea software-ului pentru biții IT0 și IT1 în registrul de control TCON. Setarea ITx = 0 configurează sistemul de întrerupere să solicite un nivel scăzut de semnal, ITx = 1 - setează întreruperea să solicite un nivel scăzut de semnal.

Flag-urile TI și RI sunt setate de hardware-ul interfeței seriale după încheierea transmisiei sau, respectiv, după încheierea recepției.

Toate indicatoarele de solicitare de întrerupere specificate sunt disponibile programatic pentru setare și resetare. Setarea semnalului de cerere de întrerupere în software are ca rezultat același răspuns din partea microcontrolerului ca și setarea aceluiași steag în hardware.

Flag-urile TF0 și TF1 sunt resetate de hardware atunci când controlul este transferat la rutina de întrerupere corespunzătoare.

Resetarea semnalizatoarelor IEx este efectuată în hardware atunci când întrerupeți întreruperea, numai dacă întreruperea a fost configurată pentru a detecta căderea semnalului INTx. Dacă întreruperea a fost configurată pentru a detecta nivelul semnalului de solicitare, atunci resetarea semnalizatorului IEx trebuie efectuată de programul de serviciu de întrerupere, acționând asupra sursei de întrerupere pentru a elimina cererea.

Indicatoarele TI și RI pot fi resetate numai prin software.

Fiecare tip de întrerupere este activat sau dezactivat individual prin setarea sau ștergerea biților corespunzători din registrul de activare a întreruperii IE. Acest registru conține, de asemenea, un bit de dezactivare generală pentru toate întreruperile. Formatul registrului IE este dat în tabel. 14.5.

Tabelul 14.5. Atribuirea biților de registru IE

Inregistreaza pozitia

Bit mnemonice

Funcţie

Dezactivați întreruperile din toate sursele

Nefolosit

Nefolosit

Dezactivați întreruperea de la port serial

Dezactivați cronometrul T/C1/întreruperea contorului

Dezactivați întreruperea de la sursă externă INT1

Dezactivați Timer/Counter Interrupt T/C0

Dezactivați întreruperea de la sursa externă INT0

Fiecărui tip de întrerupere i se poate atribui programatic una dintre cele două priorități posibile: 0 - cea mai mică sau 1 - cea mai mare.

Prioritățile sunt configurate prin setarea sau ștergerea bitului corespunzător din registrul de priorități de întrerupere IP. Formatul acestui registru este dat în tabel. 14.6.

Când solicitările de întrerupere sunt primite simultan de la surse care au priorități diferite, cererea de la sursa cu prioritate mai mare este procesată mai întâi.

În cazul primirii simultane a mai multor cereri de întrerupere cu aceeași prioritate, ordinea procesării acestora este determinată de hardware-ul microcontrolerului și nu poate fi modificată prin software. Această ordine corespunde secvenței de steaguri de solicitare de întrerupere a interogării, care arată astfel:

IT0 -> TF0 -> IT1 -> TF1 -> (RI, TI)

Tabelul 14.6. Atribuții de biți de registru IP

Poziția de înregistrare Bit mnemonic Funcție

7 - Nu este folosit

6 - Nu este folosit

5 - Nu este folosit

4 PS Prioritate de întrerupere a portului serial

3 PT1 Timer/Counter Interrupt Priority T/C1

2 PX1 Prioritate întrerupere de la sursa externă INT1

1 PT0 Timer/Counter Interrupt Priority T/C0

0 PX0 Prioritate întrerupere de la sursa externă INT0

Un apel de gestionare a întreruperilor implementat de hardware constă din următoarele acțiuni:

* salvarea valorii contorului programului pe stivă;

Punctele de intrare pentru gestionarea întreruperilor pentru fiecare sursă de întrerupere sunt fixate în hardware. Valorile lor sunt date în tabel. 14.7.

Tabelul 14.7. Adresele punctelor de intrare pentru manipulatorii de întreruperi

Sursa de întrerupere

Adresele punctelor de intrare pentru manipulatorii de întreruperi

întrerupere externă ( ITO)

Timer-counter (TFO)

Întreruperea externă (IT1)

Timer-counter (TF1)

Port serial (R1 sau T1)

Prima comandă a operatorului de întrerupere ar trebui să fie localizată la adresa specificată. De regulă, o astfel de comandă este o comandă pentru a sări necondiționat la locul din program în care se află de fapt handlerul.

La trecerea la rutina de gestionare a întreruperilor, automat, indiferent de starea registrului IE, toate întreruperile care au un nivel de prioritate egal cu nivelul de prioritate al întreruperii deservite sunt dezactivate - adică întreruperile imbricate cu un nivel de prioritate egal sunt dezactivate . Astfel, o întrerupere cu prioritate scăzută (având un „0” în bitul corespunzător al registrului IP) poate fi întreruptă de o întrerupere cu prioritate mare (având un „1” în bitul corespunzător al registrului IP), dar nu un unul cu prioritate scăzută. Deservirea unei întreruperi cu prioritate ridicată nu poate fi întreruptă de o altă sursă.

Revenirea de la manipulatorul de întreruperi se realizează folosind instrucțiunea RETI, care restabilește din stivă valoarea contorului programului PC stocat acolo în momentul în care a fost apelat gestionarea întreruperilor și logica priorității întreruperii.


Să vorbim despre întreruperi. Cuvântul întrerupere vorbește de la sine; un proces este oprit de ceva timp pentru a efectua acțiuni suplimentare. Întreruperile pot fi externe sau interne. Permiteți-mi să vă dau un exemplu simplu pe care l-am auzit de la prietenul meu...

S-a pregătit să spele vasele în bucătărie, a început cu entuziasm, suflecându-și mânecile... dar vasele s-au dovedit a fi grase și a fost nevoit să facă o pauză pentru a găsi un detergent pentru spălarea vaselor grase pe unul dintre rafturile de la unitatea de bucătărie, după care și-a continuat din nou sarcina. Dar la un moment dat, telefonul a sunat, iar el s-a oprit din nou de la serviciu, a ridicat telefonul, soacra lui a sunat și i-a spus că vine în vizită, așa că a trebuit să meargă la magazin să cumpere alimente înainte ca ea. sosit. Am fost la magazin și abia apoi am spălat vasele.

Acest exemplu prezintă două tipuri de întreruperi, primul este asociat cu execuția lucrării principale - căutarea detergentului pentru vase grase - o întrerupere internă, al doilea - apel telefonic– întrerupere externă.
Într-un microcontroler, întreruperile externe apar din cauza semnalelor care provin din alte surse, întreruperile interne apar din cauza dispozitivelor încorporate în microcontroler însuși. De ce sunt întreruperile atât de atractive?
Primul este că putem opri procesul principal pentru a îndeplini o altă funcție și apoi continuăm acest proces.
Al doilea, și probabil în multe cazuri principalul, este considerat a fi accelerarea procesului de îndeplinire a tuturor funcțiilor, datorită dispozitive suplimentare. Să revenim la exemplul nostru. Să presupunem că prietenul meu a început să spele vasele când soția sa ajunsese deja acasă. Văzând vasele grase, el îi cere să găsească lichid de spălat vase, iar în timp ce el spală, ea îi va aduce deja acest lichid. Dar apoi a sunat telefonul, soția mea a ridicat telefonul, a vorbit cu mama ei și s-a dus la magazin. Împreună, totul s-a făcut foarte repede!
Și este și mai ușor să rămâneți blocat - de exemplu. nu există program principal.
Prietenul meu stă pe canapea și nu face nimic, menajera vede vasele murdare, îi spune despre asta și, după ce a primit permisiunea, începe să se spele. Când sună telefonul îi spune soției să ridice telefonul, soția vorbește la telefon, iar conversația se duce la băcănie... Frumusețe! În acest caz, în microcontroler funcționează simultan mai multe dispozitive I/O (în microcontrolerele moderne pot fi destul de multe), iar performanța generală a procesorului crește de multe ori, dar întreruperile de la dispozitive sunt procesate secvenţial una după alta (nu simultan. ), în funcție de prioritate ( în exemplul nostru, soția are prioritate mai mare decât menajera).

Mai multe registre sunt responsabile pentru gestionarea întreruperilor
SREG – registru de stare(stare). Ne uităm la tabelul dispozitivelor de intrare/ieșire. Al șaptelea bit al registrului SREG este indicatorul I (întrerupere), care se numește indicatorul de activare a întreruperii globale. Dacă indicatorul este omis (al șaptelea bit este zero), atunci toate întreruperile sunt dezactivate. Dacă steagul este ridicat (setat I la 1), activăm întreruperile.

Steagul I este setat și resetat cu comenzile:
SEI - activați întreruperi
CLI - dezactivați întreruperile
Ce întreruperi vor funcționa este setat folosind registre numite - măști de întrerupere.
Măștile de întrerupere sunt desemnate după cum urmează:
TIMSK,..,..,.. – gestionarea întreruperilor de la temporizatoare și alte dispozitive încorporate.
GIMSK (GIKR în familia Mega) - gestionarea tuturor întreruperilor externe.
Măștile de întrerupere depind la rândul lor de steaguri de întrerupere:
TIFR și respectiv GIFR(a nu se confunda cu indicatorul de activare a întreruperii globale).

Întreruperea secvenței de execuție:
Când microcontrolerul este pornit, toate steagurile de întrerupere sunt resetate la 0. Pentru a activa întreruperile, programul trebuie să seteze flag I al registrului SREG la 1. După aceasta, înregistrați registrele de mască cu întreruperile locale setate (întreruperile de care avem nevoie) .
Când sosește o cerere de întrerupere (semnal), aceasta ridică flag-ul de întrerupere (chiar dacă întreruperea este dezactivată, pentru a organiza întreruperi imbricate și prioritate între diferite întreruperi). Dacă întreruperile nu sunt dezactivate, controlerul va contacta persoana corespunzătoare (Vectorii de întrerupere) - vector de întrerupere, întrerupând programul curent.
Vector de întrerupere este o linie fixă ​​în zona programului unde merge programul atunci când apare o întrerupere.
Se numește întreaga listă de vectori de întrerupere tabel de vectori de întrerupere, care se află la începutul codului programului.
Deci, în momentul în care se accesează vectorul de întrerupere, flag-ul I al registrului SREG și flag-ul care a provocat întrerupere sunt resetate la 0, dezactivând alte întreruperi. Dacă apar alte solicitări de întrerupere în timp ce întreruperea este în execuție, steagurile pentru acele întreruperi rămân ridicate. La finalizarea întreruperii curente, steag-ul I al registrului SREG este ridicat, permițând executarea următorului. Dacă sosesc mai multe cereri și sunt ridicate steaguri, atunci întreruperea al cărei vector este mai mic la adresa din tabel, mai aproape de începutul memoriei, va fi executată mai întâi. Urmează al doilea și așa mai departe. În plus, programatorul poate organiza o așa-numită întrerupere imbricată, atunci când apare o altă întrerupere în timpul execuției programului de întrerupere. Apoi se oprește execuția întreruperii curente și se execută una nouă, după care se reia execuția întreruperii oprite.

Ca exemplu, este dat tabelul vectorilor de întrerupere pentru ATtiny2313

Tabelul vector de întrerupere pentru Atmega16 este următorul:

Comparate, tabelele nu se potrivesc deloc.
În familia ATtiny, linia vectorului de întrerupere ocupă 16 biți, iar în familia Mega are nevoie de 32 de biți (atenție la adresele vectorilor de întrerupere; permiteți-mi să vă reamintesc că linia de adresă din zona programului este reprezentată de un 16 -bit cuvânt).

Codul de program pentru ATtiny2313 poate arăta astfel:
.cseg .org 0 rjmp Resetare rjmp INT_0 rjmp INT_1 rjmp Timer1_capt1 rjmp Timer1_comp1 rjmp Timer1_OVF1 rjmp Timer0_OVF0 rjmp UART_RX rjmp UART_UDART_PCrjmp rjmp Timer1_comp1 rjmp Timer1_OVF1 _compB rjmp Timer0_compA rj mp Timer0_compB rjmp USI_START rjmp USI_OVERFLOW rjmp EE_READY rjmp WDT_ OVERFLOW

După cum puteți vedea, vectorul de întrerupere creează un salt relativ la etichetele programului de întrerupere. Tabelul de mai jos prezintă opțiunile; 1. Când nu există întreruperi; 2, 3. cu întrerupere externă la intrarea INT_1.
Dacă etichetele sunt „goale” (nu există niciun program sub etichetă), atunci nu se întâmplă nimic, iar programul „parcurge” secvențial etichetele rămase și ajunge în siguranță la comandă RETI- Retur de întrerupere - ieșire din gestionarea întreruperii așa cum se arată în prima coloană a tabelului.

Pentru a executa un program de întrerupere, de exemplu, la intrarea INT_1, trebuie să eliminați eticheta INT_1: din listă. Acest lucru este prezentat schematic în a doua coloană a tabelului.
Dar, este incomod pentru programator să scrie toate întreruperile și etichete separate pentru ele de fiecare dată, în special în cele mai recente modele, unde tabelul este destul de mare; este mai ușor să scrieți imediat comanda RETI în linia vectorului de întrerupere dacă întreruperea nu este utilizată. Apoi programul va arăta așa cum se arată în a treia coloană a tabelului.

Controlerele AVR, în funcție de model, pot avea de la 1 la 8 intrări întreruperi externe.
Să luăm în considerare sistemul extern de management al întreruperilor. În acest scop, sunt furnizate următoarele combinații de registre I/O în funcție de model (vezi fișa corespunzătoare):
- GIMSK, EIFR, PCMSK, MCUCR;
- GIKR, GIFR, MCUCR;
- EIMSK, EICR, EIFR;
GIMSK, GIKR, EIMSK - măști de întrerupere,
EIFR, PCMSK, GIFR, EIFR – steaguri de întrerupere
Pentru permisiune sau interdicție întreruperi externe registrele de control sunt destinate: GIMSK-(Registrul general de masca de întrerupere)(Minuscul), GICR- (Registrul de control general al întreruperilor)(Mega), MCUCR – (Registrul de control MCU)




EIFR- Registrul semnalizator de întrerupere externă: 1 - activat, 0 - dezactivat. Fiecare bit (steagul) permite pinului corespunzător să acționeze ca o sursă de întrerupere.

Biți de control al registrului GIMSK:
Bit 7 – INT1: Activare cerere de întrerupere externă 1 – bit de activare întrerupere INT1: 1 – activat, 0 – dezactivat. Întreruperea va fi generată chiar dacă pinul INT1 este configurat ca ieșire. Bitul INT1 este setat să întrerupă în registrul de flag EIFR. Pinul INT1 este sincronizat cu generatorul de ceas.

Bit 6 – INT0: External Interrupt Request 0 Enable - bit de activare întrerupere INT0: 1 – activat, 0 – dezactivat. Întreruperea va fi generată chiar dacă pinul INT0 este configurat ca ieșire. Bitul INT0 este setat să întrerupă în registrul de flag EIFR. Pinul INT10 este sincronizat cu generatorul de ceas.

Bit 5 – PCIE: Pin Change Interrupt Enable – bit de activare a întreruperii pe PCINT0…7 pini: 1 – activat, 0 – dezactivat. Orice modificare pe oricare dintre pinii PCINT0...7 va genera o întrerupere. Pinii PCINT0...7 sunt configurați pentru întrerupere individual, prin biți din registrul de flag PCMSK.

PCMSK- Pin Change Mask Regiser - registrul steagului PCMSK: 1 - permis, 0 - dezactivat. Fiecare bit (steagul) permite pinului corespunzător să acționeze ca o sursă de întrerupere. Pinii PCINT0...7 nu sunt sincronizați cu generatorul de ceas, adică. o întrerupere are loc atunci când are loc o modificare pe oricare dintre pini.

Mega8

și registrul de pavilion corespunzător


Bit 7

Bit 6 – INT0: External Interrupt Request 0 Enable - bit de activare întrerupere INT0: 1 – activat, 0 – dezactivat. Întreruperea va fi generată chiar dacă pinul INT0 este configurat ca ieșire. Bitul INT0 este setat să întrerupă în registrul de steaguri GIFR



GIFR – General Interrupt Flag Register: 1 – activat, 0 – dezactivat. Fiecare bit (steagul) permite pinului corespunzător să acționeze ca o sursă de întrerupere.

Biți de control al registrului GICR:
Bit 7– : Activare cerere de întrerupere externă 1 – bit de activare a întreruperii INT1: 1 – permis, 0 – interzis. Întreruperea va fi generată chiar dacă pinul INT1 este configurat ca ieșire. Bitul INT1 este setat să întrerupă în registrul de steaguri GIFR

Bit 6 – INT0: Solicitare de întrerupere externă 0 Activare - bit de activare a întreruperii INT0: 1 – permis, 0 – interzis. Întreruperea va fi generată chiar dacă pinul INT0 este configurat ca ieșire. Bitul INT0 este setat să întrerupă în registrul de steaguri GIFR

Bit 5 – INT2: Activare cerere de întrerupere externă 2 - bit de activare a întreruperii INT2: 1 – permis, 0 – interzis. Întreruperea va fi generată chiar dacă pinul INT2 este configurat ca ieșire. Bitul INT2 este setat să întrerupă în registrul de steaguri GIFR

Funcțiile intrărilor INT0 și INT1 din toate controlerele sunt controlate de biții de ordin inferior ai registrului MCUCR

MCUCR– Registrul de control MCU
Biți de control:
Biții 1, 0 – ISC01, ISC00 (Interrupt Sense Control 0 Bit 1 and Bit 0) – starea acestor biți determină evenimentul pe pinul INT0, care generează o întrerupere INT0:
ISC01=0, ISC00=0 – nivel zero logic;
ISC01=0, ISC00=1 – orice modificare a stării logice;
ISC01=1, ISC00=0 – pe margine de cădere;
ISC01=1, ISC00=1 – pe o muchie ascendentă.

Biții 3, 2 – ISC11, ISC10 (Interrupt Sense Control 1 Bit 1 and Bit 0) – starea acestor biți determină nivelul semnalului la pinul INT1, care generează întreruperea INT1:
ISC11=0, ISC10=0 – nivel zero logic;
ISC11=0, ISC10=1 – orice schimbare a stării logice;
ISC11=1, ISC10=0 – pe o muchie de cădere;
ISC11=1, ISC10=1 – pe o muchie ascendentă.

Ei bine, se pare că am vorbit la minimum despre întreruperile externe.
Este clar că pentru ca întreruperile să funcționeze, acestea trebuie înregistrate în consecință.
Să adăugăm inițializarea întreruperii pe INT1 începută pentru minuscul pe marginea ascendentă a semnalului:

Ldi r16.0x80 ; scrie in r16 numarul 0b10000000 ldi r17.0x0C ; scrie in r17 numarul 0b00001100 out MCUCR,r17 ; întreruperea va fi generată pe frontul ascendent ISC11=1, ISC10=1 out GIMSK,r16 ; seteaza masca INT0 sei
Apropo, puteți genera o întrerupere pe tiny2313 pe orice PCINT0...7 pini, pe Mega până la seria 48 aceste caracteristici nu sunt disponibile...
Există operații în timpul cărora pot apărea întreruperi care pot cauza blocarea programului. În astfel de cazuri, înainte de a începe operația scriem CLI, iar după SEI. Astfel de operațiuni se numesc - atomic.
Este de dorit ca programele de întrerupere să fie compacte și executate la viteză maximă, deoarece scopul oricărei întreruperi este de a capta un eveniment. Dacă conform diverse motive programul rulează încet, este suficient să înregistrați evenimentul și să îl procesați puțin mai târziu.

Pentru a nu aglomera materialul prezentat cu informații inutile, recomand cititorilor să folosească fișe de date, iar dacă totul nu este clar, atunci pune întrebări mai des pe forumuri.
În continuare, vom lua în considerare în detaliu întreruperile interne bazate pe temporizatoarele încorporate. cititori. Pentru a participa la vot, înregistrați-vă și conectați-vă la site cu numele de utilizator și parola.

Unul dintre avantajele microcontrolerului ATmega8 este gama sa largă de întreruperi diferite.

Întrerupe este un eveniment la apariția căruia execuția programului principal este suspendată și este numită o funcție care gestionează o întrerupere de un anumit tip.

Întreruperile sunt împărțite în interne și externe. Sursele de întreruperi interne includ module de microcontroler încorporate (temporizatoare, transceiver USART etc.). Întreruperile externe apar atunci când semnalele externe ajung la pinii microcontrolerului (de exemplu, semnalele la pinii RESET și INT). Natura semnalelor care conduc la apariția unei întreruperi este stabilită în registrul de control MCUCR, în special în biții - ISC00 (bit 0) și ISC01 (bit 1) pentru intrarea INT 0; ISC10 (bit2) și ISC11 (bit3) pentru intrarea INT1.

În microcontrolerul ATmega8, fiecare întrerupere are propria sa vector de întrerupere(adresa de la începutul zonei de memorie a programului în care este stocată comanda de salt la rutina de întrerupere specificată). În mega8, toate întreruperile au aceeași prioritate. Dacă apar mai multe întreruperi simultan, întreruperea cu numărul de vector mai mic va fi procesată mai întâi.

Vectorii de întrerupere în Atmega8

Abordare Sursa de întrerupere Descriere
0x0000 RESET Resetare semnal
0x0001 INT0 Cerere de întrerupere externă la intrarea INT0
0x0002 INT1 Cerere de întrerupere externă la intrarea INT1
0x0003 T/C1 Captură cu temporizator T/C1
0x0004 T/C1 Match T/C1 Timer Compara Registrul A
0x0005 T/C1 Potriviți cu registrul de comparare B al temporizatorului T/C1
0x0006 T/C1 Debordare contor T/C1
0x0007 T/C0 Debordare contor T/C0
0x0008 SPI Transferul de date SPI a fost finalizat
0x0009 UART Transceiver-ul UART a finalizat primirea datelor.
0x000A UART Registrul de date UART este gol
0x000B UART Transmiterea datelor prin transceiver UART este finalizată
0x000C ANA_COMP Întreruperea de la comparatorul analogic

Managementul întreruperii

4 registre sunt responsabile pentru gestionarea întreruperilor în ATmega8:

GIMSK(aka GICR) - interzice/activează întreruperile pe baza semnalelor la intrările INT0, INT1

GIFR- gestionarea tuturor întreruperilor externe

TIMSK, TIFR- gestionarea întreruperilor de la cronometre/contoare

Inregistreaza-te GIMSK(GICR)

INTFx=1: a avut loc o întrerupere la intrarea INTx. La intrarea în rutina de gestionare a întreruperilor, INTFx este resetat automat la starea de jurnal. 0

Inregistreaza-te TIMSK

7 6 5 4 3 2 1 0
TOIE1
OCIE1A
OCIE1B
-
TICIE
-
TOIE0
-

TOIE1=1: întrerupere de depășire T/C1 activată

OCIE1A=1: întrerupe atunci când registrul de comparație A se potrivește cu conținutul contorului T/C1 activat

OCIE1B=1: întrerupe atunci când registrul de comparație B se potrivește cu conținutul contorului T/C1 activat

TICIE=1: întrerupere activată când este îndeplinită condiția de captare

TOIE0=1: întrerupere de depășire T/C0 activată

Inregistreaza-te TIFR

7 6 5 4 3 2 1 0
TOV1
OCF1A
OCF1B
-
ICF1
-
TOV0
-

TOV1=1: S-a produs debordarea T/C1

OCF1A=1: registrul de comparație A a coincis cu conținutul contorului T/C1 permis

OCF1B=1: registrul de comparație B se potrivește cu conținutul contorului T/C1 permis

ICF=1: îndeplinite condițiile de captare

TOV0=1: S-a produs debordarea T/C0

La introducerea subrutinei de gestionare a întreruperilor, indicatorul de registru TIFR corespunzător întreruperii este resetat automat la starea de jurnal. 0

Întreruperile funcționează numai când întreruperile generale sunt activate în registrul de stare SREG (bit 7 = 1). Când apare o întrerupere, acest bit este resetat automat la 0, dezactivând întreruperile ulterioare.

În acest exemplu, pinul INT0 este activat în modul de intrare pull-up. Când pinul este scurtcircuitat la masă folosind un buton, se setează 0 logic pe acesta (marginea semnalului scade de la tensiunea de alimentare la 0) și se declanșează gestionarea întreruperilor, aprinzând becul conectat la pinul zero al portului. B

lampă goală ON()
{
PORTB.0=1;
DDRB.0=1;
}

întrerupere void ext_int0_isr(void)
{
lampON();
}

DDRD.2=0;
PORTD.2=1;

SREG|= (1 în timp ce(1) (

Exemplul de mai sus arată, de asemenea, cum sunt setați vectorii de întrerupere în Code Vision AVR (interrupt void ext_int0_isr(void)). Vectorii de întrerupere sunt setați în mod similar pentru alte cazuri:

EXT_INT0 2
EXT_INT1 3
TIM2_COMP 4
TIM2_OVF 5
TIM1_CAPT 6
TIM1_COMPA 7
TIM1_COMPB 8
TIM1_OVF 9
TIM0_OVF 10
SPI_STC 11
USART_RXC 12
USART_DRE 13
USART_TXC 14
ADC_INT 15
EE_RDY 16
ANA_COMP 17
TWI 18
SPM_READY 19

Parte Microcontrolere AVR include un număr mare de dispozitive periferice (ADC, Timer/Counters, EXTI, Analog Comparator, EEPROM, USART, SPI, I2C etc.), fiecare dintre acestea putând efectua anumite acțiuni asupra datelor/semnalelor și a altor informații. Aceste dispozitive sunt integrate în microcontroler pentru a îmbunătăți eficiența aplicației și a reduce costurile atunci când se dezvoltă tot felul de dispozitive bazate pe microcontrolere AVR.

Procesorul comunică/controlează dispozitivele periferice prin registrele I/O, care se află în memoria de date, permițându-le să fie utilizate ca variabile obișnuite. Fiecare dispozitiv are propriile sale registre I/O.

Toate registrele I/O pot fi împărțite în trei grupuri: registre de date, registre de control și registre de stare.

Folosind registrele de control, dispozitivul este configurat să funcționeze într-un mod sau altul, cu o anumită frecvență, precizie etc., iar folosind registrele de date se citește rezultatul muncii a acestui dispozitiv(conversie analog-digitală, date primite, valoare cronometru/contor etc.). S-ar părea că nu este nimic complicat aici (de fapt, nu este nimic complicat aici :)), a pornit dispozitivul, a indicat modul de funcționare dorit și apoi tot ce rămâne este să tăiați cupoanele, să citiți datele gata făcute și folosiți-le în calcule. Întreaga întrebare este „când” să citești tocmai aceste date (dispozitivul și-a încheiat activitatea sau încă procesează date), deoarece toate dispozitivele periferice funcționează în paralel cu miezul microcontrolerului și chiar la frecvențe diferite. Se pune problema implementării comunicării şi sincronizarea între procesor şi dispozitiv periferic.

După cum probabil ați ghicit deja, pentru a implementa comunicarea și sincronizarea între dispozitiv și procesor, sunt folosite „Registrele de stare”, care stochează starea curentă de funcționare a unui anumit dispozitiv. Fiecare stare în care se poate afla dispozitivul corespunde unui „bit”. în starea registrului” (steagul), a cărei valoare actuală „vorbește” despre starea curentă a acestui dispozitiv sau despre funcția sa individuală (lucrare finalizată/nefinalizată, eroare în timpul procesării datelor, registru gol etc.).

Mecanismul de comunicare dintre procesor și un dispozitiv periferic este implementat prin sondaj de semnalizare, care sunt responsabili pentru o anumită funcție a acestui dispozitiv. În funcție de valoarea unui anumit flag (starea dispozitivului), puteți modifica fluxul de execuție a programului (branching). De exemplu:

Verificarea dacă este setat un anumit steag (a avut loc un eveniment):

dacă (RegX & (1<< Flag) ) // dacă steagul din registrul RegX este setat
{
// Fă ceva
}

În așteptarea finalizării unei acțiuni (eveniment):

în timp ce(!(RegX & (1<

Interogarea steaguri este o sarcină destul de intensivă în resurse, atât în ​​ceea ce privește dimensiunea programului, cât și viteza programului. Deoarece numărul total de steaguri din microcontrolerele AVR este destul de mare (un avantaj), implementarea comunicării între procesor și dispozitiv prin sondarea steaguri duce la o scădere a eficienței (viteza codului/dimensiunea codului) programului pe care îl scrieți, în plus, programul devine foarte confuz, ceea ce contribuie la apariția unor erori greu de detectat chiar și cu depanarea detaliată a codului.

Pentru a crește eficiența programelor pentru microcontrolere AVR, precum și pentru a facilita procesul de creare și depanare a acestor programe, dezvoltatorii au echipat toate dispozitivele periferice cu „surse de întrerupere” ( Sursele de întrerupere), unele dispozitive pot avea mai multe surse de întrerupere.

Folosind surse de întrerupere, este implementat mecanism de sincronizare, între procesor și dispozitivul periferic, adică procesorul va începe să primească date, steaguri de sondare și alte acțiuni pe dispozitivul periferic numai atunci când dispozitivul este pregătit pentru aceasta (va raporta finalizarea procesării datelor, o eroare în timpul prelucrarea datelor, registrul este gol etc.) etc.), prin generarea unei „cereri de întrerupere” ( Cerere de întrerupere), în funcție de valoarea unui steag (dispozitiv/funcție/stare eveniment).

În literatură, de foarte multe ori, întregul lanț de evenimente, de la „cererea de întrerupere” (IRQ) la „procedura serviciului de întrerupere” (ISR), este abreviat ca întrerupere ( Întrerupe).

Ce este o întrerupere?


Întreruperea este un semnal care anunță procesorul despre apariția unui eveniment. În acest caz, execuția secvenței curente de comenzi este suspendată și controlul este transferat către procedura de gestionare a întreruperilor corespunzătoare acestui eveniment, după care execuția codului continuă exact din punctul în care a fost întrerupt (revenirea controlului). (Wiki)

Întrerupeți rutina(Rutina de serviciu de întrerupere) nu este altceva decât o funcție/subrutină care ar trebui să fie executată atunci când are loc un anumit eveniment. Vom folosi cuvântul „procedură” pentru a-i sublinia diferența față de toate celelalte funcții.

Principala diferență între procedură și funcțiile simple este că în loc de „întoarcerea de la funcție” obișnuită (comanda de asamblare RET), ar trebui să utilizați „întoarcerea de la întrerupere” (comanda de asamblare RETI) - " Reveniți de la întrerupere".

Proprietăți de întrerupere AVR:

  • Fiecare dispozitiv periferic care face parte din microcontrolerele AVR are cel puțin o sursă de întrerupere. Printre toate aceste întreruperi, ar trebui să se includă și întreruperea de resetare, al cărei scop este diferit de toate celelalte.
  • Fiecare întrerupere are un vector (link) strict alocat care indică rutina serviciului de întrerupere. Toți vectorii de întrerupere sunt localizați chiar la începutul memoriei programului și formează împreună „tabelul vectorilor de întrerupere”.
  • Fiecare întrerupere este asociată cu un anumit „bit de activare a întreruperii”, astfel, pentru a utiliza o anumită întrerupere, ar trebui să scrieți în „bitul de activare a întreruperii” - jurnal. unitate. În plus, indiferent dacă ați activat anumite întreruperi sau nu, microcontrolerul nu va începe procesarea acestor întreruperi până când una logică nu este scrisă în „bitul de activare a întreruperilor globale” din registrul de stare SREG. De asemenea, pentru a dezactiva toate întreruperile (pentru un timp nedefinit), ar trebui scris un zero logic în bitul de activare a întreruperii generale.

Întreruperea de resetare, spre deosebire de toate celelalte, nu poate fi dezactivată. Astfel de întreruperi se mai numesc și întreruperi nemascabile.

  • Fiecare întrerupere are o prioritate strict definită. Prioritatea unei întreruperi depinde de locația sa în „tabelul vectorului de întrerupere”. Cu cât numărul vectorului din tabel este mai mic, cu atât este mai mare prioritatea întreruperii. Adică, cea mai mare prioritate este întreruperea de resetare, care este localizată mai întâi în tabelul, și în consecință în programele de memorie.Întreruperea externă INT0, în urma întreruperii Reset din „tabelul vectorului de întreruperi”, are o prioritate mai mică decât cea a Resetare, dar mai mare decât cea a tuturor celorlalte întreruperi etc.

Tabelul vector de întrerupere, cu excepția vectorului Reset, poate fi mutat la începutul secțiunii Boot a memoriei Flash prin setarea bitului IVSEL în registrul GICR. Vectorul de resetare poate fi mutat și la începutul secțiunii Boot a memoriei Flash prin programarea bitului siguranței - BOOTRST.



Fig.1 Tabel de vectori de întrerupere ATmega16

Întrerupeți prototipul de rutină


Pentru a declara o funcție ca rutină de gestionare a întreruperilor, trebuie să urmați anumite reguli de prototipare, astfel încât compilatorul/linkerul să poată identifica și asocia corect întreruperea de care aveți nevoie cu rutina sa de gestionare.

În primul rând, rutina serviciului de întrerupere nu poate accepta nimic ca argument (void) și, de asemenea, nu poate returna nimic (void). Acest lucru se datorează faptului că toate întreruperile din AVR sunt asincrone, deci nu se știe unde va fi întreruptă execuția programului, de la cine să primească și cui să returneze valoarea și, de asemenea, pentru a minimiza timpul de intrare și ieșire din întrerupere.

void isr(void)

În al doilea rând, înainte de prototipul funcției, ar trebui să indicați că este o procedură de gestionare a întreruperilor. După cum știți, în limbajul C este executat doar codul folosit în funcția principală. Deoarece procedura de gestionare a întreruperilor în funcția principală nu este utilizată nicăieri, astfel încât compilatorul să nu o „aruncă” ca inutilă, înainte de prototipul procedurii ar trebui să se precizeze că această funcție este o procedură de gestionare a întreruperilor.

Prototip de procedură de gestionare a întreruperilor în mediul AVR Studio

#include

ISR (XXX_vect)
{

}

În AVR Studio (AVR GCC), fiecare rutină de întrerupere începe cu o definiție macro ISR, urmată de următorul construct între paranteze:

XXX_vect

unde „XXX” este numele vectorului de întrerupere. Toate numele vectorului pentru un anumit microcontroler AVR pot fi găsite în „tabelul vectorului de întrerupere” din foaia de date a microcontrolerului sau în fișierul antet al acestuia. De exemplu, „tabelul vectorului de întrerupere” pentru microcontrolerul ATmega16 este prezentat în Fig. 1, unde în coloana Sursă sunt listate toate numele vectorilor de întrerupere. Numele pot fi găsite și în fișierul antet al acestui microcontroler (C :\Program Files\Atmel\AVR Tools\AVR Toolchain\avr\include\avr\iom16.h), vezi Fig. 2. Tot ce trebuie să facem este să găsim numele vectorului de care avem nevoie în tabel și să adăugăm sufixul „_vect” la acesta.


Fig.2 Fișier antet ATmega16 pentru AVR Studio

De exemplu, să scriem o procedură de gestionare a întreruperilor pentru primirea unui octet prin USART (USART, Rx Complete):

ISR (USART_RXC_vect)
{
// Întrerupe corpul handlerului
}

Apropo: înainte de a utiliza orice întrerupere în AVR Studio, ar trebui să includeți fișierele de antet io.h și interrupt.h în proiect:

#include
#include

Puteți citi mai multe despre gestionarea întreruperilor în AVR Studio (AVR GCC) în secțiunea Introducere în gestionarea întreruperilor avr-libc.

Prototip de procedură de gestionare a întreruperilor în mediul ImageCraft

#pragma interrupt_handler : iv_XXX
gol< handler_name>(nud)
{
// Întrerupe corpul handlerului
}

În mediul ImageCraft, rutina de întrerupere prototip arată astfel:

gol< handler_name>(nud)

Unde , acesta este numele pe care doriți să-l dați acestui handler de întrerupere. Una dintre cerințele pentru declararea procedurilor de gestionare a întreruperilor este ca înainte de prototipul funcției să fie indicat că este un handler de întreruperi. Acest lucru se face folosind o directivă pragma manipulator_întreruperi :

#pragma interrupt_handler : iv_XXX

Unde acesta este numele funcției care va fi folosită ca un handler de întrerupere, iar construcția „iv_XXX” este numele vectorului de întrerupere (XXX) cu prefixul „iv_”.Ca și în cazul AVR Studio, toate numele vectorului pentru un anumit microcontroler AVR poate fi găsit în „tabelul vector de întrerupere” din fișa de date a unui microcontroler dat sau în fișierul antet al acestuia (vezi Fig. 3).


Fig.3 Fișier antet ATmega16 pentru ImageCraft IDE

De exemplu, procedura de gestionare a unei întreruperi pentru primirea unui octet prin USART (USART, Rx Complete) în mediul ImageCraft va arăta astfel:

#pragma interrupt_handler usart_rxc_isr: iv_USART_RXC
void usart_rxc_isr(void)
{
// Întrerupe corpul handlerului
}

Mai multe informații despre procedurile de gestionare a întreruperilor din ImageCraft IDE pot fi găsite în meniul Help->Programming the AVR->Interrupt Handlers al mediului de dezvoltare.

Uneori, dacă mai mulți operatori de întrerupere trebuie să facă același lucru, atunci pentru a salva memoria programului, puteți direcționa mai mulți vectori de întrerupere către aceeași rutină de întrerupere.

În AVR Studio arată astfel:

ISR (INT0_vect)
{
// Fă ceva
}
ISR(INT1_vect, ISR_ALIASOF(INT0_vect) );

Mai întâi vine procedura de procesare a întreruperii pentru un vector specific, în acest caz INT0. Toate celelalte proceduri se pot referi la orice handler de întrerupere folosind constructul:

ISR (YYY_vect, ISR_ALIASOF(XXX_vect) ) ;

unde YYY este numele vectorului de întrerupere care se referă la manipulatorul de întreruperi declarat anterior pentru vectorul XXX.

În ImageCraft arată astfel:

#pragma interrupt_handler : iv_XXX : iv_AAAA
gol< handler_name>(nud)
{
// Întrerupe corpul handlerului
}

#pragma interrupt_handler : iv_XXX
#pragma interrupt_handler : iv_AAAA
gol< handler_name>(nud)
{
// Întrerupe corpul handlerului
}

unde vectorii XXX și YYY se referă la același handler de întrerupere .

Cum funcționează întreruperea în microcontrolerele AVR?

1. Să presupunem că " cerere de întrerupere” (IRQ).

Apropo: dacă mai multe solicitări de procesare a întreruperilor apar simultan, întreruperea cu cea mai mare prioritate va fi procesată prima, toate celelalte solicitări vor fi procesate după finalizarea întreruperii cu prioritate înaltă.

2. Examinare.

Dacă bitul de activare pentru această întrerupere este setat (bitul de activare a întreruperii) și bitul I (bitul de activare a întreruperii generale) al registrului de stare a procesorului (SREG) este setat, atunci procesorul începe să pregătească rutina de serviciu de întrerupere, în timp ce Bitul de activare a întreruperii (I-bit al registrului SREG) este resetat, dezactivând astfel toate celelalte întreruperi. Acest lucru se întâmplă astfel încât niciun alt eveniment nu poate întrerupe procesarea întreruperii curente.

Apropo: dacă în procedura de gestionare a întreruperilor setați I-bit la starea de jurnal. unități, atunci orice întrerupere activată poate întrerupe la rândul său procesarea întreruperii curente. Astfel de întreruperi se numesc întreruperi imbricate.

3. Pregătirea.

Procesorul finalizează execuția instrucțiunii de asamblare curente și apoi plasează adresa următoarei instrucțiuni pe stivă (PC->STACK). Apoi, procesorul verifică care sursă de întrerupere a transmis o „cerere de întrerupere” (IRQ), după care, folosind vectorul acestei surse (link) din tabelul de vectori (care este atribuit ferm fiecărei surse de întrerupere), trece la procedura de intrerupere a procesarii (instructiunea JMP).Asa este, procesorul petrece cel putin 4 cicluri de ceas (in functie de momentul in care apare cererea si de durata de executie a instructiunii curente).Este un timp de raspuns foarte bun la IRQ, comparativ cu microcontrolere de la alți producători.

Apropo: dacă apare un IRQ în timp ce microcontrolerul este în modul de repaus, timpul de răspuns la IRQ crește cu încă patru cicluri de ceas, plus timpul stocat în biții de siguranță SUT1 și SUT0 (Timp de pornire).

Întrerupere - un eveniment care necesită un răspuns imediat din partea procesorului. Răspunsul este că procesorul întrerupe procesarea programului curent ( program întrerupt) și continuă să execute un alt program ( întreruperea programului), special conceput pentru acest eveniment. La finalizarea acestui program, procesorul revine la executarea programului întrerupt.

Fiecare eveniment care necesită o întrerupere este însoțit de semnal de întrerupere, informând computerul despre acest lucru și sunat cerere de întrerupere.

Starea programului reprezintă un set de stări ale tuturor elementelor de stocare în momentul corespunzător din timp (de exemplu, după ce ultima comandă a fost executată). Când are loc o întrerupere, microcontrolerul stochează conținutul contorului programului pe stivă și încarcă în el adresa vectorului de întrerupere corespunzător. Ultima comandă a rutinei de serviciu de întrerupere trebuie să fie o comandă care revine la programul principal și restabilește contorul de program stocat anterior. În timp ce gestionarea întreruperilor se execută, unele informații se pot schimba. Prin urmare, atunci când treceți la manipulatorul de întreruperi, este necesar să salvați elementele care sunt modificate. Setul de astfel de elemente este vector de stare a programului. În acest caz, alte informații despre starea celulelor de memorie nu sunt semnificative sau pot fi restaurate programatic.

Vector stare initiala conține toate informațiile necesare pentru lansarea inițială a programului. În multe cazuri, vectorul de stare inițială conține un singur element - adresa de pornire a programului care este lansat.

Vector de întrerupere este vectorul stării inițiale a programului de întrerupere (handler) și conține toate informațiile necesare trecerii la handler, inclusiv adresa de pornire a acestuia. Fiecare tip de întrerupere are propriul său vector de întrerupere, care inițiază execuția handler-ului corespunzător. De obicei, vectorii de întrerupere sunt stocați în locații de memorie fixă ​​special alocate cu adrese scurte, care reprezintă tabel de vectori de întrerupere. Pentru a trece la programul de întrerupere adecvat, procesorul trebuie să aibă un vector de întrerupere și adresa acestui vector. La această adresă, de regulă, există o comandă de salt necondiționat la subrutina de gestionare a întreruperilor.

De regulă, controlul stocării și returnării este atribuit operatorului de întrerupere. În acest caz, handlerul este format din trei părți - pregătitoare (prolog) și finală (epilog), care asigură comutarea programului, și programul de întrerupere propriu-zis, care efectuează operațiunile solicitate de cerere. Timpul de răspuns este definit ca intervalul de timp din momentul în care este primită o solicitare de întrerupere până când programul de întrerupere începe execuția.


tp– timpul de răspuns al sistemului la întrerupere;
t z– timpul de memorare a stării programului întrerupt;
t ppr– ora programului efectiv de întrerupere;
staniu– timpul pentru a restabili starea programului întrerupt

Dacă există mai multe surse de solicitări, trebuie stabilită o anumită ordine de deservire a cererilor primite, apelată relații prioritare sau disciplina de serviciu. Setul de toate tipurile posibile de întreruperi ale procesorului este sistem de întrerupere microcontroler. Disciplina serviciului determină care dintre mai multe solicitări primite simultan ar trebui procesată mai întâi și dacă aceasta cerereîntrerupe unul sau altul manipulator de întreruperi.
Dacă o solicitare de întrerupere cu prioritate mai mare este primită în timp ce o întrerupere este procesată, controlul este transferat la manipulatorul de întrerupere cu prioritate mai mare și gestionarea întreruperi cu prioritate inferioară este suspendat. Apare întrerupe cuibărirea. Este apelat numărul maxim de programe care se pot suspenda reciproc profunzimea întreruperilor.

Dacă cererea de întrerupere nu este deservită în momentul în care sosește o nouă solicitare din aceeași sursă (aceeași prioritate), atunci întrerupe saturația sistemului. În acest caz, o parte din cererile de întrerupere se vor pierde, ceea ce pt operatie normala microcontrolerul nu este permis.

Caracteristicile sistemului de întrerupere sunt:

  • numărul total de cereri de întrerupere numărul de surse de solicitări de întrerupere;
  • tip reprezentare întrerupere - de regulă, o solicitare de întrerupere este reprezentată de un nivel de semnal logic;
  • prioritatea întreruperii – determină ordinea în care este procesată fiecare cerere de întrerupere; cu cât prioritatea este mai mare, cu atât întârzierea execuției programului de întrerupere a acesteia este mai scurtă;
  • timp de răspuns – intervalul de timp dintre apariția cererii de întrerupere și începerea execuției programului de întrerupere;
  • întârziere întrerupere – determinată de timpul total pentru stocarea și restabilirea programului;
  • adâncimea, de obicei coincide cu numărul de niveluri de prioritate din sistemul de întrerupere;
  • întreruperea saturației sistemului;
  • momentele permise de întrerupere a programului (de obicei, sfârșitul execuției următoarei comenzi).

Întrerupeți mascarea folosit pentru a spune microcontrolerului să răspundă la fiecare tip de întrerupere sau să o ignore. Masca de întrerupere reprezintă un cod binar ai cărui biți sunt alocați surselor solicitării de întrerupere. Un bit din codul binar îi spune microcontrolerului să gestioneze acest tip de întrerupere. Un bit zero, dimpotrivă, nu permite microcontrolerului să treacă la procesarea întreruperilor de tipul specificat.
De regulă, pe lângă mascarea întreruperilor, există și un bit de activare globală a întreruperilor, a cărui valoare zero dezactivează toți gestionatorii de întreruperi (cu excepția resetarii hardware și a saltului la începutul programului de execuție).
Pe lângă codul binar al măștii de întrerupere, există și un cod binar steaguri de întrerupere, care permite gestionarului de întrerupere să seteze sursa întreruperii dacă există mai multe surse cu cererea specificată în microcontroler.




Top