ATmega128 microcontroller pe 8

14
Proiect AOC In acest proiect se va achizitiona un semnal de la senzorul de temperatura aflat pe modulul de laborator si se va transmite informatia catre ledurile aflate pe acelasi modul. Modulul de laborator include un microcontroller ATMega128, iar pentru realizarea proiectului se va folosi ADC-ul, Timer-ul si USART-ul. In continuare avem o descrierea a microcontrolerului si cateva caracterisitici. Nucleul AVR combina un set bogat de uz de instructiuni cu 32 registre de lucru. Toate cele 32 de registre sunt direct conectate la Unitatea Aritmetica si Logica (ALU), permitand pe o singura instructiune intrun singur tact accesarea simultana a 2 registre independente. Rezultatul este o arhitectura ce ruleaza foarte eficent, fiind de pana la 10 ori mai rapida decat arhitectura CISC. Dispozitivul este fabricat folosind tehnologia Atmel de cel mai inalt nivel. Chipul ISP permite chipului sa fie reprogramat pe interfata seriala SPI, sau ca un program bootabil in codul AVR. Programul de boot poate folosi orice interfata pentru a descrca inforamtia in memoria Flash. Softul din memoria flash bootabila va continua sa ruleze in timp ce aplicatia Flash este updatata, oferinf o adevarata operatiune citeste in timp ce scrie. Atmega128 AVR este prevazut cu o suita completa de program si instrumente de dezvoltare de sistem: compilator C, macroassamblor, simlator de program, circuite emulatoare si evaluarea kitului. O mica descrie: Un microcontroler de mare performanta cu consum redus pe 8 biti; Arhitectura RISC avansata ;

Transcript of ATmega128 microcontroller pe 8

Page 1: ATmega128 microcontroller pe 8

Proiect AOC

In acest proiect se va achizitiona un semnal de la senzorul de temperatura aflat pe modulul de laborator si se va transmite informatia catre ledurile aflate pe acelasi modul.

Modulul de laborator include un microcontroller ATMega128, iar pentru realizarea proiectului se va folosi ADC-ul, Timer-ul si USART-ul. In continuare avem o descrierea a microcontrolerului si cateva caracterisitici.

Nucleul AVR combina un set bogat de uz de instructiuni cu 32 registre de lucru. Toate cele 32 de registre sunt direct conectate la Unitatea Aritmetica si Logica (ALU), permitand pe o singura instructiune intrun singur tact accesarea simultana a 2 registre independente. Rezultatul este o arhitectura ce ruleaza foarte eficent, fiind de pana la 10 ori mai rapida decat arhitectura CISC.

Dispozitivul este fabricat folosind tehnologia Atmel de cel mai inalt nivel. Chipul ISP permite chipului sa fie reprogramat pe interfata seriala SPI, sau ca un program bootabil in codul AVR. Programul de boot poate folosi orice interfata pentru a descrca inforamtia in memoria Flash. Softul din memoria flash bootabila va continua sa ruleze in timp ce aplicatia Flash este updatata, oferinf o adevarata operatiune citeste in timp ce scrie.

Atmega128 AVR este prevazut cu o suita completa de program si instrumente de dezvoltare de sistem: compilator C, macroassamblor, simlator de program, circuite emulatoare si evaluarea kitului.

O mica descrie: Un microcontroler de mare performanta cu consum redus pe 8 biti; Arhitectura RISC avansata ; 128K Bytes de memorie flash autoprogramabila ; 4K Bytes memorie EEPROM; 4K Bytes memorie interna SRAM; Pastrarea datelor pe o perioada de 20 de ani la 85°C / 100 ani la 25°C; Optional sectiune de cod bootabil cu blocarea independenta a bitilor; Pana la 64K Bytes memorie externa optionala; Blocarea programului pentru securitatea softului; Interfata SPI pentru programare; Interfata JTAG ; 2 timere pe 8 biti cu moduri separate prescalare si comparare; 2 timere extinse pe 16 biti; Numarator in timp real cu oscilator extern; 6 canale PWN cu programare de la 2 la 16 biti; 8 canale ADC pe 10 biti; 2 seriale programabile USART ; Interfata seriala SPI Master/Slave;

Page 2: ATmega128 microcontroller pe 8

Ceas de garda programabil cu oscilatorul intern; Calibrare interna RC; Sursa de intreruperi externa si interna; Tensiune recomandata : 4.5 - 5.5V; Oscilator intre 0 – 16MHz;

Configuratia pinilor:

Descrierea ADC-ului:

Page 3: ATmega128 microcontroller pe 8

