www.mikrocontroller.net

Forum: Compiler & IDEs ADC Rutine vom GCC-Tutorial


Autor: Richard B. (rbrose)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

es geht um diese Methode vom GCC-Tutorial:

uint16_t ReadChannel(uint8_t mux)
{
  uint8_t i;
  uint16_t result;
 
  ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);    // Frequenzvorteiler 
                               // setzen auf 8 (1) und ADC aktivieren (1)
 
  ADMUX = mux;                      // Kanal waehlen
  ADMUX |= (1<<REFS0); // AVCC als Referenz
 
  /* 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;
}

Es wir in der Methode der ADC immer komplett neu initialisiert, bei 
jeder Messung.
Ist das sinvoll? wird das nicht lagsam? Ich messe jede 10ms einen Wert 
... ist es nicht besser wenn man den ADC in der main Einstellt und dann 
in der  ReadChannel Methode den ADC nur ein und ausmacht?

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Richard B. (rbrose)

>es geht um diese Methode vom GCC-Tutorial:

Das ist eine einfache Funktion. Wie sind hier bei C, nicht C++.

>Es wir in der Methode der ADC immer komplett neu initialisiert, bei
>jeder Messung.

Ja.

>Ist das sinvoll?

Nein.

> wird das nicht lagsam?

Ja.

> Ich messe jede 10ms einen Wert
>... ist es nicht besser wenn man den ADC in der main Einstellt und dann
>in der  ReadChannel Methode den ADC nur ein und ausmacht?

Ja.

MfG
Falk

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>es geht um diese Methode vom GCC-Tutorial:
>
> Das ist eine einfache Funktion. Wie sind hier bei C, nicht C++.

Und C++ ist nicht Java.

Autor: Richard B. (rbrose)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, ich benutze den AtMEga168 und habe ADC so eingestellt:
  //init ADC
  ADCSRA |= (1<<ADEN) | (1<<ADSC) | (1<<ADPS2) | (1<<ADPS1);    // Frequenzvorteiler 
                               // setzen auf 64 (1) und ADC aktivieren (1)   //Free Running Mode     
    ADMUX |= (1<<REFS0) | (1<<ADLAR); // AVCC als Referenz //ADC0

Aber wenn ich mit
  char buffer[7];
  itoa(ADCH, buffer,10);
  uart_puts(buffer);

ADCH jede Sekunde ausgeben ist die Variable immer 255 groß, egal welcher 
Wert an PC0 anliegt.

Was ist falsch? Habe ich etwas übersehen? Mit ADSC sollte es jetzt im 
Free Running Mode permanent messen oder?

Autor: Richard B. (rbrose)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
MMhh der ADC scheint zu funktionieren ... weil wenn ich die Taste Drücke 
und dann der AVR anmachen, dann zeigt er mir ein anderen Wert an .. aber 
alle folgende sind gleich. Das heißt der Free Running Mode klappt nicht 
... Ich dachte er Updated das ADCH automatisch.

Beim ATTiny26 muss man das ADFR Bit aktivieren ... aber der AtMega168 
hat es nicht. Das wird im Register ADCSRB gemacht. Sehe ich das Richtig? 
Aber om Register ADCSRB ist Free Running Mode default ausgewählt, also 
brauche ich da nichts ändern.

Was ist falsch?

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Richard B. (rbrose)

>ADCH jede Sekunde ausgeben ist die Variable immer 255 groß, egal welcher
>Wert an PC0 anliegt.

Lies das Tutorial. GENAU!

>Was ist falsch? Habe ich etwas übersehen?

Ja. Du musst ADCW lesen, das ist der ADC als 16 Bit Wert. Denn der 
Zugriff auf ADCL ADCH muss VOLLSTÄNDIG in der RICHIGEN Reihenfolge 
erfolgen. Sonst liest du nämlich immer das gleiche.

> Mit ADSC sollte es jetzt im Free Running Mode permanent messen oder?

Ja.

MFG
Falk

Autor: Richard B. (rbrose)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Falk

Wieso muss ich ADCW lesen? Ich habe doch ADLAR aktiviert.
Und Peter Dannegger liesst im seinem Beispiel auch nur ADCH aus:

http://www.mikrocontroller.net/attachment/highlight/21646

Lese jetzt ADCW aus ... ist aber nicht viel besser ... jetzt bekomme ich 
-64^^

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Richard B. (rbrose)

>Wieso muss ich ADCW lesen?

Warum liest du nicht des Tutorial GENAU! Dann würdes du DAS hier finden.

"
Wenn eine Umwandlung abgeschlossen ist, befindet sich der gemessene Wert 
in diesen beiden Registern. Von ADCH werden nur die beiden 
niederwertigsten Bits verwendet. Es müssen immer beide Register 
ausgelesen werden, und zwar immer in der Reihenfolge: ADCL, ADCH. Der 
effektive Messwert ergibt sich dann zu:

x = ADCL;       // mit uint16_t x
x += (ADCH<<8); // in zwei Zeilen (LSB/MSB-Reihenfolge und
                // C-Operatorpriorität sichergestellt)

oder

x = ADCW; // je nach AVR auch x = ADC (siehe avr/ioxxx.h)
"

MfG
Falk

Autor: Richard B. (rbrose)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wieso widerspricht ihr euch hier im Forum??


Beitrag "ADC des ATMEGA168"
>Autor: Andreas Kaiser (a-k)
>Datum: 01.03.2008 16:28
>
>ADLAR setzen und nur ADCH verwenden.
>

Dennach kann ich nur ADCH lesen ....

Aber das ich nicht der Fehler ... man musste ADATE aktivieren.
Aber irgendwie will er trotzdem nicht richtig funktinieren.
Ich glaube es liegt am AtMega168 ...

Autor: Richard B. (rbrose)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Falk
Du hast dich geirrt, ich muss nicht ADCL vor ADCH auslesen wenn ADLAR 
gesetzt ist.

Habe jetzt in die Schaltung einen ATMega8 getan ... und da klappt es 
problemlos mit 8bit und 10bit.

Ich glaube der AtMega168 hat ein Bug. Finde irgendwie auch nicht viel 
über den 168 im Free  Running mode.

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist das :
//init ADC
  ADCSRA |= (1<<ADEN) | (1<<ADSC) | (1<<ADPS2) | (1<<ADPS1);    // Frequenzvorteiler 
                               // setzen auf 64 (1) und ADC aktivieren (1)   //Free Running Mode     
    ADMUX |= (1<<REFS0) | (1<<ADLAR); // AVCC als Referenz //ADC0
wirklich der Code den du benutzt?
Ich würde es ja eher so versuchen:
ADMUX  = (1<<REFS0) | (1<<ADLAR); //erst initialiseren, DANN starten
ADCSRA = (1<<ADEN) | (1<<ADSC) | (1<<ADATE) | (1<<ADPS2) | (1<<ADPS1);
    //                           ^^^^^^^^^^
    //                           free-running mode...
Oder z.B. im ADC-Interrupt die nächste Wandlung starten, WENN du mehrere 
Kanäle wandeln willst.
Außerdem kannst du dir mal das Register ADCSR*B* bei den AtmegaX8 
anschauen..

hth. Jörg

Autor: Richard B. (rbrose)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Jörg
was meintest du in dem anderen Thread mit

>> ADCSRB = (0<<ADTS2) | (0<<ADTS1) | (1<<ADTS0);   // Free running mode.
>Das stimmt nicht...

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit diesem Pattern triggert der ADC auf den AC.

Autor: Richard B. (rbrose)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
DANKE DIR JÖRG!! Es lag an der reihenfolge ;-)
Erst ADMUX und dann ADCSRA.
Jetzt funktioniert es.

Autor: Richard B. (rbrose)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ADCSRB = (0<<ADTS2) | (0<<ADTS1) | (1<<ADTS0);   // Free running mode.

Es stimmt so ... 0 0 0 ist für Free running mode. Steht im Datenblatt 
von dem AtMega168.

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da steht aber nicht 0 0 0, da steht 0 0 1.

Autor: Richard B. (rbrose)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aber wieso wird dann im dem AVR Tutorial erst ADCSRA beschaltet und dann 
ADMUX ?
Man sollte es mal überarbeiten. Ist ja ein sehr schlechtes Beispiel. 
Nicht allgemein gültig!

Autor: Richard B. (rbrose)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Andreas?
Bin ich blind? Oder habe ich ein anderes Datenblatt?

Table 23-5. ADC Auto Trigger Source Selections
ADTS2 ADTS1 ADTS0 Trigger Source
0 0 0 Free Running mode
0 0 1 Analog Comparator
0 1 0 External Interrupt Request 0
0 1 1 Timer/Counter0 Compare Match A
1 0 0 Timer/Counter0 Overflow
1 0 1 Timer/Counter1 Compare Match B
1 1 0 Timer/Counter1 Overflow
1 1 1 Timer/Counter1 Capture Event


0 0 1 wäre der Analog Comparator.

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Putz die Brille, wisch dir die Augen und lass mal jemand aus deiner 
Umgebung drauf gucken. Vielleicht siehst du dann, dass da (1<<ADTS0) 
steht, nicht etwa (0<<ADTS0).

Autor: Richard B. (rbrose)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alles klar ;-) Im Code ist es falsch .. nicht im Datenblatt. Ich merke 
es jetzt, sitze schon zu lange vor dem PC :-) Sehe den Wald vor lauter 
Bäume nicht.

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.