Forum: Compiler & IDEs ATmega2560 - ADC 8 ... 16 funktionieren nicht


von Markus (Gast)


Lesenswert?

Hallo!

Wer kann mir bei folgendem Problem helfen: Mit einem ATmega2560 will ich 
16 Analog-Digital-Konverter-Kanäle nutzen. Mit der unten gezeigten 
Funktion AnalogPort funktioniert das bei den Kanälen 0 bis 7 sehr gut 
(Spannungsmessung korrekt für U=0 bis 4800 mV). Wenn ich allerdings die 
Kanäle 8 bis 15 benutzen will, liefert die Funktion einem stark 
verrauschten Wert, der sich bei Spannungen zwischen 0 und 4.8 V zwischen 
3 und 4.8 V bewegt (also nur schwach von der Spannung abhängt).

Das Verhalten ist identisch auf zwei verschiedenen Prozessoren, die sich 
auf ihrer jeweils eigenen Platine befinden.

Die Zuordnung des Wertes channel auf die Register ADMUX und ADCSRB habe 
ich an Tabelle 129, Seite 295 des Prozessormanuals angepasst.

Der Compiler ist der von WinAVR. Programmer ist AVRDude und 
STK200-Dongle.
Hier noch die C-Schnipsel:

----------------------------------

Initialisierung:

DDRF = 0b00000000;    // Port F Pins (ADC1) all input
DDRK = 0b00000000;    // Port K Pins (ADC2) all input
PCMSK2 = 0b00000000;    // PCINT23:16=0 (Pin Change INTerrupt disabled)

----------------------------------
Funktion zum Auslesen des ADC mit channel=0...15:

float AnalogPort(char channel)
{
ADMUX = 0b01000000 | (channel & 0b00000111);
ADCSRA = 0b11000001;    // Bit 7: Enable ADC
        // Bit 6: Start Conversion
        // Bits 2,1,0: Teilerverhältnis von 32 (Original 101)
        // => 131.072 kHz bei 4 MHz Prozessortakt
        // (muss zwischen 50 kHz und 200 kHz liegen)

ADCSRB = channel & 0b00001000;  // Bit ACME=0: kein Comparatorbetrieb
                                // Bit MUX5 auf Channel-Bit 3

// wait until end of AD-Conversion
while ((ADCSRA & 0b01000000) == 0b01000000);

// get result
return (ADC*0.0047222*1000);  // Faktor zur Kalibrierung in mV
}

-----------------------------------
Fuse-Bits:
LFUSE = 0b11111101
HFUSE = 0b11011001
EFuse = 0b11111111

von Florian D. (code-wiz)


Lesenswert?

ADMUX = 0b01000000 | (channel & 0b00000111);

Da fehlt eine 1 in der rechten Mask. MUX hat 4 Bits und nicht 3.

ADMUX = 0b01000000 | (channel & 0b00001111);

--- das sollte helfen.

von Markus (Gast)


Lesenswert?

Nein, das behebt das Problem leider nicht. Ich habe es eben ausprobiert.

Laut Datenblatt hat MUX übrigens 6 Bits: MUX4...MUX0 im Register ADMUX 
und MUX5 im Register ADCSRB. Laut Tabelle 129, Seite 296 muss man für 
"Single Ended Input" (also keinen differenziellen ADC) an Kanal 8

MUX5:0 = 0b100000

setzen. Nach deinem Beispiel würde ich 0b101000 nehmen.

von Branko Golubovic (Gast)


Lesenswert?

Hallo Markus,

 >ADCSRB = channel & 0b00001000;  // Bit ACME=0: kein Comparatorbetrieb
 >                               // Bit MUX5 auf Channel-Bit 3

Mit dieser Zeile bei Channel Wechsel bleibt Bit3 immer gesetzt.

Zuerst Bit 3 immer Löschen.

ADCSRB&=~0b00001000 ;