ADC transforma un semnal de intrare analogic intro valoare digitala pe 10 biti prin aproximari succesive. Valorea minima este reprezentata de GND (ground), iar valoarea maxima este reprezetata de valoarea pinu-ului AREF minus LSB. Optinal AVCC sau referinta interna de 2.56V poate fi conectata la pin-ul AREF adaugand la biti REFS din registrul ADMUX. Tensiunea interna de fererinta poate fi deconectate prin capacitor extern din pinul AREF pentru a imbunatati imunitatea zgomotelor.

Canalele cu intrarea analogica si etajele diferentiale sunt selectate scriind in ADMUX biti MUX. Oricare din pinii de intrare ADC , ca GND si referinta interna de tensiun pot fi selectate ca intrari singulare pentru ADC. Selectia pinilor de intrare ADC pot fi selectate ca intrari pozitive sau negative a amplificarii diferentiale.

ADC-ul este pornit selectand biti de activare ADC, ADEN in ADCSRA. Tensiunea de referinta si selectia canalelor de intrare nu vor fi afectate pana cand ADEN nu este setat. ADC-ul nu consuma putere cand ADEN este nesetat, deci este recomandat sa se opreasca ADC-ul inainte de a intrare in modul de standby.

ADC-ul genereaza un un rezultat pe 10 biti care este scris in registrele de date ADC, ADCH si ADCL. Daca rezutlatul este lasat si nu este nevoie de o precizie mai mare de 8 biti este suficient pentru a citi ADCH-ul. Altfel ADCl-ul trebuie citit primu, apoi ADCH-ul pentru a ne asigura ca, continul datelor apartine aceleasi conversii. O data ce ADCL este citit, accesul ADC-ului la datele din registru este blocat.Asta inseamna ca daca ADCL-ul a fost citit, si daca o conversie complete inainte de ADCH este citita, nici un registru nu este updatat si rezultatul conversiei este pierdut. Cand ADCH-ul este citit, accesul ADC la registrele ADCH si ADCL este repornit.

ADC-ul are intreruperile proprii care pot fi trigerate cand conversia este completa. Cand accesul ADC-ului la datele din registru sunt interzice intre citirea dintre ADCH si ADCL, intreruperile vor fi trigerate chiar daca rezultatul va fi pierdut.

Startul unei conversii:O singura conversie este pornita scriind unu logic la bitul de start al ADC-ului,

ADSC. Bitul sta in stare high atat timp cat conversia este in progres and si va fi curatat de partea harware cand conversia este completa. Daca este selectat alt canal de date cand conversia este in proges, ADC-ul va termina conversia curenta inainte de schimbarea canalului.

In mod normal, ADC-ul este updatea constant datele din registul ADC. Modul normal de lucru este instituit scriid bitul ADFR in ADCSRA cu unu. Prima conversie ar trebui pornita scriind unu logic la bitul ADSC in ADCSRA. In acest mod ADC-ul va face conversii succesive independente de orice flag de intrerupere ADC, chiar daca ADIF este zero sau nu.

Prescalare si Momentul de conversie

Page 4: ATmega128 microcontroller pe 8

Implicit, circuitul de aproximari succesive necesita la intrare o frecventa de ceas intre 50 kHz si 200 kHz, pentru a avea rezoltuie maxima. Daca este suficienta o rezolutie mai mica de 10 biti, intrarea de ceas a ADC-ului poate fi mai mare de 200 kHz pentru a obtine o rata mai mare de esantionare. Modulul ADC contine un prescalar, care genereaza o frecventa acceptabila de ceas de la orice procesor cu frecventa in jurul valorii de 100 kHz. Prescalarul este setat de catre botul de ADPS din ADCSRA. Prescalarul incele numararea din momentul din care ADC-ul este pornit, adica cand este setat bitul ADEN din ADCSRA. Prescalarul continua sa functioneze atat timp cat bitul ADEN este setat in unu si este resetat continuu atat timp cat ADEN este in zero.

O conversie normala este realizata in 13 tacte de ceas. Prima conversie ADC, dupa ce ADC-ul este pornit, se realizaeaza in 25 de tacte de ceas, deoarece este necesar un timp de initializarea a circuitului analog. Esantionarea efectiva are loc dupa 1.5 tacte de ceas dupa ce pornirea unei conversii normale si dupa 13.5 tacte de la pornirea primei conversii. Cand o coversie este completa, rezultatul este scris in registrul de date ADC si ADIF este setat. In modul singular de conversie ADSC este curatat simultan. Softul poate selecta mai apoi ADSC-ul din nou, si si conversia va fi initiata pe panta crescatoare a clock-ului ADC.

USART – The Universal Synchronous and Asynchronous serial Receiver and Transmitter

Atmega128 are 2 USART, USART0 si USART1. Functionalitatea pentru ambele USART-uri este descrisa in continuare. USART0 si USART1 au registre diferite de I/O.

Generatorul de ceas. Ceasul logic genereaza baza ceasului pentru transmitere si primirea datelor.

