Forum: Mikrocontroller und Digitale Elektronik ADC-Wandlung in AVR-Assembler


von didi (Gast)


Lesenswert?

Hallo !!!

Folgendes Problem:
Mir ist nicht klar warum ich nach einer Muxumschaltung ,14 Takte mehr
brauche bis der gewandelte Wert korrekt ist.
Das mir unbegreifliche ist , dass ich sogar auf das ADIF warte und 
danach
noch 14 nop's einbauen muß !!!!
Das Programm läuft auf einen ATMEGA8 bei 16Mhz, nicht im 
free-runnig-mode.
Die Routine wirtd von einem exterenen Interrupt ausgelöst und soll 
schnellstmöglich 2 Kanäle abtasten.Der erste würde die 14 zusätzlichen 
nop's nicht brauchen. Der Mux wird genau einen Takt nach dem Start des
ADC umgeschaltet.
Bitte um Klärung des Problems, es kann doch nicht sein das ich nach 
conversion complete  noch 14 Takte warten muß oder habe ich einen Fehler 
gemacht ???

Hier die Interruptroutine:

ADC_HANDLER:
    sbrc Flags, GRAD_M    ; Winkelmessung Aktiv ?
  rcall GRAD_MESSUNG

  sbrs Flags, ADC_RUN    ; ADC Aktiv ?
    reti        ; Nein -> Routine Abbrechen

    in REGSAVE, SREG    ; Einlesen des SREG
  ldi i, 225              ; MUX auf Kanal 2
ADW:
    sbi ADCSRA, ADSC        ; Start ADC
  nop                     ; zwingend für Mux-Umschaltung
  out ADMUX, i            ; MUX auf Kanal 2 oder 1

  sbis ADCSRA, ADIF       ; Warte bis AD Wandlung fertig ist
    rjmp PC-1
  nop
  nop
  nop
  nop
  nop
  nop
  nop
  nop
  nop
  nop
  nop
  nop
  nop
  nop


  in tempi, ADCH       ; ADC einlesen
  ST X+,tempi         ; DATEN SPEICHERN und Zeiger um 1 erhöhen

  ldi i, 224              ; für Kanal 1 (vorwahl)
  sbic ADMUX, MUX0        ; Kanal 2 schon gewandelt > fertig
    rjmp ADW                ; Kanal 2 wandeln


  ldi tempi, high(adr_DATEN_SPEICHER+ANZAHL_DATENPUNKTE)
  cpi XL, low(adr_DATEN_SPEICHER+ANZAHL_DATENPUNKTE)
  cpc XH, tempi
  brlo ADC_HANDLER_ENDE  ; Ende vom Speicher ? -> Aufzeichnung beenden

  clr Flags
    cbi PORTD,5
ADC_HANDLER_ENDE:
  out  SREG, REGSAVE    ; Wiederherstellen von SREG
reti

von didi (Gast)


Lesenswert?

War zu schnell:

Wollte mich schon mal für die kommende Hilfe bedanken.

LG Dieter

von spess53 (Gast)


Lesenswert?

Hi

>Mir ist nicht klar warum ich nach einer Muxumschaltung ,14 Takte mehr
>brauche bis der gewandelte Wert korrekt ist.
>Das mir unbegreifliche ist , dass ich sogar auf das ADIF warte und
>danach noch 14 nop's einbauen muß !!!!

Nur zur Vorabklärung: Wie kommst du darauf?

MfG Spess

von Nachteule (Gast)


Lesenswert?

Aus dem Manual zum ATmega8, Seite 200:
The user is thus advised not to write new channel or reference selection 
values to ADMUX until one ADC clock cycle after ADSC is written.

Also dürfte sich Dein Problem in Luft auflösen, wenn Du erst den Kanal 
einstellst und danach die Wandlung startest.

von didi (Gast)


Lesenswert?

spess53 schrieb:
> Nur zur Vorabklärung: Wie kommst du darauf?

