Forum: Mikrocontroller und Digitale Elektronik mega8 - ADC im Free Run geht nicht


von Fabian S. (jacky2k)


Lesenswert?

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.

von spess53 (Gast)


Lesenswert?

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

von holger (Gast)


Lesenswert?

>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.

von Fabian S. (jacky2k)


Lesenswert?

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.

von spess53 (Gast)


Lesenswert?

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

von Hannes Lux (Gast)


Lesenswert?

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.

...

von freeRunMode (Gast)


Lesenswert?

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.

von Fabian S. (jacky2k)


Lesenswert?

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?

von Hannes Lux (Gast)


Lesenswert?

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?

...

von Fabian S. (jacky2k)


Lesenswert?

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???

von Fabian S. (jacky2k)


Lesenswert?

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?

von Johannes M. (johnny-m)


Lesenswert?

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!

von Fabian S. (jacky2k)


Lesenswert?

Wir reden doch hier von dem ADIF Wert oder???

von Spocki (Gast)


Lesenswert?

>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?

von Fabian S. (jacky2k)


Lesenswert?

Das habe ich auch nie gesagt!
Der ADC Interrupt hält evtl den Timer Interrupt auf! Und das darf nicht 
passieren.

von Hannes Lux (Gast)


Lesenswert?

> 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.

...

von Fabian S. (jacky2k)


Lesenswert?

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?

von Hannes Lux (Gast)


Lesenswert?

> und um es zu resetten muss man es wieder setzen?

Ja, so ist es...

Mecker' nicht herum, lies und verstehe stattdessen das verdammte 
Dartenblatt!!!

...

von Fabian S. (jacky2k)


Lesenswert?

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.

von Ahem (Gast)


Lesenswert?

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.

von Hannes Lux (Gast)


Lesenswert?

Danke...

...

von Fabian S. (jacky2k)


Lesenswert?

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.

von Hannes Lux (Gast)


Lesenswert?

Naja, das erinnert mich an:
http://www.youtube.com/watch?v=S2oJFrDf8P0
;-)

...

von Ahem (Gast)


Lesenswert?

Seufz.

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
Noch kein Account? Hier anmelden.