ATMEGA325 - ADC einlesen ? - warum geht nicht ???!?!?!

Gast #308194
Lesenswert?

hey,

möchte gerne kanalA und kanalB am ATMEGA325 einlesen. leider bekomme
ich auf kanalA und kanalB immer das gleiche ergebnis (ergebnis der 1ten
wandlung). im debug-singlestep-betrieb bekomme ich richtige
wandlungsergebnisse. einfügen von kleinen und grossen delays hat keinen
erfolg bebracht ?!?!

-> was tun ?? - im datenblatt ist nichts vermerkt was darauf hinweist
?!?

HILFE !!!!
thx Neubi



void main(void)
{
byte x,y;

  ADCSRA = 0x86;       // init ADC (clock,...)
  x=ADReadResult(0);
  y=ADReadResult(1);
}



byte ADReadResult(byte Channel)
{
word Result=0;

  ADMUX = Channel;  // kanal wechseln
  ADCSRA |= 0x40;   // wandlung starten
  while(!(ADCSRA & 0x10));  // warten bis wandlung fertig
  ADCSRA |= 0x10;   // int-flag löschen

  Result = (ADCH << 8) + ADCL;  // ergebnis holen
  return (Result >> 2);         // auf 8bit kürzen
}
Gast #308195
Lesenswert?

Du musst beim lesen der AD-Register unbedingt die Reihenfolge einhalten
(erst das Low Byte ADCL, dann das High-Byte ADCH). Was der Compiler aus
dem Konstrukt macht, das Du da geschrieben hast, ist undefiniert! Am
besten direkt das 16-Bit-Ergebnis aus ADC (oder ADCW) auslesen. dann
macht der Compiler das automatisch korrekt.

Gruß

Johnny
Gast #308196
Lesenswert?

Falls es nicht einleuchtet: Sobald das Low-Byte (ADCL) gelesen wird,
sperrt der Controller das High-Byte (ADCH) gegen Schreibzugriffe durch
den ADC. Erst wenn das High-Byte gelesen wird, gibt der Controller die
beiden Register wieder frei, so dass der ADC das nächste Ergebnis
ablegen kann.

Dein Code liest aber erst das High-Byte ein, shiftet es um 8 Stellen
nach links und addiert dann das Low-Byte. In diesem Moment sperrt der
Controller das komplette Register, so dass alle folgenden
Wandlungsergebnisse nicht gespeichert werden!

Die mir bekannten Compiler (WINAVR, CodeVision) besitzen alle in der
entsprechenden Headerdatei eine Definition eines
16-Bit-Ergebnisregisters ADC oder ADCW, das direkt eingelesen werden
kann:

Result = ADC;

Wenn Du eh nur 8 Bit brauchst, dann setz das ADLAR-Bit in ADMUX
(dadurch wird das Ergebnis linksbündig in den Registern ADCH und ADCL
gespeichert) und lies immer NUR das High-Byte aus. Das reduziert den
Rechenaufwand!

Gruß

Johnny
Gast #308198
Lesenswert?

> Result = ADCL + (ADCH<<8);

Ist aber (glaub ich) im ANSI-Standard nicht definiert, in welcher
Reihenfolge der Compiler das abarbeitet.

Am besten in mehreren Schritten machen, dann ist man auf der sicheren
Seite. Und der Code wird trotzdem nicht größer.

Am allerbesten die Variante mit ADC! Dafür isse da! Und für 8 Bit siehe
oben!

Gruß

Johnny

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren