Sunteți pe pagina 1din 11

Ministerul Educatiei al Republicii Moldova

Universitatea Tehnica a Moldovei


Facultatea Calaculatoare, Informatica si Microelectronica
Catedra Microelectronica si Ingineria Biomedicala

Raport
La disciplina: Microprocesoare
Lucrare de laborator Nr.7

Tema: Modului periferic ADC

A efectuat: str.gr.MN-131,Ignat Ion

A verificat: lec. as., Eugeniu Lazari

2015
Scopul lucrarii: Obinerea cunotinelor practice i deprinderilor de a opera cu
convertorul analogic - digital ntr-un microcontreller din familia AVR.

Definiia problemei:
S se elaboreze un dispozitiv care n dependen de valoarea semnalului Analogic la
una din intrrile analogice a microcontrollerului s indice nivelul semnalului pe
indicatoare pe 7 segmente.
Date teoretice:
Modulul Convertor Analog-Digital este utilizat pentru conversia tensiunii analogice
ntr-o valoare digital (n AVR pe 10 bii). De exemplu, poate fi utilizat pentru perceptarea
ieirii de la un senzor (de temperatur, presiune, etc.) n anumite intervale, sau pentru a
executa anumite aciuni n dependen de valoarea primit. Exist mai multe tipuri de
convertoare, dar cele utilizate n microcontrollerele AVR sunt convertoarele cu
aproximare succesiv. Mai jos urmeaz o schem simplificat a convertorului analog-
digital prezent pe AVR:

Fig. 1 Schem simplificat a convertorului analog-digital


La intrare avem un multiplexor analog-digital, care este utilizat la selectarea ntre opt intrri
analogice diferite. Aceasta nseamn c este posibil conversia a opt semnale (bineneles c nu
n acelai timp). La ieire, valoarea convertit este nscris n regitrii ADCL i ADCH, deoarece
regitrii AVR au lime de 8 bii este nevoie de o pereche p-u a stoca o valoare pe 10 bii.
ADCH:L= ((Vin/Vref)*1023)
Deoarece convertorul are o rezoluie de 10 bii, avem 1024 valori posibile, adic dac
tensiunea de intrare Vin este egal cu 0, atunci valoarea convertit v-a fi zero, dac Vin este
egal cu Vref atunci valoarea convertit v-a fi 1023, iar dac Vin este din Vref atunci valoarea
ADCH:L este 512. Acest proces de conversie se mai numete cuantificare, bineneles ce produce
o eroare, numit eroare de cuantificare.

Regitrii de stare i control ai CAD


CAD conine 4 regitri de I/O:
ADMUX ADC Multiplexer Select Register
ADCSR ADC Control and Status Register
ADCH:L ADC Data Register(High, Low)
Tabel 1. Regitrii de control a ADC-ului

Tab. 2. ADMUX

ADMUX
Acest registru este utilizat pentru selectarea unuia din cele 8 canale care va fi convertit.
Tabelul de mai jos arat setrile posibile ale acestui registru:

Tab. 3 Setrile posibile ale ADMUX

Fig.2. Formatul registrului ADCSRA(ADCSR)

Tab. 4 Registrul ADCSR

ADEN ADC Enable, setnd bitul dat n "1" este pornit CAD, iar n "0" CAD este oprit.
Oprind CAD n timpul unei conversii va duce la anularea conversiei date.
ADSC ADC Start Convertion, n regim de conversie continu va fi necesar de setat acest
bit doar la prima conversie, conversiile urmtoare v-or fi pornite automat. n regim de conversie
unar acest bit trebuie setat la fiecare conversie necesar. Acest bit se seteaz n "0" automat la
sfritul oricrei conversii.
ADFR ADC Free Running Mode, se seteaz n "1" la conversie continu.
ADIF ADC Interrupt Flag, acest bit este setat automat n 1 la finisarea unei conversii,
sau este setat automat n "0" doar la executarea ISR corespunztor vectorului de ntreruperi,
alternativ poate fi setat n "0" nscriind "1" n acest bit.
ADIE ADC Interrupt Enable, cnd este setat n "1" i SREG(I)=1 la apariia ADIF se
cheam ISR corespunztoare din vectorul de ntreruperi.
ADPS2:0 ADC Prescaler Select, aceti bii determin factorul de dividere a frecvenei
de clock pentru CAD, tabela de mai jos arat valorile posibile:

