Sunteți pe pagina 1din 10

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;
 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:

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
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
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-1
void 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);
}
Transmiterea Datelor in modul USART
Transmiterea 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;
}

Flagul de receptia si Intreruperile


Receptorul 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 ceas
Pentru 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);
Codul programului:
#ifndef _SERIALA_H
#pragma device_specific_function putchar
void 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;
}
//ADC initialize
// Conversion time: 75uS
void 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: Disabled
void 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 peripherals


void 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;
init_devices();
//insert your functional code here...
PORTC = 0xFF;
while(1)
{
buff = getchar();

buffi = buff-0x30;
if(buffi > 0x09 || buffi <0x00)
PORTC = 0xFF;
else
PORTC = buffi;
putchar(buff);
//printf("\n\rtest");
adc0 = ReadADC(0); //citeste de pe canal 0
printf("\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;
}

S-ar putea să vă placă și