Vaša IP adresa: 3.17.184.90
Počet návštev: 30511

Lekcia 5: AD prevodník

Dôležité registre

V tejto časti sú opísané niektoré registre súvisiace s interným AD prevodníkom, ktoré sú využité v príkladoch nižšie.

ADMUX - Register slúžiaci na nastavenie referencie AD prevodníka a na výber analógového kanála, ktorý bude pripojený k AD prevodníku.

  • Bity REFS1 a REFS0 slúžia na nastavenie referencie AD prevodníka podľa tabuľky, ktorá je uvedená nižšie. Ak na testovanie používate vývojovú dosku Mega Development Board, tak použite konfiguráciu REFS1=0 a REFS0=1. V schéme pre Mega Development Board je pin AVCC pripojený na pin VCC = 5V. Referenčné napätie je teda AVCC = 5V.

  • Bit ADLAR ovplyvňuje reprezentáciu výsledku AD konverzie v 16-bit registri ADC (uvedený nižšie). Ak ADLAR=1, tak je výsledok zarovnaný vľavo, inak je výsledok zarovnaný vpravo.
  • Bity MUX3MUX0 slúžia na výber analógového kanála ADC0ADC8, ktorý bude pripojený na vstup AD prevodníka. Vývojová doska Mega Development Board má vyvedené na svorkovnicu kanály ADC0 a ADC1.

ADCSRA - Riadiaci a stavový register AD prevodníka.

  • Bit ADEN povoľuje/vypína AD prevodník. Ak ADEN=1, tak je AD prevodník povolený. Ak je AD prevodník vypnutý počas konverzie (ADEN=0), tak sa ukončí prevod.
  • Bit ADSC spúšťa AD prevod. Zápis ADSC=1 spúšťa každý jeden prevod. Po dokončení prevodu sa automaticky vynuluje (ASDSC=0). Zápis ADSC=0 nemá žiadny vplyv.
  • Bit ADIF sa nastaví (ADIF=1) vtedy, keď je dokončený AD prevod a je aktualizovaný dátový register. ADIF je nulovaný automaticky (hardvérovo) v prípade uskutočnenia prerušenia pri dokončení prevodu (ADC Conversion Complete Interrupt), alebo softvérovo zápisom logickej jednotky (ADIF=1).
  • Bit ADIE aktivuje prerušenie pri dokončení prevodu (ADC Conversion Complete Interrupt).
  • Bity ADPS2ADPS0 nastavujú vstupnú frekvenciu AD prevodníka pomocou predeličky (Division Factor) systémovej frekvencie MCU. Nastavenie je uvedené v nasledujúcej tabuľke. Vstupná frekvencia AD prevodníka musí byť v rozmedzí 50 kHz - 200 kHz v prípade 10-bit rozlíšenia. Nastavenie frekvencie AD prevodníka sa preto odvíja od systémovej frekvencie MCU (ATmega328P má interný kryštál 8 MHz).

ADC - Register (16-bit) obsahujúci výsledok prevodu. Register sa skladá z dvoch 8-bit registrov ADCH (High) a ADCL (Low).V závislosti od nastavenia bitu ADLAR v registri ADMUX je výsledok prevodu zarovnaný vpravo alebo vľavo.

Výsledok ADC prevodu (obsah registra ADC) v prípade 10-bit rozlíšenia je vypočítaný podľa vzťahu:


Príklad č. 1

Príklad opisuje použitie interného 10-bitového AD prevodníka na digitalizáciu analógového napäťového signálu, ktorý je privádzaný k vstupu AD prevodníka ADC0 (PORTC0). Referencia AD prevodníka je 5V. Po privedení napätia 0V na vstup ADC0 sa na displeji rozsvieti číslo 0 a po privedení 5V sa na displeji rozsvieti číslo 5. Napätiu 0V zodpovedá najmenšia digitálna hodnota 0 a napätiu 5V zodpovedá najvyššia digitálna hodnota 1023. Keďže môže byť vstup AD prevodníka mierne zarušený, tak na displeji sa vypíše číslo 0, keď je digitálna hodnota menšia ako 100. Hodnota 5 sa rozsvieti v prípade, ak je digitálna hodnota väčšia ako 950. Ak sa digitálna hodnota bude nachádzať mimo týchto intervalov, tak displej zostane zhasnutý.

#include <avr/io.h>

void ADC_Init()//inicializacia AD prevodnika
{
ADMUX|=(1<<REFS0);//referencia na AVCC pine
//v scheme su piny VCC a AVCC prepojene -> referencia AD prevodnika = 5V

//digitalizujeme kanal ADC0 - prednastavena hodnota v registri ADMUX
ADCSRA|=(1<<ADPS2)|(1<<ADPS1);//predelicka 64 -> 125kHz
ADCSRA|=(1<<ADEN);//povolenie AD prevodnika
}