USART suporta, pentru ceas, 4 moduri de operare: Normal Asincron, Asincron cu viteza dubla, Master Sincron si Slave Sincron. Bitul UMSEL din UCSRC face selectia intre modul de operare asincron si sincron. Ceasul cu viteza dubla este controlat de U2X ce se gaseste in registrul UCSRA. Cand se foloseste modul sincron , adica UMSEL=1, pinul

Page 5: ATmega128 microcontroller pe 8

XCK controleza daca generatorul de ceas este intern (master mode) sau extern (slave mode). Pinul XCK este activ doar daca se foloseste modul sincron.

Initializarea USART:USART trebuie initializat inainte de inceperea comunicarii. Procesul de

initializare consta in mod normal in stabilirea ratei de transfer, stabilind formatul cadru si activand transmiterea sau receptionarea datelor, in functie de utilizare. Pentru intreruperea produsa de USART, flagul de intreruperile globale trebuie sa fie gol (intreruperile globale fiind dezactivate), cand se face initializarea.

Urmatoarul cod C este pentru initializarea USART-ului. Exemplul descrie modul de operare asincron, folosind un proces de votare (fara flag de intreruperi) si un cadru fix. Banda de transfer este data ca si parametru de functionare.

#define FOSC 1843200// Clock Speed#define BAUD 9600#define MYUBRR FOSC/16/BAUD-1void main( void ) { ... USART_Init ( MYUBRR ); ... }void USART_Init( unsigned int ubrr ) { /* Set baud rate */ UBRRH = (unsigned char)(ubrr>>8); UBRRL = (unsigned char)ubrr; /* Enable receiver and transmitter */ UCSRB = (1<<RXEN)|(1<<TXEN); /* Set frame format: 8data, 2stop bit */ UCSRC = (1<<USBS)|(3<<UCSZ0); }

Page 6: ATmega128 microcontroller pe 8

Transmiterea Datelor in modul USARTTransmiterea in modul USART este activata prin setarea bitului TXEN din

registru UCSRB. Cand transmisia este activata, portul normal de operare a pinului TxD este suprascris de USART si primeste functia de interfata seriala de iesire.

Trimiterea datelor cu o lungime de biti intre 5 si 8. O transmisie de data este initializata incarcand in bufferul de trasmisie datele ce trebuiesc transmise. Procesorul poate incarcar in bufferul de transmisie a datelor scriind la UDR I/O. Datele din buffer de transmisie nu vor fi mutate in registrul de shiftare cand acesta este gata de a transmite un nou cadru. Registrul de shiftare este incarcat cu date noi daca este in stare idle (fara transmisii la iesire), sau imediat dupa ultimul bit de stopa a cadrului anterior. Cand registrul de shiftare este incarcat cu date noi, se va transfera un cadru complet la rata de transfer a benzii de transfer, bitul U2X sau XCK in functie de modul de operare.

Mai jos este un cod simplu de transmitere a datelor prin USART.

void USART_Transmit( unsigned char data ) { /* Wait for empty transmit buffer */ while ( !( UCSRA & (1<<UDRE)) )

; /* Put data into buffer, sends the data */ UDR = data;

}

Recetia datelor folosind USART Receptia datelor prin USART este activa setand cu unu bitul de RXEN (Receive

Enable) din registrul UCSRB. Cand receptia este activa, pe pinul RxD este suprascris de catre USART si se seteaza modul de transmitere a datelor. Daca este folosit modul sincron, ceasul din pinul XCK este folosit ca ceas de transfer.

Receptia datelor cu o lungime de biti intre 5 si 8. Receptia datelor incepe in momentul in care se detecteaza un bit valid de start. Fiecare bit care urmeaza dupa bitul de start sunt prelevate sapeluri la rata de transfer sau la rata ceasului XCK si sunt shiftate in registrul de receptie pana la primirea primului bit de stop. Cel de-al doilea bit de stop va fi ignorat. Cand este primit primul bit de stop, un intreg sir de data este receptionat in registrul de shiftare si receptie, iar continului acestui registru va fi mutat in bufferul de receptie. Bufferul de receptie poate fi citit, citind locatia UDR-ului.

Urmatorul cod descrie o receptie simpla a datelor folosind USART.

unsigned char USART_Receive( void ) { /* Wait for data to be received */ while ( !(UCSRA & (1<<RXC)) ) ; /* Get and return received data from buffer */ return UDR;

Page 7: ATmega128 microcontroller pe 8

}

Flagul de receptia si IntreruperileReceptorul USART are un flag care indica starea datelor

receptionate. Flagul RXC indica daca sunt prezente date necitite in bufferul de rectie. Flagul este unu cand exista date necitite in bufferul de receptie si zero cand bufferul de receptie este gol (nu contine date necitite). Daca receptia este dezactivar (RXEN = 0) bufferul de receptie va fi curatat si in cosecinta RXC va deveni zero.

