mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ADC Umwandlung mit ATmega8


Autor: Jens S. (derfixej)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo,

ich will mit dem atmega8 2 analoge signale kontinuierlich umwandeln und
das ergebnis im sram für weitere verarbeitung zur verfügung stellen.
mache sowas zum ersten mal und scheitere schon an der initialisierung.
mit einem kanal ist es klar.

mit ADPS vorteiler einstellen
mit ADEN generell einschalten
in ADMUX kanal wählen
mit ADFR free run wählen
mit ADSC umwandlung starten

aber wie soll ich das machen wenn ich zwei eingänge kontinuierlich
abfragen will?

gruß jens

Autor: Jan M. (mueschel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gleichzeitig beide Kanäle abzufragen ist nicht möglich.
Die einfachste Lösung ist, bei jedem Auslesen des ADC-Wertes ADMUX neu
zu schreiben. So bekommst du immer abwechselnd die Werte von beiden
Eingängen.

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Jens:
Der AVR hat nur einen ADC mit einem vorgeschalten 8-kanal-Multiplexer.
So ist es nicht mgöich, mehrere Kanäle gleichzeitig zu messen.
Dafür bräuchte man dann externe Lösungen...

Autor: Jens S. (derfixej)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
na gut, das konnte ich mir denken, aber wie soll ich es realisieren, die
eingänge hintereinander fortlaufend abzufragen, wenn ich doch immer nur
einen eingang im admux setzen kann, soll ich die allg. einstellungen
enable, vorteiler, free run... separat initialisieren und dann jeweils
vor der abfrage nur admux auf den nächsten eingang umschreiben? mir
fehlt etwas die vorstellungskraft.

gruß jens

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Seite 197 im Datenblatt "Changing Channel or Reference Selection"
Solange eine Messung durchgeführt wird, kann man zwar den Kanal etc.
wechseln, die Änderung wird aber erst aktiv, sobald die Messung beendet
ist.
Du wartest das Ende der Messung ab, und startest eine neue mit
geänderten Einstellungen, nachdem du die ADC-Werte gespeichert hast.
Das kannst du entweder als konstante Abfrage des ADIF-Bit oder in der
Interrupt-Service-Soutine machen.
Beim Auftreten des Interrupts wird im free-running-mode IMHO sofort die
neue Messung gestartet. Sprich, wenn man die Einstellungen in der ISR
ändert, dann wird noch eine Messung mit den alten Einstellungen
durchgeführt. Das ist auch irgendwo im Datenblatt beschrieben...

Autor: Jens S. (derfixej)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
kann ich das auch ohne interrupt lösen? habe das mit den interrupts noch
nicht so geschnallt. wollte über polling abfragen, aber dann nützt mir
ja das adif bit nichts, oder?

gruß jens

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das einfachste ist eine Schleife:

{
  ADC-Eingang setzen
  Messung starten
  Ende der Messung abwarten
  Werte sichern
  Parameter ändern (z.B. Feldindex und dergl.)
} wiederholen

Autor: Jens S. (derfixej)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also wenn ich das richtig verstanden habe so in etwa:

main:    ldi     r16, lo8(RAMEND)
         out     SPL, r16
         ldi     r16, hi8(RAMEND)
         out     SPH, r16

;Initialisierung ADC
    ldi   r17, 0b10000...  ;ADC enable, vorteiler
    out   ADCSRA, r17
;---------------------------------------------------------------------ma 
inloop:
wdr
          rjmp loop
          rjmp save
          rjmp mainloop
;---------------------------------------------------------------------
;ersten eingang umwandeln und sichern

loop:   ldi  r16, 0     ;auswahl chanel 0
  out  ADMUX, r16                               sbi  ADCSRA, ADSC 
;wandlung
starten
warte1:  sbis   ADCSRA, ADIF  ;abfrage ob umwandlung schon beendet
  rjmp   warte1
  in  r18, ADCL  ;die unteren 8bits in r18 speichern
  in  r19, ADCH  ;die oberen 2bits in r19 speichern

;zweiten eingang umwandeln und sichern

  ldi  r16, 1    ;auswahl chanel 1
  out  ADMUX, r16
  sbi  ADCSRA, ADSC  ;wandlung starten
warte2:  sbis  ADCSRA, ADIF  ;abfrage ob umwandlung schon beendet  rjmp
warte2
  in      r20, ADCL       ;die unteren 8bits in r20 speichern
  in  r21, ADCH  ;die oberen 2bits in r21 speichern
        ret

;gesicherte werte in sram speichern
save:
  ...
  ret

wenn das so stimmt, wie bekomme ich dann die r18-r21 in den sram?
geht das überhaupt so einfach?

gruß jens

Autor: Jens S. (derfixej)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also wenn ich das richtig verstanden habe so in etwa:

main:    ldi     r16, lo8(RAMEND)
         out     SPL, r16
         ldi     r16, hi8(RAMEND)
         out     SPH, r16
         
;Initialisierung ADC           
    ldi    r17, 0b10000...        ;ADC enable, vorteiler
    out    ADCSRA, r17
      
            
;---------------------------------------------------------------------------
mainloop: wdr
          rjmp loop
          rjmp save
          rjmp mainloop
;---------------------------------------------------------------------------
;ersten eingang umwandeln und sichern
loop:     ldi    r16, 0           ;auswahl chanel 0
      out    ADMUX, r16
      sbi    ADCSRA, ADSC       ;wandlung starten
warte1:    sbis   ADCSRA, ADIF      ;abfrage ob umwandlung schon beendet ist
ADIF=1 
      rjmp   warte1
      in    r18, ADCL        ;die unteren 8bits in r18 speichern
      in    r19, ADCH         ;die oberen 2bits in r19 speichern
      
;zweiten eingang umwandeln und sichern      
      ldi    r16, 1          ;auswahl chanel 1
      out    ADMUX, r16
      sbi    ADCSRA, ADSC       ;wandlung starten
warte2:    sbis  ADCSRA, ADIF      ;abfrage ob umwandlung schon beendet ist
ADIF=1  
      in    r20, ADCL        ;die unteren 8bits in r20 speichern
      in    r21, ADCH        ;die oberen 2bits in r21 speichern
      ret
;gesicherte werte in sram speichern
save:    
      ...
      ret        

wenn das so stimmt, wie bekomme ich dann die r18-r21 in den sram?
geht das überhaupt so einfach?

gruß jens

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Jens S. (derfixej)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich denke das sollte soweit hinkommen, aber warum zeigt mir der compiler
in den zeilen mit dem adsc und adif bit dies an:


constant value required


gruß jens

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> aber warum zeigt mir der compiler
> in den zeilen mit dem adsc und adif bit dies an:
>
>
> constant value required

Ich denke mal, dass du hier zwei Programmiersprachen vermischt:

> warte2:    sbis  ADCSRA, ADIF      ;abfrage ob umwandlung schon
> ;beendet
> ;ist
> ADIF=1
>       in    r20, ADCL        ;die unteren 8bits in r20 speichern
>       in    r21, ADCH        ;die oberen 2bits in r21 speichern
>       ret

ADIF=1 passt nicht zu ASM-Syntax.
Das mag in C oder BASIC syntaktisch richtig sein, in ASM versuchst du
damit, den Wert des Bezeichners 'adif' (das ist die Bitnummer, also
eine Konstante, die in der Include-Datei festgeschrieben ist) zu
verändern. Und das darf der Assembler (der kein Compiler ist!) nicht
zulassen...

...

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achja, noch was vergessen...

Ich interpretiere deinen Code so:
- Du stellest in ADMUX die Messquelle (und Referenzquelle) ein,
- du startest die Messung (Wandlung)
- du wartest, bis das adif-Bit gesetzt ist
- du liest die Werte aus...

Also du schaltest dir Messquelle immer erst dann um, wenn du eigentlich
schon gern das Ergebnis hättest.

Ich würde das so machen:
- Ausleseroutine in einen Timer-Interrupt oder den ADC-Complete-
  Interrupt legen. Darin in regelmäßigen Zeitabständen:
- Wert einlesen und sichern
- Messquelle für nächste Messung umschalten
- Messung starten
- fertig, andere Dinge tun, wie Tastenentprellung, Zeit hochzählen,
  LCD-Ausgabe usw.
- zurück zur Mainloop.

Das spart irgendwie Rechenzeit, da nicht auf das Ergebnis der Wandlung
gewartet werden muss, sondern die Wandlung abläuft, während der AVR
noch andere Dinge tut.

Wenn du mit Sleep arbeitest, kannst du sogar die Wandlung automatisch
starten lassen, indem du das Programm nach getaner Arbeit einfach in
den Sleep-Mode schickst. Beim Mega8 geht das glaube sogar im Idle-Mode.
Schau mal im Datenblatt unter SLEEP nach.

...

Autor: Jens S. (derfixej)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo,
danke für schnelle antwort. das adif=1 gehört nur zum kommentar. da hat
was nicht so hingehauen beim reinkopieren. sollte einfach nur heißen,
dass die umwandlung beendet ist, wenn das adif bit gesetzt ist. (wie
krieg ich das denn beim nächsten mal besser hin? (code) (/code) hat
nicht geklappt)
davon kann die fehlermeldung also nicht kommen. und das mit den
interrupt klingt einleuchtend, ich hab bloß keinen schimmer wie das
funzt. was in dieser interruptroutine drinstehen muss, ist mir klar,
aber nicht wie ich diese einbinde. macht man das über die
interruptvectoren? wie gesagt das mit den interrupts hab ich noch nicht
so begriffen.

gruß jens

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann schau dir doch einfach mal die Programme (Quelltexte) auf meiner
Seite an: www.hanneslux.de

Am besten das Melodiegenerator-Projekt mit Tiny15, erste Variante, da
ist genau erklärt, wie man ASM-Programme mit Interrupts schreibt.

Auch das Projekt, was ich dir im obigen Link genannt habe, zeigt im
Quelltext recht deutlich, wie das mit den Interrupts geht.

Da ich kein Profi bin, ist das Niveau dieser Programme nicht besonders
hoch (vom mathematischen Anspruch her gesehen), der Code müsste also
nachvollziehbar und verständlich sein.

Aber auch im Datenblatt des Mega8 unter Interrupt-Sources wird erklärt,
wie das gemacht wird. Erwarte aber bitte nicht, dass ich dir das
übersetze, ich habe selbst nie englisch gelernt, ich muss da auch
gelegentlich das Wörterbuch befragen.

In C oder BASIC scheint das mit den Interrupts vielleicht etwas
kryptisch bzw etwas schwerer durchschaubar zu sein, in ASM ist aber
sehr einfach und vor allem sehr transparent.

...

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.