6.1. AVR_rauta. ADC-ohjelmointia

13
1 6.1. AVR_rauta. ADC-ohjelmointi 6.1.2008 pva, kuvat jma ”Eräät tykkäävät omasta navasta niin paljon, että ovat valmiita kumartamaan syväänkin pitääkseen sen näkyvissä.” - Jerzy Lec Tässä osiossa tärkeää: ADC-muunnoksen periaate, toiminta ja ohjelmointi/käyttö. 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. Kuva 6.1.1. AD-muunnin muuttaa analogisen tulosignaalin digitaaliseksi lähtösignaaliksi. Muunnosalue määritetään +Vref ja –Vref-jännitteillä. kun analogiatulo on lähellä nollaa == binäärilähtö on nolla kun analogiatulo on lähellä referenssiä == binäärilähtö on maksimi

Transcript of 6.1. AVR_rauta. ADC-ohjelmointia

Page 1: 6.1. AVR_rauta. ADC-ohjelmointia

1

6.1. AVR_rauta. ADC-ohjelmointi 6.1.2008 pva, kuvat jma ”Eräät tykkäävät omasta navasta niin paljon, että ovat valmiita kumartamaan syväänkin pitääkseen sen näkyvissä.” - Jerzy Lec Tässä osiossa tärkeää: ADC-muunnoksen periaate, toiminta ja ohjelmointi/käyttö. 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.

Kuva 6.1.1. AD-muunnin muuttaa analogisen tulosignaalin digitaaliseksi lähtösignaaliksi. Muunnosalue määritetään +Vref ja –Vref-jännitteillä.

kun analogiatulo on lähellä nollaa == binäärilähtö on nolla kun analogiatulo on lähellä referenssiä == binäärilähtö on maksimi

Page 2: 6.1. AVR_rauta. ADC-ohjelmointia

2

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. Analogia-digitaali-muuntimia on toiminnaltaan ja rakenteeltaan hyvin monenlaisia. Tyypillisimmät ovat:

- integroiva muunnos - peräkkäisaproksimaatio, succesive approximation, AVR-tyyyppi - suora muunnos = flash

Niistä löytyy tarkempaa tietoa netistä ja kirjoista. AVR-ohjaimissa oleva AD-muunnin perustuu peräkkäisapproksimaatioon. Tutkitaan sen toimintaa, jotta ymmärrämme siitä riittävästi koodin tekemistä varten. Peräkkäisaproksimaatioon perustuva A/D-muunnin (AVR)

Kuva 6.1.2. SAR-muunnin. (SAR, Successive Approximation Register). Siinä muunnettava analogiajännite Vi viedään komparaattorin kautta muuntimeen, josta saadaan binäärinen data ulos. Muunninta ohjataan clock-kellon tahtiin. Sama binääridata viedään myös digitaali-analogiamuuntimeen, jonka analogialähtö Ve viedään komparaattorille. Komparaattori vertaa siis sisään tulevaa jännitettä muunnostulokseen ja ohjaa muunninta sen perusteella (kts. seuraava kuva). Kun sisääntuleva jännite ja muunnettua binääritietoa vastaava analogiajännite ovat yhtä suuret, muunnosprosessi on valmis ja se lopetaan.

Page 3: 6.1. AVR_rauta. ADC-ohjelmointia

3

Kuva 6.1.3. SAR-muunnoksen toiminta. Kuvan 6.1.3 esimerkissä AD-muunnin on 8-bittinen ja referenssitasot ovat GND:n eli 0 Voltin ja +5Voltin välillä. Muunnoskierros alkaa ”arvaamalla” lähtöarvoksi puolet referenssijännitteestä asettamalla eniten merkitsevä bitti ykköseksi. Kuvassa se on 2,5V eli asetetaan 7. eli MSB-bitti ykköseksi, eli 128des. Verrataan muunnostulosta muunnettavaan jännitteeseen. Jos Vi-input-jännite on suurempi kuin muunnostulos, asetetaan seuraava eli 6. bitti ykköseksi. Nyt bitit yhdessä vastaavat 192des, se on kuvan perusteella liian iso, siksi 6.bitti nollataan ja asetetaan 5. bitti ykköseksi. Muunnostulos on nyt 160des ja selvästi liian pieni, joten jätetään bitti ennalleen ja asetetaan taas seuraava bitti ykköseksi, jne. Näin muunnos tapahtuu vertaamalla peräkkäisesti tuntemattoman sisääntulojännitteen ja tunnettujen referenssijännitetasojen eroja, ja korjaamalla tulosta aina oikeaan suuntaan.Tämän muunnostekniikan tärkein etu on, että piirin toteuttamiseen tarvitaan vain yksi komparaattori (yhden tekeminen on helpompaa kuin kymmenen kaikilta ominaisuuksiltaan täysin samanlaisen). Jatketaan kunnes analogiajännite Vi ja binäärinen muunnostulos ovat yhtä suuria. Tästä selviää myös miksi tarvitaan kellopulsseja. Successive approximation-muuntimen ongelmana on muunnostuloksen vääristy-minen, joka syntyy siitä että muunnos vaatii monta peräkkäistä vertailua (kestää kauan), ja analogiajännite saattaa muuttua kesken muunnoksen. Tämä ongelma korjataan näytteenotto-pito-piirillä (sample-and-hold).