Und erst nach bedarf Setzen.

ADCSRB|=0b00001000 ;

Außerdem,
>// wait until end of AD-Conversion
>while ((ADCSRA & 0b01000000) == 0b01000000);

kannst du auch so schreiben:
while (ADCSRA & 0b01000000);

Gruß Branko

von Branko Golubovic (Gast)


Lesenswert?

>Und erst nach bedarf Setzen.
>ADCSRB|=0b00001000 ;

Richtig ist:
ADCSRB|= channel & 0b00001000 ;

von Markus (Gast)


Lesenswert?

Hallo Branko,

Auch damit wird das Problem nicht gelöst.

 >ADCSRB = channel & 0b00001000;  // Bit ACME=0: kein Comparatorbetrieb
 >                               // Bit MUX5 auf Channel-Bit 3

> Mit dieser Zeile bei Channel Wechsel bleibt Bit3 immer gesetzt.

Dies ist eine bitweise UND-Verknüpfung, d. h. wenn channel von 8 auf 7 
wechselt, wird Bit3 (MUX5) auch wieder zurückgesetzt.

Ich habe dies zum Anlass genommen, mir die Werte von ADMUX, ADCSRA und 
ADCSRB mit den Messwerten und der Kanalnummer auf einem LC-Display nach 
der Wandlung ausgeben zu lassen. Alle Werte sind so, wie sie in obiger 
Routine gesetzt werden. Überrascht hatte mich zuerst nur, dass nach 
erfolgreicher Wandlung noch ADIF in ADCSRA automatisch gesetzt wurde 
(dies konnte ich aber inzwischen im Handbuch nachlesen).

Ich hoffe immer noch, dass jemand die zündende Idee oder Erfahrung zu 
diesem Problem hat. Könnte es irgendwie mit einer alternativen Funktion 
des Port K zu tun haben? Gehe ich recht in der Annahme, dass ADC0...ADC7 
an Port F und ADC8...ADC15 an Port K anliegen?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Markus wrote:

> Gehe ich recht in der Annahme, dass ADC0...ADC7
> an Port F und ADC8...ADC15 an Port K anliegen?

So sagt es zumindest das Pinout im Datenblatt.

Als alternate functions werden lediglich der ADC und die pin-change
interrupts genannt.

von Brako Golubovic (Gast)


Lesenswert?

Hallo Markus,

Das Problem ist dass MUX-Bits auf 2 Register aufgeteilt ist ud du
folgende Fehler gemacht hast:
>ADMUX = 0b01000000 | (channel & 0b00000111);
OK. MUX 0 bis 2 sind ausgewählt.
>ADCSRA = 0b11000001;    // Bit 7: Enable ADC
>       // Bit 6: Start Conversion
>       // Bits 2,1,0: Teilerverhältnis von 32 (Original 101)
>       // => 131.072 kHz bei 4 MHz Prozessortakt
>       // (muss zwischen 50 kHz und 200 kHz liegen)
OK. Start Conversion

>ADCSRB = channel & 0b00001000;  // Bit ACME=0: kein Comparatorbetrieb
                                // Bit MUX5 auf Channel-Bit 3
Zu spät, Du hast Konversion schon gestartet!

Richtig ist zuerst ALLE MUX-Bits richtig einstellen und DANN Konversion
starten:
1
ADMUX = 0b01000000 | (channel & 0b00000111);
2
ADCSRB = channel & 0b00001000;
3
ADCSRA = 0b11000001;    // Bit 7: Enable ADC
4
      // Bit 6: Start Conversion


Branko

von Markus (Gast)


Lesenswert?

Hallo Branko!

Genau das wars! Es war mir eben selbst aufgefallen und ich wollte genau 
dies hier posten. Die Lösung ist nur die Vertauschung der Zeilen mit den 
Zuweisungen für ADCSRA und ADCSRB.

Gratulation für diese Fehleranalyse aus der Ferne!

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.