Hallo Leute, ich habe ein Problem mit dem AD-Wandler beim Mega8 und Mega88. Der unten angehängte Code soll auf beiden Controllern laufen. Der Code läuft in einem Interrupt, der alle 3ms aufgerufen wird. Unter bestimmten Umständen kann der Abstand auch kürzer sein, aber in ca. 1s wird der Interrupt 333 mal aufgerufen. Mich interessieren 2 AD-Kanäle, Kanal 6 und Kanal 7. Über Kanal 6 messe ich die Betriebsspannung und über Kanal 7 einen Widerstand. Die externe Beschaltung ist ok, der gemessene Spannungswert am AD-Eingang entspricht den Erwartungen. Der Ablauf ist nun so: Am Ende des Durchlaufs wird der jeweils andere Kanal gestartet. Beim erneuten Aufruf wird geprüft, welcher Kanal gewandelt wurde und der Messwert wird entsprechend weiterverarbeitet, anschließend wird wieder der andere Kanal angestoßen, die ISR terminiert und so geht es fort. Soweit so gut. Jetzt habe ich nur ein Problem: Ich lese oben den ADMUX ein und sehe, welcher Kanal gewandelt wurde. Es kommt so ca. alle paar Sekunden vor, dass ich den Wert für Kanal 7 einlese, anschließend aber im ADMUX Kanal 6 steht und entsprechend ist auch der eingelesene Wert falsch. Das lässt sich auf dem mega88 nachweisen, für den mega8 weiß ich es nicht (Debugmöglichkeiten!) Ich habe ein wenig mit den Einstellungen gespielt und die Einstellungen für den ADPS für den mega88 sind so wie sie sind ertestet optimal, das heißt, der oben beschriebene Fall tritt relativ selten auf. Laut Dokumentation müsste der Prescaler den ADC aber viel zu schnell takten ? Kennt sich jemand mit diesem Problem aus? Kennt jemand Abhilfe? Ein Workaround schwebt mir schon vor, aber eigentlich möchte ich das Problem nicht umgehen sondern lösen. Danke und Ciao WilliWacker <code> interrupt [TIM1_COMPA_vect] void timer1_comp_isr(void) { byte chnl; // Alle anderen Interrupts freigeben, damit wird dieser Interrupt unterbrechbar! ENABLE_INTERRUPTS; // Bearbeiten der letzten Wandlung: // Wenn die Wandlung nicht nicht beendet ist, dann wieder raus if ( (1<<ADIF) & ADCSRA ) // AD-Wandlung beendet ? { // Welche Wandlung wurde beim letzten Aufruf gestartet 6=PowerSupply 7=Matte activatedADChannel = ADMUX & 0x07; if ( activatedADChannel == AD_CHANNEL_POWER_SUPPLY ) { b_wV = ADCH; // Daten 8 bit linksorientiert // Übernahme Messwert und Filterung; Annahme: langsame Änderung; kurze Einbrüche // oder Peaks interessieren uns hier nicht (das macht die Hardware) // ... } else // Matte { b_wM = ADCH; // Daten 8 bit linksorientiert // ... } // else Matte } // else AD-Wandlung beendet chnl = AD_CHANNEL_POWER_SUPPLY; if (activatedADChannel == AD_CHANNEL_POWER_SUPPLY ) { chnl = AD_CHANNEL_MAT_VOLTAGE; } ADCSRA = ( 1<<ADEN ) // ADC aktivieren | ( 0<<ADSC ) // Konvertierung noch nicht starten #ifdef MEGA8 | ( 0<<ADFR ) // NICHT Free Running Select #endif #ifdef MEGA88 | ( 0<<ADATE) // NICHT Free Running Select / AutoTrigger Disabled #endif | ( 1<<ADIF ) // ADC Interrupt Flag löschen (durch Schreiben einer Eins) | ( 0<<ADIE ) // Keinen Interrupt bei Wandlungsende auslösen // Frequenzvorteiler: #ifdef MEGA8 // beim mega8: | ( 6<<ADPS0); // ADPS2==1 & ADPS1==1 & ADPS0==0 ==> Teiler=64 // bei 8MHz-Takt --> ADC-Takt=125kHz #endif MEGA8 #ifdef MEGA88 // beim mega88: | ( 0<<ADPS0); // ADPS2==0 & ADPS1==1 & ADPS0==0 ==> Teiler=4 // bei 8MHz-Takt --> ADC-Takt=2MHz // Dieser Wert wurde nach den Methoden der Experimentellen // Informatik ermittelt (bei diesem Wert treten keine // Fehlmessungen mehr auf. #endif MEGA88 #ifdef MEGA88 ADCSRB = 0; // beschreibt die Triggereigenschaften, hat der mega8 erst gar nicht #endif MEGA88 ADMUX = chnl // channel=0..7 (hier aber nur 6 und 7 möglich) | (1<<ADLAR) // Ergebnis linksshiften, damit stehen die uns // interessierenden 8 bit in ADCH | (0<<REFS1) // Verwende AREF als Referenzspannung | (0<<REFS0); ADCSRA |= (1<<ADSC); // starte ADC-Wandlung } </code>
ich hab mal gehört, das man nicht direkt nach dem setzen von admux auslesen sollte, da die internen schalter wohl ne zeit brauchen. setz doch probehalber mal nach dem auslesen das admux schonmal auf den nächsten kanal.
Das wars wohl doch nicht. Dann werde ich zu meinem Workaround greifen. Danke für Deine Antwort !
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.