Professional Documents
Culture Documents
6.1. AVR - Rauta. ADC-ohjelmointia
6.1. AVR - Rauta. ADC-ohjelmointia
ADC-ohjelmointi
6.1.2008 pva, kuvat jma
Sisältö
Yleistä
Peräkkäisaproksimaatioon perustuva A/D-muunnin (AVR)
AD-muuntimissa on tärkeää:
AVR ja ADC
ADC-rekisterit ja niiden asetukset
Huomiota ADC-muuntimista ja niiden käytöstä
Mallikoodi, pollaus
Mallikoodi, keskeytys
mallikoodi, floating point
Lämpötilan mittaus LM35-anturilla
Yleistä
Maailma on analoginen – ainakin vielä. Jotta tietokone voi käsitellä analogista tietoa,
se on ensin muutettava AD-muuntimella digitaaliseksi. AD-muuntimen tehtävä on
muuttaa tietty valikoitu analoginen jännitetieto digitaaliseen binääriseen muotoon,
esim. 0-5V muutetaan 0-255 binääriarvoksi.
1
Muuntimia tarvitaan muuttamaan anturien (analoginen lämpötilatieto, painearvo, jne.)
tai mitattavan analogiajännitteen arvo binääriseksi jotta se soveltuu MCU:n käyttöön.
2
Kuva 6.1.3. SAR-muunnoksen toiminta.
3
AD-muuntimissa on tärkeää:
resoluutio,
Se vaihtelee 8-bitistä 20-bittiin.
Tarkkuus ilmoittaa sen, kuinka paljon ulos saatu binääriarvo voi vaihdella eri piiri-
yksilöiden välillä (tai samalla piirillä lämpötilan/ajan/ym. funktiona), kun sisään
syötetään tiettyä jännitettä.
Resoluutio puolestaan ilmoittaa, kuinka moneen "askeleeseen" mittausalue on jaettu.
output alue
- alue, joka kertoo monenko bittiseksi tulojännite muunnetaan
- 0-Vref -> 8-bittiä 0-255, resoluutio = Vref/256
- 0-Vref -> 9 bittiä, 0-512, resoluutio = Vref/512
- 0-Vref -> 10 bittiä, 0-1024, resoluutio = Vref/1024
muunnosnopeus
AVR:n successive approximation-muunnin tarvitsee muunnokseen kellopulsseja,
jotka generoidaan pääkellosta. Muunnosaika määrää miten kauan muunnos kestää ja
samalla muunnoksen tarkkuuden. Se riippuu ADC-kellotaajuudesta ja sen on oltava
luokkaa 50 kHz ... 200 kHz. Mitä pienempi sitä tarkempi tulos, mitä suurempi sitä
nopeammin muunnos käy ( jos nopeita signaaleja muunnettava). Käytä yli 200 kHz,
jos muunnoksen nopeus on tärkeämpää kuin resoluutio.
Normaalisti muunnos vie 13 ADC-clk. Eka 25 kelloa. Jos kello on 200 kHz, niin
normaali muunnos vie 65 us, extedded vie 125 us.
4
AVR ja ADC
AVR:n sisään on integroitu AD-muunnin perustuu peräkkäisaproksimaatioon,
successive approximation. Se on 10-bittinen ja analogiatuloja on 8 kpl ja ne kaikki
sijaitsevat A-portissa.
single conversion,
kun muunnos on valmis, tulos on ADC datarekistereissä, seuraava muunnos
aloitettava uudestaan samalla lailla ja ohjelmoija määrää milloin muunnos tapahtuu
free running,
kun muunnos on valmis, uusi aloitetaan välittömästi eli free running. Ts. ADC mittaa
jatkuvasti tulojännitettä ja päivittää datarekistereitä.
5
Matematiikkaa
AD-muuntimesta tuleva luku välillä 0-1023 (10 bittiä, 2 potensiin 10) pitää kertoa tai
jakaa lopputulosta varten sopivasti kokonaisluvuksi. Jos referenssi on vaikka 5V,
kerrotaan ensin luku luvulla 250 ja sitten jaetaan by 512 tai kahdella, riippuu
tapauksesta.
ADC-rekisterien initialisointi
Kun muunnos on valmis, ADC antaa keskeytyspyynnön, jos se on sallittu (ja globaali
keskeytysbitti asetettu) hypätään keskeytysaliohjelmaan ja tehdään tulokselle jotain,
viedään vaikka jemmaan.
6
AVR, ATmega32, Analog to Digital Converter
ADMUX, ADC Multiplexer Selection Register
Bitti 7 6 5 4 3 2 1 0
Nimi REFS1 REFS0 ADLAR MUX4 MUX3 MUX2 MUX1 MUX0
Kun muunnos on valmis, tulos löytyy näistä kahdesta rekisteristä. Data on luettavissa seuraavasti,
riippuen ADLAR-bitistä. Lue ADCL-rekisteri ensin, sitten vasta ADCH.
ADLAR = 0
Bitti 7 6 5 4 3 2 1 0
ADCH - - - - - - ADC9 ADC8
ADCL ADC7 ADC6 ADC5 ADC4 ADC3 ADC2 ADC1 ADC0
ADLAR = 1
Bitti 7 6 5 4 3 2 1 0
ADCH ADC9 ADC8 ADC7 ADC6 ADC5 ADC4 ADC3 ADC2
ADCL ADC1 ADC0
7
ADCSRA, ADC Control and Status Register
Bitti 7 6 5 4 3 2 1 0
Nimi ADEN ADSC ADATE ADIF ADIE ADPS2 ADPS1 ADPS0
Bitti 7 6 5 4 3 2 1 0
Nimi ADTS2 ADTS1 ADTS0 - ACME PUD PSR2 PSR10
8
Analogia-digitaalimuunnoksen (AVR) periaate:
- analogiajännite mitataan ja verrataan suhteessa Vref-jännitteeseen
- muutetaan tuo mitattu jännite 10-bittiseksi binääritiedoksi
- ja talletetaan ADCL- ja ADCH-rekistereihin
muutetaan tulos desimaalimuotoon ja tulostetaan.
Esim. 7805-regun toleranssi on 5% luokkaa. Joten ADC virhe voi olla 5%.
Oletus:
regun out: 5.1V
ADC-input: 2.5V
Muunnoksesta odotetaan lukua 512, mutta se onkin 501.
Pyrkimys:
kunnollinen referenssijännite ja huolellinen digitaali- ja analogisähköjen pitäminen
erillään.
9
Mallikoodit
1. pollausmenetelmä
2. keskeytysmenetelmä
3. floating point, liukuluku, desimaaliluku-tulostus
Mallikoodi, pollaus
/**********************************************************
Project : adc_pollaus.c
Hardware: PV-M32 + PV-EMO
Date : 11.11.2007
Author : pva
Comments: mittaa ADC3-inputtiin liitetyn potentiometrin
liulla olevaa jännitettä,
ja tulostaa sen (A-porttiin kytkettyyn) LCD-näyttöön
Potikka GND ja +5V välillä.
for(i=0;i<2000;i++)
_delay_loop_2(time);
}
void Tulosta(void)
{
uint8_t voltti;
uint32_t adc_data;
adc_data = ADCW; // luetaan muunnostulos muuttujaan
adc_data = (adc_data * 5000)/1023;
// skaalataan muunnostulos 'volteiksi'
10
void ADC_init(void)
{
ADCSRA = (1<< ADEN) ; // ADC käyttöön
ADMUX |= (1<<MUX1) | (1<<MUX0); // valitaan ADC3
ADMUX |= 1 << REFS0;
// Uref = AVcc ja 0,1 uF kerko oltava Vref-pinnissä
ADCSRA |= (1<<ADPS2) | (1<<ADPS0); // clk/32, 125 kHz
ADCSRA |= (1<<ADSC); // aloita muunnos
}
int main(void)
{
DDRC |= 1<<0;
PORTC |= 1<<0; // taustavalo
LCD_init(1, 0, 0);
ADC_init();
DDRA &= ~(1<<3); // jännitteen lukupinni "sisään"
// LCD-initin konfiguroinnin "korjaus"
Analysointi
void ADC_init(void)
Funktiossa initialisoidaan AD-muuntimen rekisterit ja bitit. Initialisointi tehdään siten,
että tehdään yksittäinen muunnos (kahteen kertaan, koska ensimmäinen muunnos on
yleensä heiman virheellinen) ja kun se on valmis, käydään lukemassa ADC-
muuntimen tulostusrekisteri.
11
Tulos on 10-bittinen, joten se vaatii kaksi rekisteriä, jotka molemmat voidaan lukea
yhdellä komennolla:
adc_data = ADCW; // luetaan muunnostulos muuttujaan
adc_data = ADCW;
// luetaan muunnostulos muuttujaan (10 bittia >> 0-1023)
LCD_Clear();
adc_data = (adc_data * 5); // Referenssijannite=+5V
12
LCD_WriteUINT(adc_data/1023);
// Jannitteen kokonaisosan lasku
LCD_WriteChar(0x2C); // Pilkku
LCD_WriteString(" Volttia" );
LCD_SetCursorXY(0, 1);
LCD_WriteString("V-mittari");
}
void ADC_init(void)
{
ADMUX |= 1<<REFS0;
// (1<<REFS0) AVCC=5V with external capacitor at AREF pin
ADMUX |= (1<<MUX1) | (1<<MUX0); // valitaan ADC.3-input
ADCSRA |= (1<<ADPS2) | (1<<ADPS0); // jakoluku 32
// 4000000/32 = 125 kHz
// oltava välillä 50 kHz ... 200 kHz
ADCSRA |= (1<<ADIE)|(1<< ADEN); // adc ON ja keskeytys ON
}
int main(void)
{
DDRC |= TAUSTAVALO;
PORTC |= TAUSTAVALO;
LCD_init(1, 0, 0);
ADC_init();
DDRA &= ~(1<<3); // ADC.3 input
sei(); // globaali keskeytys sallittu
13