Indem ich einmal Masse und einmal 5V anlege und am Kanal 1 bekomme ich 
dann
den Wert 0 bzw. 255 (ohne die nop's),was richtig ist.Jedoch am 2. Kanal 
bekomme ich Werte die größer 0 bzw. kleiner 255 sind, erst wenn ich die 
14 nop's drinnen habe passt es.

LG Dieter

von didi (Gast)


Lesenswert?

Nachteule schrieb:
> Aus dem Manual zum ATmega8, Seite 200:
> The user is thus advised not to write new channel or reference selection
> values to ADMUX until one ADC clock cycle after ADSC is written.
>
> Also dürfte sich Dein Problem in Luft auflösen, wenn Du erst den Kanal
> einstellst und danach die Wandlung startest.

Wenn Du meinen Code anschaust wirst Du feststellen,das ich das mache:


    sbi ADCSRA, ADSC        ; Start ADC
  nop                     ; zwingend für Mux-Umschaltung
  out ADMUX, i            ; MUX auf Kanal 2 oder 1


LG Dieter

von Rolf Magnus (Gast)


Lesenswert?

>> Also dürfte sich Dein Problem in Luft auflösen, wenn Du erst den Kanal
>> einstellst und danach die Wandlung startest.
>
> Wenn Du meinen Code anschaust wirst Du feststellen,das ich das mache:

1. Wandlung starten:

>    sbi ADCSRA, ADSC        ; Start ADC

2. Kanal umschalten:

>  nop                     ; zwingend für Mux-Umschaltung
>   out ADMUX, i            ; MUX auf Kanal 2 oder 1

Also ich habe meine Probleme, zu sehen, wie du da erst den Kanal 
einstellst und danach die Wandlung startest.

von Franz (Gast)


Lesenswert?

>> "...one ADC clock cycle after..."

ADC clock ist nicht unbedingt gleich CPU clock! (ist abhängig von der 
Prescaler Einstellung)

von didi (Gast)


Lesenswert?

Rolf Magnus schrieb:
> Also ich habe meine Probleme, zu sehen, wie du da erst den Kanal
> einstellst und danach die Wandlung startest.

Der 1. Kanal wird schon nach dem Reset eingestellt und schon mal eine 
Wandlung durchgeführt, da die erste Wandlung laut Datenblatt länger 
dauert.....der prescaler ist auf 0.
Nach Aufruf der Routine wird der voreingestellte Kanal 1 gestartet und 
danach
auf Kanal 2 umgestellt.Ohne den nop funktioniert es nicht und mit 2 
nop's auch nicht, das habe ich getestet.Also die Umschaltung 
funktioniert ...
nur eben wie gesagt brauche ich dann noch die 14 nop's bis der Wert 
stimmt.

Danke erstmals LG Dieter

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Wenn Referenzspannungsquellen umgeschaltet werden, sollte man noch dazu 
den ADC ausschalten und wiedereinschalten, um eine lange Wandlung (25 
ADC-Clocks) durchzuführen, nur so kann das Ergebnis korrekt sein. 
Ansonsten gilt _immer_:

1. Wenn ADSC=0 oder ADIF=1, Ergebnisregister auslesen
2. ADMUX umschalten
3. Neue Wandlung auslösen

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

didi schrieb:
> der prescaler ist auf 0.

Kannste vergessen. Der ADC darf nur innerhalb 50...250kHz Samplerate 
laufen, wenn Du 10Bit Auflösung haben willst. Bei 8Bit kannst Du bis 
maximal 1MHz gehen. Stelle den ADC-Prescaler also auf 64.

von didi (Gast)


Lesenswert?

Travel Rec. schrieb:
> Kannste vergessen. Der ADC darf nur innerhalb 50...250kHz Samplerate
> laufen, wenn Du 10Bit Auflösung haben willst. Bei 8Bit kannst Du bis
> maximal 1MHz gehen. Stelle den ADC-Prescaler also auf 64.

Ok ,ich brauche nur 8-Bit,müßte somit mit Teiler 16 gehen oder ?
Werde ich mal testen,kann es aber erst am Dienstag probieren.

Aber eines ist mir immer noch nicht klar, wieso klappt es beim Kanal 1 
und
komisch finde ich das ich ,das ich ADIF abwarte und danach noch 14 Takte 
warten muß bis das Ergebnis stimmt.Wieso kommt dann ADIF schon nach 
13-Takte ?

Danke nochmals LG Dieter

von spess53 (Gast)


Lesenswert?

Hi

>komisch finde ich das ich ,das ich ADIF abwarte und danach noch 14 Takte
>warten muß bis das Ergebnis stimmt.Wieso kommt dann ADIF schon nach
>13-Takte ?

Dazu müsste man zumindest die Initialisierung des ADC und den Takt des 
Controllers kennen.

MfG Spess

von didi (Gast)


Lesenswert?

Hier:

ldi temp, 
(1<<REFS1)|(1<<REFS0)|(1<<ADLAR)|(0<<MUX3)|(0<<MUX2)|(0<<MUX1)|(0<<MUX0)
out ADMUX, temp

ldi temp, (1<<ADEN)|(1<<ADIE)  ;Teiler: 0
out ADCSRA, temp


LG Dieter

von spess53 (Gast)


Lesenswert?

Hi

Du aktivierst den ADC-Complete-Interrupt. Gibt es da auch eine 
entsprechende Interrupt-Routine?

MfG Spess

von didi (Gast)


Lesenswert?

Nein,die habe ich nicht ,im Simulator springt er die zwar an aber dort 
habe ich reti und somit gehts wieder zurück.
Ich wollte es aber eigentlich mit ADSC realisieren ,dieser ist solange 
gesetzt bis die AD-Wandlung fertig ist,hat aber auch nicht funktioniert 
bzw.
komme ich auf das selbe Ergebnis als wenn ich es mit ADIF mache.

LG Dieter

von spess53 (Gast)


Lesenswert?

Hi

Du bist dir aber bewusst, das du ADIF wieder manuell zurücksetzen must. 
Daher brauchst du auch die vielen 'nop's

'ADIF is cleared by hardware when executing the corresponding interrupt 
handling vector. Alternatively, ADIF is cleared by writing a logical one 
to the flag.'

Deine ADIF-Abfrage ist sinnlos, weil dein Flag schon von der vorherigen 
Wandlung noch gesetzt ist.

MfG Spess

von didi (Gast)


Lesenswert?

Hi !!

Könnte auch sein ,im Simulator wird es jedenfalls zurückgesetzt , aber 
wie gesagt das mag nichts heißen,der Sim. ist sicherlich nicht 
fehlerfrei.
Danke jedenfalls das Du mich darauf aufmerksam gemacht hast, werde ich 
testen.

LG Dieter

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.