Hallo zusammen, ich beschäftige mich gerade intensiv mit dem ADC im free running mode und habe dazu ein paar Fragen. Einige Sachen im Datenblatt sind mir unklar. Meine Funktion sieht wie folgt aus: uint16_t ADC_Read_free_running_mode( uint8_t channel ) { static uint8_t channel_vorheriger, result; if (channel_vorheriger!=channel) //wenn ein neuer Kanal gewählt wurde, dann Kanal einstellen und Testmessung { //Wandlung mit der Änderung des Kanals synchronisieren loop_until_bit_is_set(ADCSRA, ADIF); //channel change during a conversion will not go in effect ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F); // Kanal waehlen, ohne andere Bits zu beeinflußen _delay_us(250); // 250us Warten, damit die Elektronik sich darauf einstellen kann, verlangsamt das Programm unnötig!!!!!! kann man das ändern? result=ADCW; //eine Messung machen die verworfen wird } channel_vorheriger=channel; return ADCW; // ADC auslesen und zurückgeben Mit loop_until_bit_is_set(ADCSRA, ADIF) will ich die Kanaleinstellung synchronisieren und warten bis die Wandlung abgeschlossen ist, damit auch tatsächlich der Kanal eingestellt ist, den ich erwarte. Laut Datenblatt wird ADIF gelöscht (auf Null oder 1 gesetzt??? auf 1 oder?), wenn der dazugehörige interruptvector ausgeführt wird. Im free running mode wird kein vector ausgeführt und somit auch kein bit gelöscht, oder? Ich müßte es dann manuell nach jedem lesevorgang auf 1 setzen, um es zu löschen??? Im Datenblatt steht, das es gelöscht wird, indem man eine 1 schreibt!! Dann auch wieder im Datenblatt: After the conversion is complete ADIF is high. Muss ich ADIF also danach wieder im free running mode manuell auf Null setzen? ADCSRA&= ~(1<<ADIF); //löschen würde meine Funktion dann so aussehen müssen?? loop_until_bit_is_set(ADCSRA, ADIF); ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F); ADCSRA&= ~(1<<ADIF); //löschen _delay_us(220); result=ADCW; Was sagt ihr zu diesem _delay_us(220)????? Immer nach einer Kanaländerung muss gewartet werden, damit sich die Elektronik darauf einstellt. Hält dies mein Programm nicht unnötig auf und man könnte die Funktion im free running mode nicht anders, ohne delay, schreiben?? Wie würdet ihr das denn besser machen? Wozu benötigt man das DIDR0? Digital Input Disable Register 0 man kann damit, laut Datenblatt, den input buffer des betreffenden ADC PIN deaktivieren. Wenn man den digitalen Input nicht benötigt, dann kann man etwas einstellen, aber wozu und weshalb? Könntet ihr mir das bitte erklären? Es wäre nett, wenn ihr mir zu meienr Probelmatik noch ein paar Tipps geben könntet. Herzlichsten Dank, Matthias.
Hallo Matthias, du hast doch schon einen Thread zu diesen Themen offen. Beitrag "Analogmessung mehrerer Kanäle hinterteinander, überall gl. Werte?" im letzten Beitrag des Alten Threads hatte ich versucht das syncronisierte Ändern des Kanals zu beschreiben. 1. Syncronisieren, dann wie du gelesen hast ADIF löschen.
1 | ADCSRA = (1<<ADIF); //löschen |
Oder einfacher die ISR-ADC-Routine hinschreiben:
1 | ISR(ADC_vect) // ADC Conversion Complete |
2 | {
|
3 | // evtl. weiterer code
|
4 | // Flag.
|
5 | }
|
Dann geht das Löschen von ADIF automatisch. Aber syncrones Ändern wird nicht mehr über ADIF signalisiert, evlt. ein Flag verwenden. 2. ADC stoppen ADEN=0 und Auto Trigger off ADATE=0 3. ADC-Kanal ändern, 4. ADC Starten ADEN=1 und eine Wandlung starten ADSC=1 5. auf das Ende der ersten Wandlung warten:
1 | loop_until_bit_is_not_set(ADCSRA, ADSC); |
5. ADC-Werte lesen und verwerfen:
1 | (void)ADCW; |
6. Free Running mode setzen
1 | ADCSRB = (0<<ADTS2) ^ (0<<ADTS1) ^ (0<<ADTS0); |
7. Starte erste Wandlung ADSC=1, ADC Auto Trigger Enable ADATE=1
1 | ADCSRA |= (1<<ADSC) ^ (1<<ADATE); |
Aber warum soll der ADC im Freerunning Mode laufen, wenn Du die Messwerte nicht verwendest ? Vielleicht einfach nur eine ADC-Wandlung mit ISR-ADC um ein Flag zu setzen dass die Wandlung fertig ist. Danach in der Main das Flag abfragen und eine neue ADC-Wandlung starten. Also sind das zwei unabhängige Prozesse ADC-Wandlung (ISR) und ADC-Wert auslesen (main-prozess). Damit ist keine delay mehr nötig !
Hallo Uwe, vielen Dank, das Du mir weiter helfen willst. Ich habe Deine ausführliche Routine gestern auch intensiv bearbeitet und bin schon, Dank Deiner Hilfe, ein gutes Stück weiter gekommen. Einige Funktionen davon kenne ich aber noch nicht, deswegen wollte ich nochmal nachfragen. Hättest Du denn vielleicht auch Zeit mir das am Telefon zu erklären? Gern gebe ich Dir für die Zeit auch Geld (20€ für 30min, damit ich das Thema ADC bald mal durch habe :-) ). Ansonsten halt hier im Forum auch gern. ja, ich habe schon ein Thread zum Thema offen, war wohl doch nicht so gut ein neues auf zumachen. Dachte das wird es noch mehr gelesen, aber das ist wohl Unsinn. Ich werde mir Deine Codebeispiele die Tage weiter durcharbeiten oder jederzeit mit Dir am Telefon. Jetzt würde ich dann erst mal andere wichtige Fächer für die Schule bearbeiten. Woher kommt die ISR (ADC_vect) Routine??? ist das ein automatischer Timeraufruf, so wie Du den Timer in Deinem Beispeil initialisiert hast? IM gesamten PDF finde ich kein Stichwort zu ADC_vect oder ist das eine von Dir selbst erstellte Funktion? Ich hatte noch keine Zeit mir diese Funktion genau anzuschauen. Oder einfacher die ISR-ADC-Routine hinschreiben: ISR(ADC_vect) // ADC Conversion Complete { // evtl. weiterer code // Flag. } Wozu soll der free running modus denn sonst gut sein, als ihn nicht nach jedem Kanalwechsel so aufwendig und zeitaufwendig neu initialisieren zu müssen? Im single modus dauert die erste Messung ungefähr 25 clock cycles, initialisierung usw. Diese Zeit wollte ich mir im free running modus sparen. Das geht wohl aber anscheinend nur, wenn ich bei einem Kanal bleibe, oder? Herzlichsten Dank für Deine Unterstützung Uwe, viele Grüße, Matthias.
>Wozu benötigt man das DIDR0? Digital Input Disable Register 0 >man kann damit, laut Datenblatt, den input buffer des betreffenden ADC >PIN deaktivieren. Wenn der Pegel eines Analogsignals sich zufällig in der Nähe der digitalen Umschaltpunkte befindet, kann das ein ständiges, häufiges Kippen der Digitalstufe bewirken. Um den damit verbundenen unnötigen Stromverbrauch zu vermeiden, kann man für ausschließlich analoge Eingänge den Input Buffer über das DIDR abschalten.
Vielen Dank für Deine Antwort. Vuvuzelatus schrieb: >>Wozu benötigt man das DIDR0? Digital Input Disable Register 0 > >>man kann damit, laut Datenblatt, den input buffer des betreffenden ADC >>PIN deaktivieren. > > Wenn der Pegel eines Analogsignals sich zufällig in der Nähe der > digitalen Umschaltpunkte befindet, kann das ein ständiges, häufiges > Kippen der Digitalstufe bewirken. Um den damit verbundenen unnötigen > Stromverbrauch zu vermeiden, kann man für ausschließlich analoge > Eingänge den Input Buffer über das DIDR abschalten.
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.