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
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.
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.
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
>Und erst nach bedarf Setzen. >ADCSRB|=0b00001000 ; Richtig ist: ADCSRB|= channel & 0b00001000 ;
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?
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.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.