Page 4: 6.1. AVR_rauta. ADC-ohjelmointia

4

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. AD-muunnosalue ja referenssijännite Vref, Aref

- analogia-input-alue, jonka välillä muunnos tehdään, on 0-Vref - Vref, joko sisäinen 2,56V tai ulkoinen jännite, joka tuodaan Vref-pinniin

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. ulostulon lähdön tyyppi tarkoittaa miten ulkoinen muunnin liitetään ohjiameen. Se voi olla sarja- (I2C-, SPI-, tai uWire) tai rinnakkaismuotoinen (4- tai 8-bittinen). Kun ADC otetaan käyttöön, on ensin selvitettävä:

- miten kytketään mitattava analogiajännite muuntimen tuloon - miten valitaan tuo tulo muunnosprosessiin - millainen ja miten Vref eli vertailujännite valitaan (sis. vai ulkoinen) - miten valitaan muunnosnopeus - otetaanko käyttöön pollaus- vai keskeytysmenetelmä - miten ADC otetaan käyttöön, mitkä rekisterit ja mitkä bitit on initialisoitava - miten ja minne tulostetaan (LCD, USART,...)

Page 5: 6.1. AVR_rauta. ADC-ohjelmointia

5

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.

Kuva 6.1.3. AVR-ADC. A-porttia voidaan käyttää tavallisena digitaalisena input/output-porttina ja sen lisäksi ohjausrekistereitä manipuloimalla analogisena tulona. A-portin inputissa on analogiasignaalia varten multiplekseri, jolla valitaan yksi kahdeksasta tulosta muuntimen sisääntuloon. Näyte/pito-piiri, S/H, Sample and Hold, pitää muunnettavan jännitteen vakiona muunnostapahtuman ajan. Muunnosväli määritetään jännitteillä Aref. Muunnos tapahtuu kellon ohjaamana. Muunnos alkaa start-komennolla ja kun muunnos on valmis muunnin ilmoittaa siitä asettamalla ready-lipun. (kts. rekisterien esittelyt edempänä). Kun muunnos on valmis, arvo siirretään ADCH- ja ADCL-rekistereihin ja annetaan keskeytyspyyntö. Kun tulos=resoluutio on 10 bittiä, niitä varten tarvitaan kaksi 8-bittistä rekisteriä. AVR-ADC:n toiminta modet: 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ä.

Page 6: 6.1. AVR_rauta. ADC-ohjelmointia

6

Matematiikkaa Yleisesti pienissä mikro-ohjaimissa käytetään vain kokonaislukulaskentaa. Liukuluku-laskenta, floating point, vie paljon muistia ja myös aikaa. Printf-funktiota ei yleensä kannata käyttää tulostuksessa, sillä sen (standardin mukainen) formatointi ei toimi, koska 8-bittisen mikro-ohjaimen resurssit ei riitä. 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.

Floating point -laskenta on hidasta – käytä integereitä. From the datasheet: "The first ADC conversion result after switching reference voltage source may be inaccurate, and the user is advised to discard this result." “Heitä eka muunnostulos roskiin, koska se ei ole tarkka”.

