Hallo zusammen, ich habe einen ATmega64M1 und möchte mit diesem eine ADC-Messung durchführen. Ich arbeite mit einem externen 16MHz-Quarz. Habe hierfür auch die Fuse-Bits richtig eingestellt. Mein Problem ist, dass ich eine 10-Bit-ADC habe (laut Datenblatt), jedoch werden im Register mehr als 10 Bit beschrieben (Ausgelesen mit dem Befehl ergebnis = ADCW). Soll heißen, die Umrechnungsformel für 10 Bit (Vin = Vref*ADC/1024) nach Datenblatt liefert ein falsches Ergebnis, rechne ich jedoch mit 16 Bit (Vin = Vref*ADC/65535) funktioniert der Aufbau wie er soll! Kann mir bitte jemand erklären was da los ist? Habe ich evtl. doch einen 16-Bit ADC Wandler aber hab irgendwas darüber überlesen? Das Programm: #include "avr/io.h" #include "avr/interrupt.h" float dummy; unsigned int ergebnis; // UNTERPROGRAMME void init_timer0(void); void ADC_Init(void); //HAUPTPROGRAMM int main(void) { DDRD |= (1<<DDD7); // Pin D7 als Ausgang festlegen, alle anderen D-Pins sind als Input deklariert! S.72 PORTD |= 0b0111111; //Pin D7 ausschalten, alle anderen D-Pins sind eingeschalten. Da diese als Input deklariert sind, wurde jetzt Pull-Up-Resistor aktiviert init_timer0(); // Timer0 aufrufen ADC_Init(); // Aufrufen des Unterprogramms ADC-Initialisierung ergebnis=0; dummy = 0; sei(); while(1) {/* PROGRAMMSCHLEIFE*/} return(0); } //UNTERPROGRAMME //#Timer_Einstellungen void init_timer0(void) { TCNT0 = 0; // Timer/Counter resetet OCR0A = 127; // nach 128 Stufen zurück auf TIMSK0 = (1<<OCIE0A); // compare match A interrupt is enabled TCCR0A |= (1<<COM0A1)|(0<<COM0A0)|(1<<WGM01); // Clear OC0A on compare match TIFR0 = (1<<OCF0A); // Führe Match-Interrupt aus! TCCR0B |= (1<<CS02)|(0<<CS01)|(1<<CS00); // clock prescaler auf /1024 } // ADC_Initialisieren void ADC_Init(void) { ADMUX = (1<<AREFEN) | (0<<ISRCEN) | (0<<REFS1) | (1<<REFS0); // externe Referenzspannung 5V (Versorgungsspannung) ADMUX |= (0<<MUX4)|(0<<MUX3)|(1<<MUX2)|(0<<MUX1)|(1<<MUX0); // ADC5 ADCSRA |= (1<<ADEN); // Enable ADC ADCSRA |= (1<<ADSC); // In Free-Running mode this bit to 1 for first conversion ADCSRA |= (1<<ADATE); // ADC auto trigger enable ADCSRA |= (1<<ADIE); // Enable Interrupt ADCSRA |= (0<<ADLAR); ADCSRA |= (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // /128 prescale ADCSRB = (0<<ADTS3) | (0<<ADTS2) | (1<<ADTS1) | (0<<ADTS0); // Triggersource Timer/counter0 compare match A ADCSRB = (1<<ADHSM); // ADC-High Speed Mode DIDR0 = (1<<ADC0D); // digital input disabled } //ISR's ISR(ADC_vect) { ergebnis = ADCW; dummy = (4.96)*ergebnis/65535; //Vin = Vref*ADC/1024 if (dummy>=1.8) { PORTD = (1<<DDD7); //PD7 anschalten } else { PORTD = 0x00; } }
Du hast das Ergebnis der Wandlung links ausgerichtet (für 8-Bit-Ergebnis gedacht). ... ... Sieh dir mal ADLAR und AREFEN genauer an.
und irgendwie Schmeißt Du die Register durcheinander. Mal abgesehen von der 0 Schieberei (0 << XXX)
Habe die Erläuterung im Datenblatt AREFEN falsch verstanden! Jetzt geht es wie es soll! Danke für die schnelle Hilfestellung!
Lukas D. schrieb: > Jetzt geht es wie es soll! Reiner Zufall! Du hast die Zuordnung der Bits zu den Registern vertauscht!
Hallo nochmal! Ich habe mir das ganze jetzt moch einmal angesehen und verstehe es nicht! Ich habe doch das Ergebnis der Wandlung rechts ausgerichtet (10 Bit). Siehe dazu Bild ADLAR und ADLAR1. Wenn ich ADLAR=0 "setze" (lasse wie er ist) habe ich das Register rechts ausgerichtet und 10 Bit. Wie/wo sind die Register durcheinander geraten? Zudem würde mich interessieren wie das mit dem Register generell ist. Wenn ADLAR=0 wird zuerst ADCL und dann ADCH beschrieben, richtig? Das Auslesen habe ich so verstanden: Zuerst ADCL und erst dann ADCH auslesen. Aber das geschieht im Background. Da habe ich ja nichts drann geändert! Was auch nicht ganz durchsichtig ist, ist die Einstellung zur externen Referenzspannung! Hier habe ich die zweite Einstellung von oben gewählt, siehe Bild AREFEN! Somit muss AREFEN=1 gesetzt werden. Etwas weiter unten im Datenblatt finde ich aber folgende Info zu AREFEN, Bild AREFEN1. Das wiederspricht sich doch!!! AREFEN=0 damit interne AREF getrennt ist von AREF. Oben steht aber das AREFEN=1 gesetzt werden soll um externen Kondensator auf AREF zu legen. Generell interessiert mich auch wo die Unterschiede in den ersten drei Einstellungsoptionen zur Referenzspannung liegen? 1: External Vref on AREF pin, Internal Vref is switched off 2: AVcc with external capacitor connected on the AREF pin 3: AVcc (no external capacitor connected on the AREF pin) 1 und 3 scheinen das selbe zu sein?! Wenn Ihr mir das Entwirren könntet wäre ich euch sehr dankbar! Grüße, Luk
> ADMUX = (1<<AREFEN) | (0<<ISRCEN) | (0<<REFS1) | (1<<REFS0); ISRCEN steht in ADCSRB (auch wenn das hier wegen der 0 keine Rolle spielt) AREFEN dito, spielt eine Rolle. > 1 und 3 scheinen das selbe zu sein?! Mitnichten. Bei 1 muss eine Referenzspannung von außen angelegt werden, bei 3 wird die Versorgungsspannung AVcc als Referenz benutzt.
Das Bit ADLAR repräsentiert zur besseren Unterscheidung die Zahl 5. Mit '1 << ADLAR' kan man in irgendeinem Register das 5. Bit setzen. Genauso ist es mit 'AREFEN'. Dein Eingangspost:
1 | ADMUX = (1<<AREFEN) /* .... */ |
2 | //
|
3 | //
|
4 | ADCSRA |= (0<<ADLAR); |
Diese beiden Befehle 'bearbeiten' in den jeweiligen Registern das 5.Bit. Nur: Das 5.Bit in ADMUX hat die Bezeichnung 'ADLAR'. Auch wenn du die Bezeichnung 'AREFEN' verwendest, sagst du dem µC trotzdem, das er das Ergebnis der Wandlung links ausrichten soll. Beim zweiten Befehl passiert nichts Schlimmes. Nämlich gar nichts. Das wäre nur kritisch wenn 'ADATE' nicht gesetzt werden soll, und du mit '1 << ADLAR' das 5.Bit einschaltest. Bit 5 in 'ADCSRA'? Richtig 'ADATE'. Die Auswahl der Referenz kann im Register 'ADCSRB' vorgenommen werden, in dem sich auch ein Bit (Nummer 5) befindet ... mit dem Namen 'AREFEN' ... Alle anderen Bits schaust du dir noch mal an.
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.