mikrocontroller.net

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


Autor: didi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: didi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
War zu schnell:

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

LG Dieter

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Nachteule (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: didi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: didi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Franz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> "...one ADC clock cycle after..."

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

Autor: didi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Knut Ballhause (Firma: TravelRec.) (travelrec) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Knut Ballhause (Firma: TravelRec.) (travelrec) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: didi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: didi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

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

MfG Spess

Autor: didi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: didi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.