ADC-rekisterien initialisointi ADCSR 3 alinta bittiä, valitaan kellon jakoluku ADIE enable-mahdollista interrupt-keskeytys ADEN enable ADC, otetaan ADC käyttöön ADSC aloita muunnos, start conversion - ADC-kellotaajuus oltava välillä 50 kHz ... 200 kHz - käytä yli 200 kHz, jos muunnoksen nopeus on tärkeämpää kuin resoluutio

- 1 MHz kello antaa 8-bitin resoluution - 2 MHz antaa 6-bitin resoluution

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.

Page 7: 6.1. AVR_rauta. ADC-ohjelmointia

7

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 REFS1 REFS0 Toiminne 0 0 AREF, Internal Vref turned off 0 1 AVCC with external capacitor at AREF pin 1 0 Reserved 1 1 Internal 2,56 V reference with external capacitor at AREF pin MUX4 … MUX0 Analog Channel and Gain Selection Bits MUX4…0 Single Ended Input 00000 ADC0 00001 ADC1 00010 ADC2 00011 ADC3 00100 ADC4 00101 ADC5 00110 ADC6 00111 ADC7 Katso tarkemmin ATMega32 dokumentti 2503.pdf, sivu 213, Table 84. ADLAR, ADC Left Adjust Result 1 To left adjust the result, bitit alkavat vasemmalta 0 Result is right adjusted, bitit rekisterien oikeassa reunassa

ADCH & ADCL ADC Data Register 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

Page 8: 6.1. AVR_rauta. ADC-ohjelmointia

8

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 Nimi Merkitys Toiminto 7 ADEN ADC Enable 1: Enable, 0: Disable 6 ADSC ADC Start Conversion 1: start conversion, in single conversion mode

1: start the first conversion, in free running mode 0: kun muunnos valmis eka vie 25 clk, seuraavat 13 clk

5 ADATE ADC Auto Trigger Enable

1: muunnos alkaa valitun signaalin nousevasta reunasta, valitaan by ADTS in SFIOR

4 ADIF ADC Interrupt Flag 1: kun muunnos valmis 0: nollataan, kun keskeytysohjelma on ajettu, tai kirjoitetaan 1 to flag (1 uusimman dokin muk.)

3 ADIE ADC Interrupt Enable 1: ADC conversion complete interrupt is enabled

ADPS2 … ADPS0, ADC Prescaler Select Bits ADPS2 ADPS1 ADPS0 Division factor 0 0 0 2 0 0 1 2 0 1 0 4 0 1 1 8 1 0 0 16 1 0 1 32 1 1 0 64 1 1 1 128

SFIOR, Special Function IO Register Bitti 7 6 5 4 3 2 1 0 Nimi ADTS2 ADTS1 ADTS0 - ACME PUD PSR2 PSR10

ADTS2 … ADTS0, ADC Auto Trigger Source Selection ADTS2 ADTS1 ADTS0 Trigger source 0 0 0 Free Running mode 0 0 1 Analog comparator 0 1 0 External Interrupt Request 0 0 1 1 Timer/Counter0 Compare Match 1 0 0 Timer/Counter0 Overflow 1 0 1 Timer/Counter1 Compare Match B 1 1 0 Timer/Counter1 Overflow 1 1 1 Timer/Counter1 Capture Event

Page 9: 6.1. AVR_rauta. ADC-ohjelmointia