uint16_t StartPrevodu()//funkcia s navratovou hodnotou typu uint16
{
ADCSRA|=(1<<ADSC);//start prevodu
while ((ADCSRA&(1<<ADIF))==0) ; //caka na dokoncenie prevodu
ADCSRA|=(1<<ADIF);//nulovanie dokoncenia prevodu zapisom log.1
return ADC;//vysledok prevodu je v registri ADC
}

void ZhasniDisplej()
{
PORTB=255;//zhasne displej (vsetky segmenty)
}

void RozsvietNulu()
{
PORTB=(1<<PORTB6);//zhasne segment G
}

void RozsvietPatku()
{
PORTB=(1<<PORTB1)|(1<<PORTB4);//zhasne segmenty B a E
}

int main(void)
{
DDRB=255;//PORTB ako vystupny (pripojeny displej)
ZhasniDisplej();
ADC_Init();//inicializacia AD prevodnika

while (1)
{
uint16_t hodnota=StartPrevodu();
if (hodnota<100)
RozsvietNulu();
else
{
if (hodnota>950)
RozsvietPatku();
else
ZhasniDisplej();
}
}
}


Príklad č. 2

V nasledujúcom príklade je digitalizovaný analógový signál privedený na vstup ADC0 so vzorkovacou frekvenciou fvz = 100 Hz (Tvz = 10 ms). Digitálne vzorky sú odosielané do PC cez rozhranie USART (Baude Rate = 19 200). Tento príklad je komplexný, pretože využíva časovač, prerušenie a rozhranie USART, ktoré boli predstavené v predchádzajúcich lekciách.

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

#define RTS PIND2

void ADC_Init()//inicializacia AD prevodnika
{
ADMUX|=(1<<REFS0);//referencia na AVCC pine
//v scheme su piny VCC a AVCC prepojene -> referencia AD prevodnika = 5V

//digitalizujeme kanal ADC0 - prednastavena hodnota v registri ADMUX
ADCSRA|=(1<<ADPS2)|(1<<ADPS1);//predelicka 64 -> 125kHz
ADCSRA|=(1<<ADEN);//povolenie AD prevodnika
}

void Timer1_Init()//inicializacia 16-bit casovaca (TIMER1)
{
TCCR1B|=(1<<CS11);//zapnutie casovaca predelicka 8 -> fCPU=8MHz-> f_casovac=1MHz -> T_casovac=1us
OCR1A=10000;//10000x1us=10ms->fvz=100 Hz
TCCR1B|=(1<<WGM12); //automaticke nulovanie TCNT1 pri dosiahnuti hodnoty v OCR1A
TIMSK1=(1<<OCIE1A);//zapnutie prerusenia casovaca (TIMER1_COMPA_vect)
}

void USART_Init()
{
// Nastavenie USART-8 datovych bitov,jeden stop bit,ziadna parita
// - uvedene parametre su vychodiskove hodnoty registrov,
// preto nie je potrebne nastavovat
UBRR0=25; //nastavena rychlost 19200 Baud (z datasheetu) pri f_MCU=8MHz
UCSR0B|=(1<<TXEN0); //zapnutie vysielaca
}

void USART_send(unsigned char bajt)
{
while ( !( UCSR0A & (1<<UDRE0)) ) ; //pocka na vyprazdnenie buffera
UDR0 = bajt; //odoslanie bajtu cez USART
}

uint16_t StartPrevodu()//funkcia s navratovou hodnotou typu uint16
{
ADCSRA|=(1<<ADSC);//start prevodu
while ((ADCSRA&(1<<ADIF))==0) ; //caka na dokoncenie prevodu
ADCSRA|=(1<<ADIF);//nulovanie dokoncenia prevodu zapisom log.1
return ADC;//vysledok prevodu je v registri ADC
}

ISR(TIMER1_COMPA_vect) //obsluha prerusenia casovaca TIMER1
{
//prerusenie sa spusta kazdych 10ms
if (! (PIND&(1<<RTS)))//ak je linka RTS na log.0
{
uint16_t digi_hodnota=StartPrevodu();
//digi_hodnota = 16 bit = 2 bajty
USART_send(digi_hodnota);//odosle dolny bajt
USART_send(digi_hodnota>>8);//odosle horny bajt
}

}

int main(void)
{
DDRD&=~(1<<RTS);//pin RTS (PIND2) ako vstupny
ADC_Init();//inicializacia AD prevodnika
Timer1_Init();//inicializacia casovaca TIMER1 (16 bit)
USART_Init();//inicializacia USART

sei();//globalne povolenie preruseni

while (1)
{

}
}