Forum: Mikrocontroller und Digitale Elektronik ADC channel via ADMUX ändern?


von Klaus R. (klaus2)


Lesenswert?

Hallo,

wieso muss ich den ADC channel in ADC_init vorgeben, ein ändern in 
ADC_read bringt kein Ergebnis (der ADC gibt dann nur 1023 aus)?
1
void ADC_init() {
2
3
  ADMUX = 0;
4
5
  ADCSRA |= (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);   // Activate ADC with Prescaler 128 --> 8Mhz/128 = 62.5kHz
6
7
  ADMUX |= (1<<REFS1) | (1<<REFS0);                // Interne Vref beutzen
8
9
  ADCSRA |= (0<<ADLAR);                      // left aligned = 1
10
11
  }
12
13
void ADC_read(char ADC_channel) {
14
15
  //ADMUX = ADC_channel;          // Select pin ADC0 using MUX
16
    
17
  ADCSRA |= (1<<ADSC);                // eine Wandlung "single conversion"
18
    
19
  while ( ADCSRA & (1<<ADSC) ) {;}       // auf Abschluss der Konvertierung warten
20
 
21
  
22
    adc_value = ADCL;               // value is uint16_t x
23
    adc_value += (ADCH<<8);         // ...use LOW byte of ADC result
24
                              // ...add HIGH bye of ADC result
25
26
  }

Danke, Klaus.

von MaK (Gast)


Lesenswert?

ATMEGA 328?

Änderungen an ADMUX wirken sich erst bei der nächsten Konvertierung aus, 
wenn bereits eine Konvertierung läuft, sonst erst bei der übernächsten. 
Wenn ADMUX geschrieben wird, landet das erst in einem Zwischenregister, 
erst am Ende der Konvertierung wird der Multiplexer umgeschaltet.

von Klaus R. (klaus2)


Lesenswert?

Atmega 8

  //ADMUX = ADC_channel;          // Select pin ADC0 using MUX

  ADCSRA |= (1<<ADSC);                // eine Wandlung "single 
conversion"

-> Das wäre doch VOR der Wandlung? Hatte ich auch schon im DaBla 
gelesen, meinte es aber damit einzuhalten?

Klaus.

von MaK (Gast)


Lesenswert?

> -> Das wäre doch VOR der Wandlung? Hatte ich auch schon im DaBla
> gelesen, meinte es aber damit einzuhalten?
>

Wie gesagt: Die Umschaltung erfolgt am Ende jeder Wandlung. Warte mal 
das Ende der 1. Wandlung ab und starte eine neue. Dann erhältst du das 
richtige Ergebnis.

von Mario M. (thelonging)


Lesenswert?

Klaus R. schrieb:
> ein ändern in
> ADC_read bringt kein Ergebnis

Vielleicht weil Du da die REFSx-Bits löschst und damit Vref umschaltest?

von Hmmm (Gast)


Lesenswert?

Wenn Du ADMUX dort nur mit dem Channel beschreibst, vermurkst Du die in 
ADC_init() gesetzten Vref-Bits.

von MaK (Gast)


Lesenswert?

Das, was Mario M. und Hmmm oben gesagt haben, stimmt natürlich. Ich 
hatte oben auch nicht ganz recht: Bei der ersten Konvertierung werden 
MUX und REFS doch upgedatet. Nur im free running mode passiert das nur 
am Ende jeder Konvertierung.
Datenblatt:
Figure 92. ADC Timing Diagram, First Conversion (Single Conversion Mode)
Figure 93. ADC Timing Diagram, Single Conversion
Figure 94. ADC Timing Diagram, Free Running Conversion

Trotzdem sollte man nach dem Ändern der Referenzspannungsquelle  das 
Ergebnis der nächsten Konvertierung wegwerfen. (Abschnitt ADC Voltage 
Reference, letzter Satz)

von Falk B. (falk)


Lesenswert?

//ADMUX = ADC_channel;          // Select pin ADC0 using MUX

wie bereits gesagt, werden hier alle anderen Bits in diesem Register 
gelöscht, was im Allgemeinen NICHT erwünscht ist. Besser so.
1
ADMUX = ADMUX & ~0xF | ADC_channel & 0xF;

Damit werden nur die MUX-Bits in ADMUX gelöscht und ADC-channel außerdem 
auf 0-15 begrenzt, ein fälschlicher Aufruf mit >15 macht die anderen 
Bits nicht kaputt. Nennt sich defensives Programmieren. Siehe auch 
Bitmanipulation.

von Klaus R. (klaus2)


Lesenswert?

"Wenn Du ADMUX dort nur mit dem Channel beschreibst, vermurkst Du die in
ADC_init() gesetzten Vref-Bits."

Verdammt - logisch! Es war halt zu spät :)

Danke!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.