Hallo, ich versuche grade den ADC des Atmega8 im FreeRun Modus zu betreiben, das will mir jedoch nicht so ganz gelingen. Also ich weiß nicht genau woran es liegt und wollte daher einfach mal wissen, ob ich den ADC so richtig benutze/initialisiere: void ADC_init() { ADMUX = 3; // channel 3 ADMUX |= (1<<REFS0); // vcc als ref verwenden ADCSRA = (1<<ADEN) | (1<<ADPS0) | (1<<ADPS1) | (0<<ADPS2) | (1<<ADFR); // 8x prescaler at 16Mhz crystal } uint16_t GetValue() { return ADCW; } Ich weiß, der Prescaler ist sehr klein, muss aber sein ;) Laut Datenblatt geht das, es leidet halt nur die Qualität der Messungen, das ist aber nicht so schlimm.
Hi Der ADC muss gestartet werden ->'ADSC'-Bit. Teiler 8 ist arg schnell. Mit 128 würdest du im grünen Bereich liegen. MfG Spess
>Der ADC muss gestartet werden ->'ADSC'-Bit. Teiler 8 ist arg schnell. >Mit 128 würdest du im grünen Bereich liegen. Und man muss auf das Ergebnis warten. Den Scheiss der da oben als Code angeboten wird kann er sich an die Tapete nageln.
Dir ist klar, dass es um den Free Run Modus geht?!?! Da muss ich wenn ich das Datenblatt richtig interpretiere auf nichts warten. Wenn doch würde es erklären warum es nicht geht. When this bit is set (one) the ADC operates in Free Running mode. In this mode, the ADC samples and updates the Data Registers continuously. Clearing this bit (zero) will terminate Free Running mode.
Hi >Dir ist klar, dass es um den Free Run Modus geht?!?! >Da muss ich wenn ich das Datenblatt richtig interpretiere auf nichts >warten. Wenn doch würde es erklären warum es nicht geht. Selbstverständlich musst du auf das Ende einer Conversation warten. Woher willst du wissen, wann ein gültiges Ergebnis vorliegt? So wie du dir das vorstellst, ist Würfeln wesentlich genauer. MfG Spess
Wenn das Einlesen eines Analog-Signals nicht besonders eilig ist, dann nutze ich auch gern den Free-Run-Mode. Allerdings lese ich das Ergebnis dann nebenher im Timer-Interrupt oder einem vom Timer-Interrupt synchronisierten Job aus, so dass zwischen den Ausleseterminen eine oder mehrere ADC-Wandlungen stattgefunden haben. Dazu ist es natürlich erforderlich, mal zu überschlagen, wie lange ein Wandlungszyklus dauert, was mit einem Taschenrechner und dem Verständnis der Zusammenhänge kein Problem ist. Achja, der Timer wird nicht wegen des ADC gestartet, das ADC-Timing macht er nur nebenbei. Bei mir hat fast jedes AVR-Programm einen Timer laufen, der einen Großteil der Jobs synchronisiert und damit das Programm effizienter macht, indem man Warteschleifen und Busywaits vermeidet. ...
Hallo, du musst nicht zwangsläufig darauf warten, ob die Wandlung abgeschlossen ist oder nicht. Falls sie es nicht ist, liest du halt den Wert aus, der ein paar µs alt ist, wenn es auf die paar µs nicht ankommt, entsteht dadurch kein Problem.
freeRunMode wrote: > Hallo, > du musst nicht zwangsläufig darauf warten, ob die Wandlung abgeschlossen > ist oder nicht. Falls sie es nicht ist, liest du halt den Wert aus, der > ein paar µs alt ist, wenn es auf die paar µs nicht ankommt, entsteht > dadurch kein Problem. Jo, so hatte ich das auch verstanden und das ist auch voll OK. Das Problem ist, dass ich einen relativ schnellen Timer laufen habe (80kHz) der auf keinen Fall unterbrochen werden darf, also fällt der Interrupt-Vektor flach. Außerdem sollte auf eine Messung (die ruhig etwas älter sein darf) nicht lange gewartet werden müssen. Also ist der obere Code zusammen mit dem Start Befehl OK?
Was hindert Dich daran, in der Mainloop das Interrupt-Pending-Flag zu pollen und bei noch nicht fertigem ADC das Auslesen und Auswerten zu überspringen und dafür andere Jobs zu erledigen? ...
Nichts, ist auch eigentlich egal. Aber wann wir das Flag denn gesetzt?? Ich meine der Free Run Modus ist ja grade, dass er die ganze Zeit am arbeiten ist, also wird das Flag mal in einem einzelnen System Takt gesetzt oder wie???
Ich habe grade noch eine Erkenntnis gewonnen. Das mit dem Warten auf das Flag hilft auch nichts! Weil von dem Ende der Schleife bis zum nächsten Takt wo ich den Wert dann auslese kann er ja auch verändert werden, passiert zwar nur seeehhhhhhhhr selten (ca einer von 6500), darf aber nicht passieren. Gibt es evtl ne Möglichkeit Interrupts zu priorisieren, dass ich sagen kann sollte ein Timer Interrupt in der Warteschleife stehtn wird der auf jeden Fall als erster ausgelöst?
Fabian S. wrote: > Nichts, ist auch eigentlich egal. Aber wann wir das Flag denn gesetzt?? Wenn der ADC fertig ist und ein neues Ergebnis im Datenregister steht (letzteres allerdings unter der Voraussetzung, dass das Datenregister nicht durch einen falschen oder unvollständigen Zugriff blockiert ist, siehe AVR 16-Bit-Register)... > Ich meine der Free Run Modus ist ja grade, dass er die ganze Zeit am > arbeiten ist, also wird das Flag mal in einem einzelnen System Takt > gesetzt oder wie??? Schau bitte ins Datenblatt! Da steht, wie lange der ADC für eine Wandlung braucht. Und das ist erheblich mehr als ein Systemtakt!
>Das >Problem ist, dass ich einen relativ schnellen Timer >laufen habe (80kHz) der auf keinen Fall unterbrochen >werden darf, also fällt der Interrupt-Vektor flach. ??? Ein Timer-Overflow-Interrupt hält doch den Timer nicht an. In der TOVL-Interruptroutine kannst Du dann eine Variable zählen und diese regelmässig aus der main abfragen. Wo ist das Problem?
Das habe ich auch nie gesagt! Der ADC Interrupt hält evtl den Timer Interrupt auf! Und das darf nicht passieren.
> Der ADC Interrupt hält evtl den Timer Interrupt auf! Und das darf nicht > passieren. Das passiert auch nicht, wenn Du den ADC in der Mainloop ausliest. Die Mainloop ist ja, wie der Name schon sagt, eine Schleife. In dieser wird ADIF abgefragt. Ist es gesetzt, dann ist eine Wandlung fertig. Dann kannst Du: - ADCL und ADCH auslesen (da wird ein temporäres Hilfsregister aktiv, um das zu verhindern, was Du befürchtest, das ist aber im Datenblatt bestens erklärt) - ADIF durch Schreiben einer 1 löschen - den ausgelesenen ADC-Wert wegräumen bzw. auswerten Falls ADIF nicht gesetzt war, überspringst Du einfach diesen Block. Wo also ist Dein Problem??? Dein Timer schlägt (bei 16MHz Quarz) alle 200 Takte zu. Wenn die ISR halbwegs effizient programmiert ist, bleibt für die Mainloop massig Zeit für verschiedene Jobs. Es gibt auch noch die Möglichkeit, aus der Timer-ISR langsamere Takte abzuleiten. Man kann in der Timer-ISR z.B. ein Register herunterzählen. In der Mainloop fragt man das Register auf größer Startwert ab (das wäre ein Unterlauf), setzt es auf Startwert und arbeitet den Job ab. Das kostet in der ISR einen einzigen zusätzlichen Takt und bläht die Mainloop auch nicht unnötig auf. Bei einem Startwert von 79 entsteht dabei in Deinem Fall ein Jobtakt von 1kHz. Dies ist eine gute Basis für ADC lesen, Drehgeber abfragen, LCD bedienen, mit weiterem Teiler 1:16 Tasten entprellen, Berechnungen anschubsen, usw. Ein Timer kann nämlich bei guter Programmplanung etliche Arbeiten zugleich erledigen bzw. synchronisieren. ...
Mhh da hab ich wohl was verplant. Man muss warten bis das Bit gesetzt ist, dann ist er fertig und um es zu resetten muss man es wieder setzen? Ist es dann nicht immer auf 1?
> und um es zu resetten muss man es wieder setzen?
Ja, so ist es...
Mecker' nicht herum, lies und verstehe stattdessen das verdammte
Dartenblatt!!!
...
Ja ich habe meinen Fehler doch eingeräumt, dass ich mich in der einen Zeile im Datenblatt verlesen habe, wo steht, dass man es setzen und nicht löschen muss. > Mecker' nicht herum, lies und verstehe stattdessen das verdammte > Dartenblatt!!! Und du kannst mich wohl kaum dazu auffordern etwas zu verstehen, wenn ich bitten darf. Entwerder ich verstehe es oder nicht, wenn nicht und ich hier desshalb was frage ist das wohl berechtigt.
Man mag einräumen, das Hannes Lux Aufforderung ein wenig harsch klingt, aber sie ist nicht ohne Anlass geblieben. (Das Du gemeckert hast finde ich nicht). Ganz offensichtlich verstehst Du nicht irgendein Detail nicht, sondern: 1. Du weisst nicht, das AD-Wandlung gestartet werden muss -> Datenblatt 2. Du weisst nicht, das auf den Abschluss der Wandlung gewartet werden muss bzw. das es dafür einen Interrupt gibt. -> Datenblatt 3. Du weisst nicht, das auch im Free-Run-Modus nicht einfach Ergebnisse erzeugt werden -> Datenblatt 4. sondern das auch dort die Wandlung abgewartet werden muss -> Datenblatt 5. Du weisst nicht wie der Free-Run-Mode überhaupt geht -> Datenblatt 6. Du weisst nichts über die Wandlungsgeschwindigkeit -> Datenblatt 7. Du weisst nichts über Interruptprioritäten im AVR -> Datenblatt 8. Du weisst nicht das man die Prioritäten nicht verändern kann -> Datenblatt (zugegeben, das muss man daraus schliessen, das eine Möglichkeit dazu nicht angegeben ist.) Das heisst Dir fehlen die meisten Grundlagen für die AD-Wandlung und die Interruptbehandlung. Es ist ja nicht schlimm, das Du das alles nicht weisst. Aber ich finde es unhöflich von Dir zu erwarten, das wir Dir hier alles ohne eigene Anstrengung servieren und das wir hier Dein Halbwissen und Deine Vermutungen bestätigen oder widerlegen. Also lies BITTE das f... Manual und die Tutorials und stelle dann fragen die sich auf gelesenes und ausprobiertes beziehen.
Ahem wrote: > Man mag einräumen, das Hannes Lux Aufforderung ein wenig harsch klingt, > aber sie ist nicht ohne Anlass geblieben. (Das Du gemeckert hast finde > ich nicht). > > Ganz offensichtlich verstehst Du nicht irgendein Detail nicht, sondern: > > 1. Du weisst nicht, das AD-Wandlung gestartet werden muss -> Datenblatt Weiß ich, hatte ich auch gesagt, dass ichs nur vergessen hatte mit rein zu schreiben > 2. Du weisst nicht, das auf den Abschluss der Wandlung gewartet werden Und desshalb meine Frage, ob das was ich als aller erstes gepostet hatte korrekt ist. Wo auch das auslesen eines Wertes drin steht. Und ich habe im Datenblatt nichts gefunden, was aussagte, dass im Free Run Modus jemals ein ungültiger Wert in dem Register steht. > muss bzw. das es dafür einen Interrupt gibt. -> Datenblatt Ich hatte auch gesagt, dass ich den Interrupt nicht verwenden will/kann. > 3. Du weisst nicht, das auch im Free-Run-Modus nicht einfach Ergebnisse > erzeugt werden -> Datenblatt Wie gesagt, habe ich eben nicht gefunden (habe ich auch immer noch nicht) > 4. sondern das auch dort die Wandlung abgewartet werden muss -> > Datenblatt > 5. Du weisst nicht wie der Free-Run-Mode überhaupt geht -> Datenblatt > 6. Du weisst nichts über die Wandlungsgeschwindigkeit -> Datenblatt Wieso? Eigentlich schon? ADC Takt durch den Faktor (den ich bei der Initialisierung ja auch eingestellt habe und das auch begründet habe) und dann dauert eine Wandlung 13 Takte oder so. > 7. Du weisst nichts über Interruptprioritäten im AVR -> Datenblatt > 8. Du weisst nicht das man die Prioritäten nicht verändern kann -> > Datenblatt (zugegeben, das muss man daraus schliessen, das eine > Möglichkeit dazu nicht angegeben ist.) Da hast Recht, werde ich mir mal ansehen.
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.