miercuri, 30 iulie 2014

Scoala de vara Lectia 4 - Arhitectura microcontrollerului, intreruperi.

Cand ne gandim la arhitectura microcontroller-ului ne referim la structura ei pe module si cum interactioneaza pentru realizarea executiei instructiunilor. ca componente ale arhitecturii unui microcontroller vom evidentia: memoria de programe, contorul de program, decodificatorul de comenzi, unitatea aritmetico logica, registrul de stare, bus de date, memoria RAM, Memoria EEPROM,, registri de uz general, registri periferici i module periferice.
Pe scurt, executia unei instructiuni in cadrul arhitecturiise realizeaza in felul urmator:
Instructiunea este selectata de catre Program counter, din memoria de programe si transmisa catre decodificatorul de comenzi, pentru a fi interpretata, Decodificatorul de comenzi descifreaza comanda si configureaza sistemul pentru realizarea instructiunii in dependeta de valoarea bitilor din registrul de stare al operatiilor. insa fiecare instructiune se executa in modul sau, in dependenta de grupul din care face parte.
Vom evidentia trei grupuri principale de instructiuni : 
a. Operatii  de control - pentru realizaea ramificarilor si apel de subrutine
b. Operatii aritmetico-logice - pentru calcule
c. Operatii de transfer:- pentru asigurarea transferului de date intre modulele Microcontrollerului



Intrerupere vom numi procesul de intrerupere a executiei normale a programului pentru realizarea unei probleme prioritare.

  Majoritatea modulelor periferice sunt capabile sa genereze situatii de intrerupere, care la rindul lor vor apela automat,  la nivel hardware, o subrutina de prelucrare a acestei situatii, daca modulul este configurat pentru acest lucru.
Mai mult decat atat, vom constata ca functia principala main este de fapt o subrutina de prelucrare a intreruperii reset, care se apeleaza automat la caderea nivelului pe pinul RESET al microcontrollerului sau la situatia POWER-ON RESET.
In mod normal subrutina de prelucrare a intreruperii nu poate fi intrerupta de catre alta subrutina de intrerupere, insa aceasta proprietate poate fi exlusa prin setarea bitului global de permisiune a intreruperilor. Deci, in functia main, dupa initializarea sistemului si imediat inainte de bucla infinita se va seta bitul global de permisiune a intreruperii prin functia sei(), permitand ca alte intreruperi sa intrerupa bucla infinita a programului.
Intreruperea Externa este cel mai simplu modul periferic ce poate genera intrerupere, aceasta fiind generata de la modificarea starii pinului rezervat acestei intreruperi.



Surse de informare suplimentare:  


Aplicatie practica:

Schimbarea starii unui LED in opus la apasarea detectarea apasarii unui buton conectat la intreruperea externa, algoritmul de schimbare a starii fiind identic cu cel realizat in aplicatia precedenta, vezi mai sus.
In ciclul principal al programului, va rula o aplicatie de licarire a unui led. La apasarea tastei si mentinerea acestea se va observa ca licarirea nu este influientata, fapt ce demonstreaza ca prelucrarea intreruperii nu afecteaza ciclul principal cu conditia ca in intrerupere nu se realizeaza bucle de asteptare.



#include <avr/io.h> // includem libraria de definire

// a periferiilor
#include <util/delay.h> // includem libraria pentru retineri
#include <avr/interrupt.h> // libraria de lucru cu intreruperile


#define LED_1_MASK 1<<PIN5 // Masca pentru ledul testat

// in intrerupere
#define LED_2_MASK 1<<PIN3 // masca pentru ledul de licarire
// in bucla infinita

// Subrutina de initializare a intreruperii de la pinul EXT_INT0
InitInt0(){
GICR= 1<<INT0; // activarea intreruperii de la 
// pinul EXT_INT0
MCUCR=1<<ISC01|0<<ISC00; // setarea modului de detectie a
// intreruperii pe front cescrtescator
}


// subrutina de prelucrare a intreruperii de la pinul EXT_INT0

ISR(INT0_vect){


if(PORTA & LED_1_MASK ) // verifica starea curenta a ledului

PORTA &=~LED_1_MASK; // stinge LED daca e aprins
else // daca testule FALSE (LED stins)
PORTA |= LED_1_MASK; // aprinde ledul
}



int main(void){ // functia principala a programului

// ea fiind totodata subrutina de prelucrare 
// a intreruperii RESET


// parte de initializare a programului



// setarea pinilor pentru leduri spre iesire 

DDRA = LED_1_MASK | LED_2_MASK ;


// activare pull-up pe pinii neutilizati 

// si stingerea ledurilor conectati la pinii selectati
PORTA = 0xFF & ~(LED_1_MASK |LED_2_MASK );


DDRD = 0x00; // setarea portului butonului spre intrare  

PORTD = 0xFF; // activarea rezistentelor de pull-up
// inclusiv pe pinul butonului
InitInt0(); // initializarea intreruperii externe
sei(); // setarea bitului global de 
// permisiune a intreruperilor


// partea de procesare a programului 



while(1){ // bucla infinita de control



PORTA ^= LED_1_MASK; // schimbarea starii ledului in opus

_delay_ms(300); // retinere pentru a observa licarirea
 
} // sfaarsit bucla infinita
} // sfatist functia main - program