www.mikrocontroller.net

Forum: Compiler & IDEs Probleme mit AD Wandler am AT90CAN128


Autor: Stephan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Morgen Forumsgemeinde,

ich habe ein Problem mit dem AD-Wandler an meinem AT90CAN128. Ich habe 
den Quellcode aus dem AVR-GCC Tutorial genommen und anversich nicht 
verändert, bis auf eine Abfrage welche Reversenzspannung genommen werden 
soll.

Hier kurz den Quellcode:
uint16_t ReadChannel(uint8_t mux, uint8_t referenz)
{
  uint8_t i;
  uint16_t result;

  ADMUX = mux;                      // Kanal waehlen

  if(referenz == 0)
    ADMUX |= (0<<REFS1) | (1<<REFS0) | (0 << ADLAR); //externe Referenzspannung(5V) nutzen
  if(referenz == 1)
    ADMUX |= (1<<REFS1) | (1<<REFS0) | (0<<ADLAR);  //interene Referenzspannung (2,56V) nutzen

  ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);    // Frequenzvorteiler
                               // setzen auf 128 (1) und ADC aktivieren (1)

  /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
     also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
  ADCSRA |= (1<<ADSC);              // eine ADC-Wandlung
  while ( ADCSRA & (1<<ADSC) ) {
     ;     // auf Abschluss der Konvertierung warten
  }
  result = ADCW;  // ADCW muss einmal gelesen werden,
                  // sonst wird Ergebnis der nächsten Wandlung
                  // nicht übernommen.

  /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
  result = 0;
  for( i=0; i<4; i++ )
  {
    ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
    while ( ADCSRA & (1<<ADSC) ) {
      ;   // auf Abschluss der Konvertierung warten
    }
    result += ADCW;        // Wandlungsergebnisse aufaddieren
  }
  ADCSRA &= ~(1<<ADEN);             // ADC deaktivieren (2)

  result /= 4;                     // Summe durch vier teilen = arithm. Mittelwert

  return result;
}

Wie ihr seht frage ich vor dem beschreiben des ADMUX-Registers die 
Variable "referenz" ab um die gewünschte Referenzspannung in das 
Register zu programmieren.
In meiner while-Schleife in meiner Main-Funktion rufe ich direkt 3 mal 
hintereinander die "ReadChannel"-Funktion auf, um die Channel 0 bis 2 
wandeln zu lassen.
while(1)
{
     .
     .
     .

     ergebnis1 = ReadChannel(0, ad_wandler1[1]);
     ergebnis2 = ReadChannel(1, ad_wandler2[1]);
     ergebnis3 = ReadChannel(2, ad_wandler3[1]);
     
     .
     .
     .
}

Das funktioniert auch soweit nur wenn ich z.B. dem Channel 0 die 2,56 
Volt  interneReferenzspannung zuweise und den Channeln 1 und 2 die 5 
Volt externe Referenzspannung zuweise bekomme ich kein vernünfiges 
Ergebnis für die einzelnen Wandlungen.
Variable "result" vom Channel 0 hat bei einer Spannung von 1 Volt bei 
der intern Referenzspannung einen Wert von 265 sollte aber rechnerisch 
bei 400 liegen.
Variable "result" der Channel 1 und 2 hat einen Wert von 222 bei einer 
realen Referenzspannung von 4,6 Volt.

Wenn ich allen 3 Channeln die gleicher Referenzspannung zuweise, egal 
welche, passen alle 3 Ergebnise.

Hat jemand von euch eine Idee wo ich den Fehler habe? Kann vieleich der 
AD-Wandler nicht schnell genug seine Referenzspannung umschalten?

Ich dank euch allen wie immer für eure Hilfe.

Gruß
Stephan

Autor: ADC (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Datenblatt sagt:

21.5 Changing Channel or Reference Selection
...
Note that the conversion starts on the following rising ADC clock edge 
after
ADSC is written. The user is thus advised not to write new channel or 
reference selection values
to ADMUX until one ADC clock cycle after ADSC is written.

Vielleicht solltest du nach dem Umschalten ein bisschen warten oder den 
ersten ausgelesenen Wert verwerfen...

Autor: ADC (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich sehe gerade, dass du das ja machst.
Probier es doch mal, wenn du ihm etwas mehr Zeit gibst. (zB zwei oder 
drei Dummyreads)

Autor: Stephan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die schnelle Antwort. Werde ich mal versuchen.

Autor: Stephan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also wenn ich 10 Dummyreads mach dann funktioniert es, aber des ist doch 
eigendlich auch nicht Sinn der Sache, oder?

Autor: Andreas R. (rebirama)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich vermute das ist ein elektrisches, kein Softwarepoblem.

Du schaltest zwischen interne Ref und AVCC als Ref um.
Beide Referenzspannungen werden mit dem Kondensator an AREF gepuffert.
-> Du musst warten, bis der Kondensator umgeladen wurde.
(21.5.2 im Datenblatt)

-> Kondensator kleiner machen oder Wartezeit nach dem Referenzwechsel 
erhöhen.

Autor: Stephan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das mit der Ladezeit des Kondensators klingt logisch. Ich lass einfach 
den AD-Wandler die Dummyreads machen.

Dank euch mal wieder.

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.