ATMega16 ADC Kanal wechseln?

Gast #2382089
Lesenswert?
• ▲
▼
Hi.

Hab schon gesucht ob es Beiträge gibt die mein Problem lösen, aber ich 
habe nichts gefunden auch wenn viele dasselbe Problem hatten.

Ich will im Betrieb den ADC Kanal wechseln und hab im Datenblatt 
gelesen, man soll das ADEN Bit löschen, dann den Kanal wechseln und dann 
ADEN wieder setzen.
1
  ldi     temp, (0<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0)
2
    out     ADCSRA, temp
3
    ldi     temp, (1<<REFS0) | (0<<REFS1) | (0<<ADLAR) | (0<<MUX0) | (1<<MUX1) | (1<<MUX2) | (0<<MUX3) | (0<<MUX4)
4
    out     ADMUX, temp
5
    ldi     temp, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0)
6
    out     ADCSRA, temp

Ich habe zwei Routinen, also quasi "Kanal1_auslesen" und 
"Kanal2_auslesen". Am Anfang jeder Routine steht der obige Codeblock und 
bei dem einen setze ich (1<<MUX0) und beim anderen lösche ich es mit 
(0<<MUX0).

Die Routinen werden abwechseln aufgerufen. Beim ersten Aufruf von 
Routine1 wird der erste Kanal ausgelesen. Dann wird die zweite Routine 
aufgerufen und Kanal2 wird ausgelesen, dann wieder Routine1 und ab hier 
wird nur noch Kanal2 ausgelesen, statt auch Kanal1. Wo könnte da der 
Fehler liegen?

ADC wird anschließend an den Block oben ganz schlicht über:
1
  sbi ADCSRA, ADSC
2
wait_adc2:
3
    sbic    ADCSRA, ADSC
4
    rjmp    wait_adc2
5

6
  in r23, ADCH
7
  in r22, ADCL

ausgelesen.
#2382095
Lesenswert?
• ▲
▼
Das Geht auch ohne aus- und einschalten.

Siehe Codebeispiel. Dieser Läuft produktiv auf einem Atmega8:

;    ADCs einlesen:
      cbi ADMUX, 1      ;Kanal 0
      cbi ADMUX, 0
      rcall adc_read
      mov adc0, temp1

      sbi ADMUX, 0      ;Kanal 1
      rcall adc_read
      mov temp_innen, temp1

      cbi ADMUX, 0
      sbi ADMUX, 1      ;Kanal 2
      rcall adc_read
      mov temp_aussen, temp1

      rjmp main
;------------------------------------------------------
adc_read:
      ldi temp1, 0b11010101  ;ADC-Single shot starten
      out ADCSR, temp1
      nop

adc_wait:  sbis ADCSR, ADIF    ;ADC-Conversion abwarten
      rjmp adc_wait

      in temp1, ADCH      ; 8-Bit Auflösung
      ret
#2382302
Lesenswert?
• ▲
▼
Nicht nur beim ADC, bei allen 16bit Registern, auch Timer usw. . Beim 
Lesen des  Lowbyte wird gleichzeitig das Highbyte zwischengespeichert, 
damit sich der Wert nicht zwischen Low- und Highbyte lesen nochmal 
ändert, und so falsche Ergebnisse kommen. Beim Schreiben muss man erst 
High schreiben.

Aus dem Datenblatt:
When the low byte of a 16-bit register is read by the CPU, the high byte 
of the 16-bit register is copied into the temporary register in the same 
clock cycle as the low byte is read.

To do a 16-bit write, the high byte must be written before the low byte. 
For a 16-bit read, the low byte must be read before the high byte.

Antwort schreiben

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.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.