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.