www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Probleme mit ADC auf Mega8 und Mega88


Autor: Willi Wacker (williwacker)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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>

Autor: Werner A. (homebrew)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Willi Wacker (williwacker)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das wars wohl doch nicht. Dann werde ich zu meinem Workaround greifen.

Danke für Deine Antwort !

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.