9

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. Huomiota ADC-muuntimista ja niiden käytöstä Mikro-ohjaimien sisäisten AD-muuntimien resoluutio on yleensä luokkaa 8-bittiä (vaikka muuta väitetään). Vaikka niiden ominaisuudet eivät riitä irtomuuntimen tasolle, niin sisäiset muuntimet sopivat monenlaiseen valvontaan (jännitteet, virrat, jne.). Jos tarvitset parempaa tarkkuutta, kannattaa ajatella ulkopuolista esim. 12-bittistä muunninta. Sisäisiä AD-muuntimia vaivaa se, että CPU:n sähköt ovat ”likaisia”, joka häiritsee muuntimen toimintaa (huolellinen koodari ei käytä AD-muuntimen käyttö- eikä referenssijännitteenä ohjaimen käyttöjännitettä, vaan kummallekin on oltava oma regulaattorinsa). Lisäksi yleiskäyttöisten mikro-ohjainten sisään integroidut muuntimet kohisevat paljon ja toimivat hitaasti. Mutta kyllä ne alkuun ja varsinkin aiheen opiskeluun riittää. Jos haluaa nopeampaa ja tarkempaa muunnosta, sitten tarvitaan ulkoinen ADC. Ulkoisilla muuntimilla päästään 12-bittiin, jos ympäristö rakennetaan huolella. Tarkkuutta lisää: Pysäytetään CPU muunnoksen ajaksi. Toistetaan muunnos esim. sata kertaa ja lasketaan keskiarvo. Toisto saa aikaan sen, että tarkkuutta saadaan enemmän. Pidä käyttösähköt kunnossa. Rakennetaan jännitesyötöt kuten ohjekirja neuvoo. Parasta olisi tietysti tehdä analogiajännite eri regulaattorilla kuin digijännite, siis AD- muuntimille omaa suodatettua sähköä. Muuntimen käyttösähköt, AVCC ja AGND, jos tarkkuudella ei ole väliä, voidaan liittää ohjaimen power-pinneihin. Jos oltava tarkka, suodata jännite hyvin ja kiinnitä huomioita piirilevyn johdotukseen. Parasta olisi tarkka pienivirtainen oma regulaattori anturille ja sitten työregulaattori muulle logiikalle. 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. Pidä myös AD-muuntimen referenssijännite kunnossa. Pahin tapaus on se, jos analogia-puoli käyttää referenssijännitteenään koko piirin käyttöjännitettä, jolloin käyttöjännitteen ”notkuminen” näkyy mittaustuloksessa. Referenssijännitteen siisteys on tärkeämpi kuin käyttöjännitteen siisteys. Pyrkimys: kunnollinen referenssijännite ja huolellinen digitaali- ja analogisähköjen pitäminen erillään.

Page 10: 6.1. AVR_rauta. ADC-ohjelmointia

10

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 potentiome trin liulla olevaa jännitettä, ja tulostaa sen (A-porttiin kytkettyyn) LCD-näyttöö n Potikka GND ja +5V välillä. Kytke 10 k potentiometrin liuku n.100kohmin vastuks en kautta ADC3-inputtiin. EMOn ADC1 = ADC3 ==>> korjat tu. Säädä potikan liun jännitettä ja resetoi aina välil lä. Jotta DVM näyttää oikein, pidä reset-nappia alhaalla mittauksen ajan. *************************************************** *******/ #include <avr/io.h> #include <util/delay.h> #include "lcd_tat.h" // *** Primitive wait() *** void wait(uint16_t time) { volatile uint16_t i; 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 muuttu jaan adc_data = (adc_data * 5000)/1023; // skaalataan muunnostulos 'volteiksi' voltti = 0x30 + (adc_data/1000 % 10); // laskee voltit LCD_WriteChar(voltti); // tulostaa voltit LCD_WriteChar(0x2C); // tulostaa pilkun voltti = 0x30 + (adc_data/100 % 10); // 'sadat mV' LCD_WriteChar(voltti); voltti = 0x30 + (adc_data % 10); // 'kymmen et mV' LCD_WriteChar(voltti); LCD_WriteChar('V'); }

Page 11: 6.1. AVR_rauta. ADC-ohjelmointia

11

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-pinnis sä ADCSRA |= (1<<ADPS2) | (1<<ADPS0); // clk/32, 12 5 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" // eka mittaus, joka hylätään // koska se on epätarkka loop_until_bit_is_set(ADCSRA, ADIF); // muunnos_valmis pollaus ADCSRA |= (1<<ADIF) ; // nollaa lippu ADCSRA |= (1 << ADSC); // aloita uusi muunnos, eka hylätään loop_until_bit_is_set(ADCSRA, ADIF); Tulosta(); } Analysointi Kopioi lcd_tat.c ja lcd_tat.h tiedostot projektikansioon ja liitä lcd_tat.c koodipuuhun. 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. DDRA &= ~(1<<3); // jännitteen lukupinni "sisään" // LCD-initin konfiguroinnin "korjaus"

LCD-näyttö on samassa portissa kuin AD-muuntimen tulot, siksi sen initialisoinnin ”korjaus” tehdään yllä olevalla komennolla, eli määritetään A-portin 3-pinni tuloksi. Sitten jäädään odottamaan muunnoksen valmistumista. Se tehdään komennolla loop_until_bit_is_set(ADCSRA, ADIF); // muunnos_valmis pollaus