Oscilatorul de ceasPentru controlerul AVR cu oscilator de ceas (pini TOSC1 si

TOSC2), cristalul se conecteaza intre cei doi pini. Nu este necesar nici un condensator extern. Oscilatorul este optimizat pentru a folosi o frecventa de 32.768 kHz. Aplicarea unui ceas extern pinului TOSC1 nu este recomandata

Intai se realizeaza initializarea circuitelor prin rutina init_devices(); Citirea de la un canal al ADC-ului se realizeaza cu ajutorul unei functii separate

int ReadADC( unsigned char channel)

La generarea inreruperii de sfarsit de numarare, se executa rutina de servire a intreruperii Timerului 1:

void timer1_ovf_isr(void)

Timerul se incarca cu valoarea de numarare care va fi aceeasi ca la initializare pentru a genera in intreruperea cu frecventa de 1Hz continuu:

TCNT1H = 0x57;TCNT1L = 0x41;

In vederea transmiterii valorii temperaturii de la senzor, se citeste aceasta valoare de la iesirea ADC-ului, dupa care se transmite pe interfata seriala asincrona:

int i = ReadADC(0);printf("\r\n%d", i);

Page 8: ATmega128 microcontroller pe 8

Codul programului:

#ifndef _SERIALA_H#pragma device_specific_function putcharvoid putchar( unsigned char data ){/* Wait for empty transmit buffer */while ( !( UCSR1A & (1<<UDRE1)) );/* Put data into buffer, sends the data */UDR1 = data;}

unsigned char getchar( void ){/* Wait for data to be received */while ( !(UCSR1A & (1<<RXC1)) );/* Get and return received data from buffer */return UDR1;}

#endif

//ICC-AVR application builder : 4/21/2010 9:56:00 AM// Target : M128// Crystal: 11.059Mhz

#include <iom128v.h>#include <macros.h>#include "Seriala.h"

void port_init(void){ PORTA = 0x00; DDRA = 0x00; PORTB = 0x00; DDRB = 0x00; PORTC = 0x00; //m103 output only DDRC = 0xFF; PORTD = 0x00; DDRD = 0x00; PORTE = 0x00; DDRE = 0x00; PORTF = 0x00; DDRF = 0x00; PORTG = 0x00; DDRG = 0x00;}

Page 9: ATmega128 microcontroller pe 8

//ADC initialize// Conversion time: 75uSvoid adc_init(void){ ADCSRA = 0x00; //disable adc ADMUX = 0x00; //select adc input 0 ACSR = 0x80; ADCSRA = 0xC6;}

//UART1 initialize// desired baud rate:115200// actual baud rate:115198 (0.0%)// char size: 8 bit// parity: Disabledvoid uart1_init(void){ UCSR1B = 0x00; //disable while setting baud rate UCSR1A = 0x00; UCSR1C = 0x06; UBRR1L = 0x05; //set baud rate lo UBRR1H = 0x00; //set baud rate hi UCSR1B = 0x18;}

//call this routine to initialize all peripheralsvoid init_devices(void){ //stop errant interrupts until set up CLI(); //disable all interrupts XDIV = 0x00; //xtal divider XMCRA = 0x00; //external memory port_init(); uart1_init(); adc_init();

MCUCR = 0x00; EICRA = 0x00; //extended ext ints EICRB = 0x00; //extended ext ints EIMSK = 0x00; TIMSK = 0x00; //timer interrupt sources ETIMSK = 0x00; //extended timer interrupt sources SEI(); //re-enable interrupts //all peripherals are now initialized}void putchar(unsigned char);unsigned char getchar();int ReadADC( unsigned char);//void main(void){ unsigned char buff = 0x00; unsigned char buffi = 0x00; unsigned int adc0 = 0;

Page 10: ATmega128 microcontroller pe 8

init_devices(); //insert your functional code here... PORTC = 0xFF; while(1) { buff = getchar();

buffi = buff-0x30;if(buffi > 0x09 || buffi <0x00)

PORTC = 0xFF;elsePORTC = buffi;

putchar(buff);//printf("\n\rtest");adc0 = ReadADC(0); //citeste de pe canal 0printf("\n\r%d",adc0," ");

}}

int ReadADC( unsigned char channel){ //int i;

ADMUX = channel; // Select channel ADCSRA |= 0x40; // Start conversion while (!(ADCSRA & 0x10)); // Check if converstion is ready ADCSRA |= 0x10; // Clear Conversion ready flag by setting the bit

//i = ADCL; // Read 8 low bits first (important) //i += (int)ADCH << 8; // Read 2 high bits and multiply with 256

return ADC;}