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 }
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
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
im Prinzip müsste es dann ja so funktionieren: Result = ADCL + (ADCH<<8); IAR: Result = ADC;
> 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
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.