Exactitatea maxim a conversiei se obine, dac frecvena de tact a modulului ADC e


cuprins ntre 50...200kHz. respectiv coeficientul scalrii trebuie de ales n aa mod, ca frecvena
ADC-ului s se afle n acest diapazon. Dac ns exactitatea conversiei e mai mic de 10 bii e
destul, se poate de utilizat o frecven mai mare, mrind astfel frecvena msurrii. n modelele
ATmega8x, ATmega16x, ATmega64x i ATmega128x pentru acest scop se utilizeaz bitul
ASCHM din registrul SFIOR. La setarea lui n 1 viteza de conversie se mrete. ns
concomitent crete i consumul de energie a microcontrollerului.

Fig.3. Formatul registrului ADCSRB

Fig.4. Formatul registrelor ADCH i ADCL

Aceti regitri conin ultima valoare convertit, ADCH biii ADC9:8, ADCL biii ADC7:0.
Cnd ADCL este citit datele din ADCH nu sunt modificate pn cind nu se citete i ADCH, adic
este esenial ca ambii regitri s fie citii n acelai timp adic ADCL se citete naintea ADCH.
Seria ATMEGA conin un CAD mai complex, care are aceleai funcii de baz dar i anumite
posibiliti mai avansate ca:
apte Canale de intrare difereniale;
Dou Canale de intrare difereniale cu amplificare 10x i 200x;
Ajustarea la stnga a regitrilor ADCH:L (p-u rezoluie de 8 bii);
Tensiune de referin selectabil de 2.56V;

Modul de lucru:

1) Formarea schema bloc de functionare a programului.


ISR(ADC_vect)

Volt =
ConvertDataToVoltage()

Adevar Fals
ind == 0

ADC_MUX_Select(1); ADC_MUX_Select(0);
ind = 1; ind = 0;
V[0] = Volt; V[7] = Volt;

retur
Fig9 schema bloc ISR(ADC_vect)
n
2) Proiectam schema electrica pentru simulare in PROTEUS

Figura10 Shema electrica simulata in proteus

3)Scrierea Driver-ului pentru ADC

adc.h
#ifndef ADC_H_
#define ADC_H_

#include "main.h"
void ADC_Enable();
void ADC_Desanable();
void ADC_Start();
unsigned ADC_Isbusy();
void ADC_AutoTrigEnable();
void ADC_AutoTrigDisable();
void ADC_ISR_Enable();
void ADC_ISR_Disanable();
void ADC_Prescaler_Select(uint8_t);
void ADC_MUX_Select(char);
int Colect_Data();
void ADC_MUX_Ref (char);
#endif
adc.c
#include "main.h"

//PORTD &= ~(1<<7)

void ADC_Enable()
{
ADCSRA |=(1<<ADEN);
};
void ADC_Desanable()
{
ADCSRA &=~(1<<ADEN);
};
void ADC_Start()
{
ADCSRA |= (1 << ADSC);
};

unsigned char ADC_Isbusy()


{
if(ADCSRA & 1<<ADSC)
return 1;
else
return 0;
};
void ADC_AutoTrigEnble()
{
ADCSRA|=(1<<ADATE);
};
void ADC_AutoTrigDisable()
{
ADCSRA &= ~(1<<ADATE);
};
void ADC_ISR_Enable()
{
ADCSRA |= (1 << ADIE);
}
void ADC_ISR_Disanable()
{
ADCSRA &= ~(1 << ADIE);
}
void ADC_Prescaler_Select(char pins)
{
ADCSRA |= ((ADCSRA & 0XF8) | pins);
}
void ADC_MUX_Select (char pins)
{
if (pins == 0)
{
ADMUX = ADMUX & 0XF8;
}
else
{
ADMUX |= ((ADMUX & 0XF8) | pins);
}
}
void ADC_MUX_Ref (char pins)
{
ADMUX |= ((ADMUX & 0X3F) | pins);
}
int Colect_Data()
{
int adcRes;
adcRes = ADCL;
adcRes |= (int)(ADCH << 8);
return adcRes;
}
4)Scriem codul programului

