Download as pdf or txt
Download as pdf or txt
You are on page 1of 13

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

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.

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.

2
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).

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.

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,...)

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.

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ä.

5
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.

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

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

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 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 1: muunnos alkaa valitun signaalin
Enable 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

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.

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.

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ä.

Kytke 10 k potentiometrin liuku n.100kohmin vastuksen


kautta ADC3-inputtiin. EMOn ADC1 = ADC3 ==>> korjattu.
Säädä potikan liun jännitettä ja resetoi aina välillä.
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 muuttujaan
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); // 'kymmenet mV'
LCD_WriteChar(voltti);
LCD_WriteChar('V');
}

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"

// 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.

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

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); // 'kymmenet 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++)_delay_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

12
LCD_WriteUINT(adc_data/1023);
// Jannitteen kokonaisosan lasku
LCD_WriteChar(0x2C); // Pilkku

adc_data=(adc_data%1023)*10; // Jannitteen kymmenesosan lasku


LCD_WriteUINT(adc_data/1023);
adc_data=(adc_data%1023)*10; // Jannitteen sadasosan 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 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

while(1) // jatkuva mittaus


{
DDRA &= ~(1<<3); // ADC.3 input
// oltava tässä, koska "lcd sekoittaa asetukset"
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

13

You might also like