jossa pollataan ADCSRA-rekisterin ADIF-bitin tilaa. Kun muunnos on valmis, ko. bitti on asettunut, eli on ”1”, sitten sama uudelleen ja sitten siirrytään tulostamaan muunnostulos.

Page 12: 6.1. AVR_rauta. ADC-ohjelmointia

12

Tulos on 10-bittinen, joten se vaatii kaksi rekisteriä, jotka molemmat voidaan lukea yhdellä komennolla: adc_data = ADCW; // luetaan muunnostulos muuttuja an

Sitten laskemaan tulostusta varten rekisterien sisältöjä. 8-bittisten mikro-ohjaimien käyttämistä liukulukulaskentaan on yleensä vältettävä. Resurssit ei riitä. AVR on nopea bitinkääntäjä, mutta hidas laskemaan. Siksi laskemme arvot kokonaislukulaskennalla. Sitä varten ensin tulos skaalataan ylöspäin käyttämällä kaavaa: adc_data = (adc_data * 5000)/1023; // skaalataan muunnostulos 'volteiksi'

Sitten lasketaan voltit ja sen desimaalit käyttäen hyväksi tavallista jakolaskua ja jakojäännöstä. / jakolasku % jakojäännös voltti = 0x30 + (adc_data/1000 % 10); // laskee voltit LCD_WriteChar(voltti); // tulostaa voltit LCD_WriteChar(0x2C); // tulostaa pilkun voltti = 0x30 + (adc_data/100 % 10); // 'sadat mV' LCD_WriteChar(voltti); voltti = 0x30 + (adc_data % 10); // 'kymmen et mV' LCD_WriteChar(voltti); LCD_WriteChar('V');

Mallikoodi, keskeytysmenetelmä, jatkuva mittaus /************************************************** ****************** Project : adc_keskeytys.c Hardware: PV-M32 (4 MHz) + PV-EMO Software: AVRStudio4.13 + WinAVR-20070525 Date : 11.11.2007 Author : pva Comments: mittaa ADC-3-trimmerin liu'un jännitteen ja tulostaa sen A-porttiin kytkettyyn LCD-näyttöön. Laita 10 kohmin trim_potikka GND ja +5 V väliin, liulle noin 100 kohmia ja se ADC3-inputtiin, eli PA .3 Säädä potikkaa, seuraa lcd-näyttöä. *************************************************** *****************/ #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #include "lcd_tat.h" #define AIKA 600 #define WAIT(time) for(uint16_t i=0;i<2000;i++)_del ay_loop_2(time); #define TAUSTAVALO 1<<0 // hypätään tänne, kun muunnos valmis ISR(ADC_vect) { uint16_t adc_data = 0; adc_data = ADCW; // luetaan muunnostulos muuttujaan (10 bittia >> 0-1023) LCD_Clear(); adc_data = (adc_data * 5); // Referenssijannite= +5V

Page 13: 6.1. AVR_rauta. ADC-ohjelmointia

13

LCD_WriteUINT(adc_data/1023); // Jannitteen kokonaisosan lasku LCD_WriteChar(0x2C); // Pilkku adc_data=(adc_data%1023)*10; // Jannitteen kymme nesosan lasku LCD_WriteUINT(adc_data/1023); adc_data=(adc_data%1023)*10; // Jannitteen sadas osan lasku LCD_WriteUINT(adc_data/1023); 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 kesk eytys 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 while(1) // jatkuva mittaus { DDRA &= ~(1<<3); // ADC.3 input // oltava tässä, koska "lcd sekoittaa asetukse t" ADCSRA |= (1<< ADEN) | (1<<ADSC); // (1<< ADEN) ADC ON // (1<<ADSC) Start conversion WAIT(AIKA); } } Analysointi Nämä ovat tulossa seuraavaan painokseen. Mallikoodi, floating point, liukuluku-tulostus 8-bittisten mikro-ohjaimien käyttämistä liukulukulaskentaan on yleensä vältettävä. Resurssit ei riitä. AVR on nopea bitinkääntäjä, mutta hidas laskemaan. Liukulukurutiinit ovat avr-gcc:ssä ihan kohtuullisesti tehtyjä. Double-tyyppiset laskutoimitukset ovat hitaita, koska mitään erityistä matematiikkayksikköä ei AVR:ssä ole ja käsiteltävät luvut ovat isoja (kahdeksan tavua). Lämpötilan mittaus LM35-anturilla