C:AD-Konverterer

Fra CodeWiki

Gå til: navigasjon, søk

Vi skal skrive et C-program som benytter AD-konverteren i 18F452 til å konvertere data fra en lydmåler. AD-konverteren skal gjøre en 10-bits konvertering og benytter kanal 0. Lydmåleren gir ut en analog spenning og opererer i området 0-127 dB (desibel). Overskrides smertegrensen på 100 dB (desibel), skal en varsellampe koblet til PORTB bit 0 tennes ved at en setter en 1’er på IO-linjen. Eksempelet tar utgangspunkt i et PICDEM-2 mikroprosessorkort.

Først vet vi altså at vi har 10-bits konvertering av 127dB. 2¹⁰ = 1024. 128/1024 = 0.125. Det vi her har funnet ut er at når øker bitmønsteret med 1 så øker desibelnivået med 0.125. En annen måte er å si at vi får 8 bits endring per endring i desibel. (1024/128 = 8).

De 10 bit'ene blir lagt inn i to lagerplasser. ADRESH og ADRESL. (Address High og Address low). Under initialiseringen velger du hvorvidt AD-Converteren er venstre eller høyrejustert. Er den venstrejustert benytter du 2 bit i ADRESH og alle 8 bit i ADRESL (10 bit) og omvendt om du har venstrejustert.

Koden tar utgangspunkt i et PICDEM-2 mikroprosessorkort og koden er derfor litt spesfikk til dette. Likevell kan man dra utbytte av eksempelet hvis man er interessert i Analog til Digital Konvertering.

Pollet Løsning

void main(){ //starter en main-metode
 
ADCON0=0x01; //Det 0.bit'et som er ADON (skrur på AD-converteren) er 1.
ADCON1=0x80; //Setter AD-Converteren til venstrejustert. (Hadde vi valgt høyrejustert setter vi ADCON1=0x00)
TRISB=0x00;  // Setter PORTB som utport. (lysdiodene)
PORTB=0x00; //Sikrer oss om at lysdiodene på PortB er avskrudd.
 
int16 sg; //Definerer en variabel sq. Må være int16 siden vi planlegger å sette sq = 800 og int-datatypen er kun 4-bit. Vi velger int16.
sg = 800; //Setter denne til 800. Siden vi skal uttrykke 100 desibel og vi har 8 bit per desibel. 
 
int16 res; //Et 16-bits variabel res hvor vi skal lagre resulatene i.
 
while(1){ //Evig løkke
        res=0; //Nullstiller res-variabelen
        ADRESH=0;
	ADRESL=0; //Setter innholdet i ADRESH og ADRESL til 0 for å nullstille innholdet i disse i starten av hver gjennomføring i løkken.
        ADCON0.2=1; //Starter AD-Konverteringen (ADCON0.2 = Go/Done)
        while(ADCON0.2==1){ //Mens ADCON0.2==1, jobber ADCON med målingen og settes til 0 når den er ferdig. Vi lar den hente målingen
        }
        res=ADRESH*256 //Skal ha 2 bit fra ADRESH som vi vil skifte 8 plasser til venstre. Derfor ganger vi med 256 bit.
                       //Eventuelt kunne vi skrevet ADRESH<<8; for å bytte 8 plasser til venstre
        res=res+ADRESL; //Legger til ADRESL-verdien til res-varibelen.
 
        if(res>sg){ //Hvis resultatet er større en smertegrensen på 100dB..
             PORTB.0=1; //Skrur på lysdioden hvis resultatet er høyere enn 100 dB (smertegrensen)
         }
         else{
             PORTB.0=0; //Ellers så skrur vi av lysdioden.
         }
}

Minste endringen vi kan måle i lydnivået er altså da 0.125 dB som vi fant i starten.

Interruptstyrt løsning

Vi skal nå oppnå samme resultat ved bruk av en interruptrutine.

static int16 res //Global 16-bits variabel, res
 
#pragma origin 0x8
interrupt_rutinen(void{ //Vi starter her interrupt_rutinen
 
res=ADRESH<<8; //Skal ha 2 bit fra ADRESH som vi vil skifte 8 plasser til venstre
res=res+ADRESL; //Setter inn i ADRESL også
PIR1.6=0;
 
#pragma fastMode
}
 
void main(){
 
RCON.7=1;
ADCON1=0x80; 
IPR1.6=1;
RCON.7 = 1;
PIE1.6 = 1;
INTCON.7=1;
ADCON0.0=1;
int16 grense;
grense = 800;
 
while(1){
TRISA=0x00;
res=0;
ADCON.2=1;
while(ADCON0.2=1){}
if(res>grense){PORTA.0=1};
else {PORTA.0=0;}
}
}
Personlige verktøy
dataprogrammering
generelt