diyundso.de

Verwenden der internen ADC eines AVRs

Bei AVRs mit einem internen ADC kann mit der folgenden Vorgehensweise der Wert einer Spannung an ADCx ermittelt werden.
Die Messauflösung beträgt 10 Bit. Damit liegt der Messwert x zwischen 0V = 0 <= x <= 1023 = Referenzspannung

Initialisierung

Zunächst wird eine Referenzspannungsquelle ausgewählt:
//interne Referenzspannung (oft 2,56V, siehe Datenblatt)
ADMUX = 0xC0;

//AVCC
ADMUX = 0x40;

//AREF
ADMUX = 0x00;

Aktivieren des ADC:
ADCSRA = 0x80; //ADC aktivieren, Rest 0 setzen

Anschließend wird ein Vorteiler für den ADC gewählt. Die Frequenz sollte bei 100-200kHz liegen:
ADCSRA |= 0x01; //Vorteiler 2
ADCSRA |= 0x02; //Vorteiler 4
ADCSRA |= 0x03; //Vorteiler 8
ADCSRA |= 0x04; //Vorteiler 16
ADCSRA |= 0x05; //Vorteiler 32
ADCSRA |= 0x06; //Vorteiler 64
ADCSRA |= 0x07; //Vorteiler 128

Konvertierung starten:
ADCSRA |= (1<<6); //Konvertierung starten

Warten auf den Abschluss der Konvertierung:
while(ADCSRA & (1<<6)){};

Ergebnis auslesen:
uint16_t ergebnis = 0;

//Bei AVRs mit 16-bit Registern für den Messwert des ADCs
ergebnis=ADCW;

//Bei AVRs mit zwei 8-Bit-Registern für den Messwert
ergebnis = ADCL;
ergebnis += (ADCH<<8);

Eigentliche Messung

Zum Beginn der eigentlichen Messung muss als erstes der zu messende Kanal ausgewählt werden:
uint8_t kanal = 2; //z.B. aus ADC2

ADMUX &= (0xE0); //Vorhandenen Wert fuer den Kanal loeschen

//den Wert fuer den Kanal schreiben, dabei die vorderen 3 Bits vor evtl. fehlern schuetzen

ADMUX |= (kanal&(0x1F));

ADCSRA |= (1<<6); //Konvertierung starten
Anschließend kann wie bei der Initialisierung auf den Abschluss der Messung gewartet, und der Wert ausgelesen werden

Fertiger Code zum Ausführen von Messungen

#include <avr/io.h>


void adc_init (void){

//interne Referenzspannung
//ADMUX = 0xC0;

//AVCC
//ADMUX = 0x40;

//AREF
ADMUX = 0x00;


ADCSRA = 0x80; //ADC aktivieren, Rest 0 setzen

//ADCSRA |= 0x01; //Vorteiler 2
//ADCSRA |= 0x02; //Vorteiler 4
//ADCSRA |= 0x03; //Vorteiler 8
//ADCSRA |= 0x04; //Vorteiler 16
ADCSRA |= 0x05; //Vorteiler 32
//ADCSRA |= 0x06; //Vorteiler 64
//ADCSRA |= 0x07; //Vorteiler 128

ADCSRA |= (1<<6); //Konvertierung starten

while(ADCSRA & (1<<6)){}; //Kovertierung beendet

uint16_t ergebnis = 0;

ergebnis = ADCL;
ergebnis += (ADCH<<8);

}



uint16_t adc_read (uint8_t kanal){

static uint8_t init = 0;

if(init==0){adc_init(); init++;} //beim ersten Aufruf zunaechst initialisieren

ADMUX &= (0xE0); //Vorhandenen Wert fuer den Kanal loeschen

//den Wert fuer den Kanal schreiben, dabei die vorderen 3 Bits vor evtl. fehlern schuetzen

ADMUX |= (kanal&(0x1F));

ADCSRA |= (1<<6); //Konvertierung starten



while(ADCSRA & (1<<6)){}; //Kovertierung beendet

uint16_t ergebnis = 0;

ergebnis = ADCL;
ergebnis += (ADCH<<8);

return ergebnis; //Ergebnis zurueckgeben

}



double adc_read_avg (uint8_t kanal, uint16_t anzahl){

uint32_t summe = 0;

for (uint16_t i = 1; i<=anzahl; i++){ //anzahl = Anzahl der Durchlaeufe

summe+=adc_read(kanal);

}

return ((double)summe/(double)anzahl); //Durchschnitt zurueckgeben

}

Benutzung des Codes

Vorbereitung
1. Wählen einer Referenzspannungsquelle in adc_init()
2. Wählen eines Vorteilers zum Erreichen von 100-200kHz in adc_init()
Funktionsaufruf
Der Aufruf von:
adc_read(uint8_t x);
liefert den Wert einer Einzelmessung von ADCx als uint16_t

adc_read_avg(uint8_t x, uint16_t n);
liefert den gemittelten Wert von n Messungen an ADCx als double
Impressum

Valid HTML 4.01 Transitional