#include <avr/io.h>
#include <avr/interrupt.h>

#define F_CPU 1000000


#define DIV 64
#define F_T0 F_CPU/DIV
#define F_INT 200
#define TCNT0_init (256 - F_T0/F_INT)
#define ADC_MAX 1023
#define VOLT_MAX 5
unsigned char V[8] = {0,0,0,0,0,0,0,0};
unsigned char ind = 0;
unsigned char indicator = 8;
unsigned char cifra[10]= {252,96,218,242,102,182,190,224,254,246};

void Afisare()
{
switch (indicator)
{
case 0:
PORTD |= (1<<1);
PORTB = cifra[V[indicator]];
PORTD &= ~(1<<2);
break;
case 1:
PORTD |= (1<<2);
PORTB = cifra[V[indicator]];
PORTD &= ~(1<<3);
break;
case 2:
PORTD |= (1<<3);
PORTB = cifra[V[indicator]];
PORTD &= ~(1<<4);
break;
case 3:
PORTD |= (1<<4);
PORTB = cifra[V[indicator]];
PORTD &= ~(1<<5);
break;
case 4:
PORTD |= (1<<5);
PORTB = cifra[V[indicator]];
PORTD &= ~(1<<6);
break;
case 5:
PORTD |= (1<<6);
PORTB = cifra[V[indicator]];
PORTD &= ~(1<<7);
break;
case 6:
PORTD |= (1<<7);
PORTB = cifra[V[indicator]];
PORTD &= ~(1<<0);
break;
case 7:
PORTD |= (1<<0);
PORTB = cifra[V[indicator]];
PORTD &= ~(1<<1);
break;
}
if (indicator <= 0)
{
indicator = 8;
}
indicator--;
asm("nop");

int ConvertDataToVoltage()
{
int Voltage = (Colect_Data() * VOLT_MAX)/ADC_MAX;
return Voltage;
}

ISR(ADC_vect)
{
int Volt = ConvertDataToVoltage();
if (ind == 0)
{
ADC_MUX_Select(1);
ind = 1;
V[0] = Volt;
}
else
{
ADC_MUX_Select(0);
ind = 0;
V[7] = Volt;
}
ADCSRA |= (1 << ADSC);
}
void Port_init()
{
DDRA = 0x00;
PORTA = 0xFF;
DDRB = 0b11111111;
PORTB = 0b00000000;
DDRC = 0b11111111;
PORTC = 0b00000000;
DDRD = 0Xff;
PORTD = 0b00000000;
}
void ADC_init()
{
ADC_Enable();
ADC_AutoTrigEnble();
ADC_ISR_Enable();
ADC_Prescaler_Select(0b00000011);
ADC_MUX_Ref (0b01000000);
ADC_Start();

}
ISR(TIMER0_OVF_vect)
{
TCNT0 = TCNT0_init;
Afisare();
}
void TIMER0_init()
{
TCNT0 = TCNT0_init;
TIMSK |= (1<<TOIE0);
TCCR0 |= (1 << CS01);

int main(void)
{
Port_init();
ADC_init();
TIMER0_init();
sei();
while(1)
{
asm("nop");
}
}

Concluzie:In urma efectuarii laboratorului dat am studiat si am aplicat in


practica modului periferic ADC. In concluzii putem spune ca ADC-ul are un
rol important intr-un procesor, fiindca el ne permite sa masuram si sa
pastram semnalul analogic.

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