C:AD-Konverterer
Fra CodeWiki
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;} } }
