Forum: Mikrocontroller und Digitale Elektronik ATTINY44 ADC Problem


von Klaus W. (rasuth)


Lesenswert?

Hallo zusammen,

ich habe ein Problem bezüglich eines nicht funktionierenden ADC des 
ATTINY44 und bislang keine Lösung und keine Info dazu gefunden. So hoffe 
ich, dass ich hier vielleicht einen Tipp bekommen kann der mich weiter 
bringt.

Folgende Schaltung:
Ich habe eine Brücken-Schaltung und möchte die Brückenspannung mittel 
dem  ADC  (PA2(pos) und PA3(neg)) messen nach:

(Upos-Uneg)/Vref*1024

Die Differenzspannung liegt zwischen 0...500mV. Sollte ja kein Problem 
sein.

Ich habe ein Assemblerprogramm geschrieben, mit dem ich die gemessene 
Differenzspannung mit einem digitalen Schwellwert vergleiche und 
entsprechend dem Ergebnis (größer/kleiner als Schwellwert) eine LED als 
Testindikator ein oder ausschalte.

Das Problem ist, dass der ADC nichts macht. Ich bin im Momment sehr 
ratlos. Vielleicht könnte jemand über den Code schauen wo hier der 
Fehler liegt, ich habe keinen gefunden - ADC sollte dem Datenblatt 
entsprechend definiert sein.
Das wäre echt nett. Schaltung wollte ich anhängen ging aber nicht (es 
lässt sich keine Datei auswählen!).

Vielen Dank
Rasuth




;fclock=8MHz
;defination ADC

;define PA2 and PA3 as inputs;
  ser temp
  cbr temp, (1<<DDA3)|(1<<DDA2); set as input
  out  DDRA, temp;

;disable digital Portpin-driver
  clr    temp
  sbr    temp,  (1<<ADC2D)|(1<<ADC3D)
  out    DIDR0,  temp

;disable analog comparator
  clr    temp
  ldi    temp, (1<<ACD)
  out    ACSR, temp

;reference voltage=Vref-->REFS1=1;
;diffunipolar-mode PA2=pos/PA3=neg-->MUX4=1
  ;ADC = (PA2-PA3)/Vref*1024
  clr    temp
  ldi    temp, (1<<REFS1)|(1<<MUX4)
  out    ADMUX, temp

;enable the ADC ADEN=1; set prescaler=32 (250KHz) ADPS2=1, ADPS0=1
  clr    temp
  ldi    temp, (1<<ADEN)|(1<<ADPS2)|(1<<ADPS0)
  out    ADCSRA, temp

;ADLAR=0
  clr    temp
  out    ADCSRB, temp


test1:
convert_start:
  in    temp,  ADCSRA; (setting prescale, Vref)
  ori    temp,  1<<ADSC; starts single conversion
  out    ADCSRA,  temp

convert_wait:
  in    temp, ADCSRA
  sbrs  temp, ADIF
  rjmp  convert_wait; ADIF is set after updating ADC register


;test ADC result through led on PORTB0
;if ADC Result > LED off
;if ADC RESULT < LED on
  in    temp, ADCL
  cpi    temp, 100
  brge  test2
  cbi    PORTB, PINB0; ADCL < zahl
  rjmp  test1

test2:
  sbi    PORTB, PINB0 ; ADCL > zahl
  rjmp  test1

von H.Joachim S. (crazyhorse)


Lesenswert?

Wenn du nur 8bit nutzen willst, muss ADLAR gesetzt sein.

von S. Landolt (Gast)


Lesenswert?

PB0 wird nicht als Ausgang gesetzt.

von S. Landolt (Gast)


Lesenswert?

> Wenn du nur 8bit nutzen willst, muss ADLAR gesetzt sein.

Zusätzlich
1
  in  temp,ADCH
statt ADCL.

von Richtig Steller (Gast)


Lesenswert?

Klaus W. schrieb:
> ich habe ein Problem bezüglich eines nicht funktionierenden ADC

Nein, der ADC funktioniert. Du hast ein Problem mit demjenigen
der vor dem Bildschirm und der Tastatur sitzt.

von Rasuth (Gast)


Lesenswert?

S. Landolt schrieb:
>> Wenn du nur 8bit nutzen willst, muss ADLAR gesetzt sein.
>
> Zusätzlich  in  temp,ADCH
> statt ADCL.

ich habe es mit ADLAR=1 und mit ADCH lesen probiert. Das wars. Jetzt 
funktioniert es wie es sollte.

Vielen Dank für den TIP   !!!!

Es ist immer gut wenn man kompetente, freundliche und hilfsbereite Leute 
fragen kann....

von Karl M. (Gast)


Lesenswert?

Hallo ,

noch eine kleine programmiertechnische Anmerkung:
1
clr    temp
2
ldi    temp, <value>
Die erste Anweisung
1
clr temp => eor temp,temp
 ist unnötig und hat keine Bedeutung für die weitere Programmausführung!

von Klaus W. (rasuth)


Lesenswert?

Karl M. schrieb:
> Hallo ,
>
> noch eine kleine programmiertechnische Anmerkung:clr    temp
> ldi    temp, <value>
> Die erste Anweisungclr temp => eor temp,temp ist unnötig und hat keine
> Bedeutung für die weitere Programmausführung!




bei zuweisung eines wertes hast du recht

ldi temp, 0x04   ist korrekt

Definition von temp darf aber nicht weggelassen werden, wenn es sich um 
eine
Bit Operation, bei der einzelne Bits gesetzt werden,  handelt.
Temp muss zuvor definiert sein (wie in meinem Fall mit 0)

clr temp
ldi temp (1<<x) (setzt in dem register temp eine 1 an der Stelle x)

von Karl M. (Gast)


Lesenswert?

Naja,

ich würde es nicht mit einem ORI, genau SBR entspricht diesem Mnemonic, 
wie bei Dir lösen!
Beispiel:
1
clr temp
2
sbr temp,(1<<ADC2D)|(1<<ADC3D)

Kürzer uns schneller ist deshalb:
1
ldi temp,(1<<ADC2D)|(1<<ADC3D)

Korrekt sind beide Varianten.

von leo (Gast)


Lesenswert?

Klaus W. schrieb:
> Bit Operation, bei der einzelne Bits gesetzt werden,  handelt.
> Temp muss zuvor definiert sein (wie in meinem Fall mit 0)
>
> clr temp
> ldi temp (1<<x) (setzt in dem register temp eine 1 an der Stelle x)

Nope.

Mit "ldi" ("load immediate") setzt du einen direkten Wert, wie auch 
immer dieser ausschaut. 0x4 oder 1<<2 ist vollkommen egal.

Du verwechselst das mit "ori" ("Logical OR with Immediate"), wo ein 
definierter Vorzustand gebraucht wird.

Das "clr tmp" kann daher generell entfallen, wenn dann ein "ldi tmp" 
folgt.

leo

von Rasuth (Gast)


Lesenswert?

Karl M. schrieb:
> clr temp
> sbr temp,(1<<ADC2D)|(1<<ADC3D)
>
> Kürzer und schneller ist deshalb:

ldi temp,(1<<ADC2D)|(1<<ADC3D)


>> Das ist richtig. Danke für den Hinweis.

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.