O intrerupere reprezinta un semnal sincron sau asincron de la un periferic ce semnalizeaza aparitia unui eveniment care trebuie tratat de catre procesor. Tratarea intreruperii are ca efect suspendarea firului normal de executie al unui program si lansarea in executie a unei rutine de tratare a intreruperii (RTI).
Intreruperile hardware au fost introduse pentru a se elimina buclele pe care un procesor ar trebui sa le faca in asteptarea unui eveniment de la un periferic. Folosind un sistem de intreruperi, perifericele pot atentiona procesorul in momentul producerii unei intreruperi (IRQ), acesta din urma fiind liber sa-si ruleze programul normal in restul timpului si sa isi intrerupa executia doar atunci cand este necesar.
Inainte de a lansa in executie o RTI, procesorul trebuie sa aiba la dispozitie un mecanism prin care sa salveze starea in care se afla in momentul aparitiei intreruperii. Aceasta se face prin salvarea intr-o memorie, de cele mai multe ori organizata sub forma unei stive, a registrului contor de program (Program Counter), a registrelor de stare precum si a tuturor variabilelor din program care sunt afectate de executia RTI. La sfarsitul executiei RTI starea anterioara a registrelor este refacuta si programul principal este reluat din punctul de unde a fost intrerupt.
Pentru a asocia o intrerupere cu o anumita rutina din program, procesorul foloseste tabela vectorilor de intrerupere (TVI). Fiecarei intreruperi ii este asociata o adresa la care programul va face salt in cazul aparitiei acesteia. Aceste adrese sunt predefinite si sunt mapate in memoria de program intr-un spatiu contiguu care alcatuieste TVI. Adresele intreruperilor in TVI sunt setate in functie de prioritatea lor, cu cat adresa este mai mica cu atat prioritatea este mai mare.
Pentru ATMega16, TVI este data in tabelul de mai jos:
Se observa ca TVI este plasata de la prima adresa a memoriei de program si ca intreruperile sunt puse din doua in doua adrese consecutive. Prioritatea cea mai mare o are intreruperea de RESET, de la adresa 0, apoi intreruperea externa 0 (INT0).
Perifericele care pot genera intreruperi la ATMega16 sunt timerele, interfata seriala (USART), convertorul analog-digital (ADC), controllerul de memorie EPROM, comparatorul analog si interfata seriala I2C. Deasemenea, procesorul poate sa primeasca cereri de intreruperi externe din trei surse (INT0, 1 si 2) ce corespund unui numar egal de pini exteriori.
Intreruperile pot fi activate sau dezactivate de utilizator in program prin setarea individuala a bitilor de interrupt enable pentru fiecare periferic folosit si prin setarea flagului de “Global Interrupt Enable” (I) din Status Register (SREG).
Tratarea unei intreruperi pentru ATMega16 se face ca in figura de mai jos.
Sa presupunem ca programul nostru primeste intreruperea externa INT0 in timp ce executa instructiunea ldi R16,0xFF. Dupa efectuarea instructiunii, registrul contor program (PC) este automat salvat in stiva si apoi initializat la valoarea corespunzatoare adresei lui INT0 (123) la adresa 2FF care-i permite sa sara la rutina efectiva de tratare a intreruperii. La sfarsitul oricarei RTI trebuie sa existe instructiunea reti care reface din stiva registrul PC (programul sare inapoi la adresa de unde ramasese inainte de intrerupere).
In timpul executiei unei intreruperi, bitul I din SREG este setat la 0 si resetat la iesire, adica orice alta intrerupere care poate aparea in timpul intreruperii curente nu va fi luata in seama. Cu toate acestea, utilizatorul poate sa reseteze bitul I din software, permitand astfel executia de intrerupere in intrerupere.
Concret, o secventa de cod care trateaza o intrerupere este data mai jos:
.cseg ; aici incepe segmentul de cod ;tabela de intreruperi .org 0 jmp main ; Intreruperea de reset jmp int0_handler ; Intrerupere externa 0 jmp int1_handler ; Intrerupere externa 1 main: ldi r16, HIGH(RAMEND) ; initializeaza stiva out SPH, r16 ldi r16, LOW(RAMEND) out SPL, r16 sei ; "set enable interrupt" - ; dam drumul ingreruperilor setand bitul “I” din registrul SREG loop: ; bucla principala a programului [..cod program principal..] rjmp loop ; RUTINA DE TRATARE INTRERUPERI int0_handler: push r16 ; salvam un registru in stiva in r16, SREG ; citim valoarea din SREG in registrul general r16 push r16 ; punem pe stiva valoarea push r17 ; salvam pe stiva r17 in r16, PIND ; in registrul r16 incarcam valoarea din registrul PIND ldi r17, 234 ; Incarcam 234 in r17 add r16, r17 ; adunare fara carry; ; -- continutul registrelor, inclusiv SREG, este modificat ; -- refacerea continutului initial al registrelor pop r17 ; scoate din stiva r17 pop r16 ; scoate din stiva r16 out SREG, r16 ; reface SREG pop r16 ; reia valoarea lui r16 din stiva reti ; se reintoarce din intrerupere
Acest registru este raspunzator pentru plasarea tabelului vectorului de intreruperi.
Aceste intreruperi sunt generate prin intermediul pinilor INT0, INT1 si INT2. Ele sunt activate chiar daca acesti pini sunt setati ca fiind de output. Modul in care se pot genera intreruperile externe poate fi setat prin configurarea registrelor MCUCR si MCUCSR.
De exemplu, pentru a folosi intreruperea externa INT2 sunt necesare urmatoarele configurari:
Perifericele care pot genera intreruperi sunt: timerele, convertorul analog-digital, interfetele seriale (RS232, I2C, SPI) etc.
Timerul/Counterul, dupa cum ii spune si numele ofera facilitatea de a masura intervale fixe de timp si de a genera intreruperi la expirarea intervalului masurat. Un timer, odata initializat va functiona independent de unitatea centrala (core μP). Acest lucru permite eliminarea buclelor de delay din programul principal. Principiul de functionare a unui Timer poate fi descris in linii mari de cele trei unitati:
Timerele sunt prevazute cu mai multe canale astfel in paralel se pot desfasura diferite numaratori. ATmega16 este prevazut cu 3 unitati de timer: doua de opt biti si una de numarare pe saisprezece biti.
Principalele caracteristici sunt:
Majoritatea registrelor si referintelor de biti din aceasta sectiune sunt prezentate intr-o forma generala.Un “n” mic inlocuieste numarul timerului si un “x” mic inlocuieste unitatea de comparare de output. Atunci cand se foloseste registrul sau bitul definit intr-un program, trebuie folosită forma precisă.
TCNT1, OCR1A/B si ICR1 sunt toate registre de 16 biti. Proceduri speciale trebuie urmate cand se acceseaza registre de 16 biti.
Registrele de control T/C(TCCR1A/B) sunt registre de 8 biti si nu au restrictii de acces CPU. Rolul lor este de-a configura Timerul pentru un anumit mod de functionare. Toate intreruperile sunt activate/dezactivate individual in TIMSK( nu sunt prezentati in figura deoarece aceste registre sunt folosite si de alte unitati timer). T/C este incrementat intern prin intermediul ceasului dat de unitatea de prescaler, sau de catre o sursa externa de ceas conectata la pinul T1. Bloc-ul logic de selectare a ceasului controleaza ce sursa de ceas este folosita sau limita pana la care T/C numara. T/C este inactiv cand nu este selectata nici o sursa de ceas.
Registrele de comparare ale output-ului (OCR1A/B) sunt comparate cu valoarea T/C la fiecare incrementare a acestuia. Rezultatul comparatiei poate fi folosit de catre generatorul de unde pentru a genera un semnal PWM la pinul de Comparare a Output-ului(OC1A/B). Operatia de comparare va seta si semnalul de potrivire-comparare (OCF1A/B) la generarea unei cereri de intrerupere de comparare output.
Valoarea TOP poate fi desemnata astfel incat sa fie una din aceste valori fixe: 0x00FF, 0X01FF, 0X003FF sau valoarea memorata in registrele OCR1A sau ICR.
TCNT1, OCR1A/B si ICR1 sunt registre de 16 biti care pot fi accesate de catre AVR CPU cu ajutorul bus- ului de date de 8 biti. Un registru de 16 biti poate sa sa fie accesat folosind doua operatii, fie de scriere, fie de citire pe 8 biti. Pentru a executa o scriere de 16 biti, byte-ul HIGH trebuie sa fie scris inaintea byte-ului LOW (bug de compilator, nu feature hardware).
SRAM-ul este in esenta memoria cu care este inzestrat cipul(ATmega16) . In timp ce registrele generale sunt folosite pentru operatii, SRAM-ul este folosit pentru a depozita date in timpul executiei. Ca sa putem utiliza SRAM-ul trebuie sa stim cateva aspect legate de spatial de adresare, de directivele asm si instructiunile care opereaza pe SRAM. Toate locatiile din memorie pot fi accesate fie direct fie indirect.
In cazul incarcarii in memorie sau din memorie de la o adresa directa stim exact de unde sau unde sunt datele. Exemplu: Folosind adresa 0x60 ca sa adresam valoarea dintr-un byte(de la adresa “digit”), putem folosi instructiunile sts si lds.
lds r16, digit ; (incarcam in registrul general r16 continutul de la adresa 0x60 din memoria SRAM ) sts digit,r16 ; (punem valoarea din registrul general r16 in SRAM la adresa digit)
Adresarea indirecta se face similar cu cea cu ajutorul pointerilor in C sau Pascal: perechile de registre pointeri (r26:r27 sunt numiti X, r28:r29 Y, r30:r31 Z) pot fi folositi sa faca referire la spatial de adresare AVR. Daca de exemplu X(r28:r29) ia ca valoare 0x60 el va pointa la “digit” si poate fi folosit pentru a face diferite operatii pe valoarea lui “digit”.
ldi XL, 0X60 ; incarcam in r26(XL) cu valoarea low(0x60) ldi XH, 0X00 ; incarcam in r27(XH) cu valoarea high(0x60) ld r16,X ; incarca in r16 valoarea la care pointeaza X
In diagrama de mai sus observam ca prima adresa de SRAM este 0x60. Exemplu ( diferenta intre adresarea indirect si adresarea directa):
Stim ca registrul de I/O PORTA se gaseste in tabelul de registre :
</latex> cum f(t) este o forma de unda dreptunghiulara valoarea sa maxima se atinge pentru 0<t<D*T. Tipuri de PWM
Multe circuite digitale pot genera semnale PWM. Majoritatea microcontrollerelor dispun de aceasta facilitate. Pentru a implementa o asemenea facilitate ele se folosesc de un numărator care este incrementat periodic (conectat direct sau indirect la o unitate de ceas) si care este resetat la sfarsitul fiecărei perioade a PWM-ului. Cand valoarea numaratorului este mai mare decat valoarea de referinta, iesirea PWM(output-ul) trece din starea inalta in stare joasa (sau invers).
In schema de mai sus este reprezentat schematic suportul hardware pe care trebuie sa-l interfatam in acest laborator.Dupa cum se observa, cu ajutorul microcontrollerului si mai precis folosind facilitatile oferite de: sistemul de intreruperi, timere, memoria microcontrollerului, vom interfata un afisaj cu leduri, un buzzer(sounder in schema) si doua butoane.