Forum: Mikrocontroller und Digitale Elektronik AD-Wandler am ATTiny44 bringt scheinbar nur einmal einen korrekten Wert


von Christof Rieger (Gast)


Lesenswert?

Ich steh hier voll auf dem Schlauch. Im Simulator läuft das Programm, am 
Device scheint der ATTiny44 nur einmal den Wert korrekt zu messen.

Ich möchte über einen Spannungsteiler die Spannung an einem Kondensator 
messen. Als Messeingang verwende ich dem PA1.
PA3 Wechselt auf High wenn meine Schwellspannung erreicht wird.
Das klappt aber nicht.
Resete ich den ATTiny44 wenn die Schwellspannung höher ist, dann wird 
PA3 High.
Resete ich den ATTiny44 wenn die Schwellspannung niedriger ist, dann ist 
der PA3 Low. Lade ich den Kondensator bleibt PA3 Low.
Der AD-Interrupt scheint aber zu funktionieren, da nur dort der 
Watchdogtimerreset erfolgt und ein WD-Reset scheinbar nicht ausgelöst 
wird.
Kennt jemand das Problem ?

;* Target  : ATTiny44
;**** includes ****
;Interner Takt 8MHz und Takteiler auf 8 somit effektiev 1MHz



.DEF V_Cpower_akt  =r2 ;Aktuelle Spannung am GoldCap in cV
.DEF V_MicPower_akt =r3  ;Aktuelle Spannung am µ-Controller
.DEF V_Cpower_alt  =r4 ;Alte Spannung am GoldCap in cV
.DEF V_MicPower_alt =r5  ;Alte Spannung am µ-Controller

.DEF Flags      =r23;Flags |C_V_Busy|Mic_V_Busy|0|0|0|0|0|0|

.EQU C_V_Busy    =7
.EQU Mic_V_Busy    =6

.include "tn44def.inc"

.ESEG
.ORG 0x00
datx:
  .DB 1, 2, 3, 4, 5, 6, 7, 8, 9

.CSEG
.ORG 0x00
  rjmp  RESET    ; Reset Handle
  reti        ; External Interrupt Request 0
  reti        ; Pin Change Interrupt Request 0
  reti        ; Pin Change Interrupt Request 1
  reti        ; Watchdog Timer Overflow
  reti        ; Timer/Counter1 Capture Event
  reti        ; Timer/Counter1 Compare Match A
  reti        ; Timer/Counter1 Compare Match B
  reti        ; Timer/Counter1 Overflow
  reti        ; Timer/Counter0 Compare Match A
  reti        ; Timer/Counter0 Compare Match B
  reti        ; Timer/Counter0 Overflow
  reti        ; Analog Comparator
  rjmp  ADC_Ready  ; ADC Conversion Complete
  reti        ; EEPROM Ready
  reti        ; USI Start Condition
  reti        ; USI Overflow

.ORG 0x11
RESET:
  ldi  r16,high(RAMEND)
  out  SPH,r16      ; Stack auf höchste RAM-Adresse
  ldi  r16,low(RAMEND)
  out  SPL,r16      ; Stack auf höchste RAM-Adresse
;Watchdog
  ldi r16,0b00001011
  out WDTCSR,r16
;Port ini
  ldi r16,0b00000000
  out PORTA,r16
  ldi r16,0b00111101
  out DDRA,r16
  ldi r16,0b00000000
  out PORTB,r16
  ldi r16,0b00000000
  out DDRB,r16
;AD-Wandler ini
  ;AD-Wandler ein, Inerrupt ein, Takt 125kHz
  ldi r16,1<<ADEN|0<<ADSC|0<<ADATE|0<<ADIF|1<<ADIE|3
  out ADCSRA,r16
  ldi r16,0<<BIN|0<<ACME|0<<ADLAR|0
  out ADCSRB,r16
  ;Nicht benötigte AD mit 1 ausschalten.
  ldi r16,0b11111101
  out DIDR0,r16
  ;Spannung am Kondensator messen Ref 1,1V 1 Digit =0,01 Volt
  ldi r16,1<<REFS1|1
  out ADMUX,r16
  sei

  sbi PORTA,PA2

  sbi ADCSRA,ADSC
Spannungen_C_messen:
  sbr Flags,1<<C_V_Busy
L1_C_V_Busy:
  sbrc Flags,C_V_Busy
  rjmp L1_C_V_Busy
  sbi ADCSRA,ADSC
  mov r16,V_Cpower_akt
  cpi r16,60
  brlo Spannungen_C_messen ;warten bis mind. 0,6V am C

  sbi PORTA,PA3

Spannungen_mC_messen:
  sbr Flags,1<<C_V_Busy|1<<Mic_V_Busy
L1_Mic_V_Busy:
  sbrc Flags,Mic_V_Busy
  rjmp L1_Mic_V_Busy
  sbi ADCSRA,ADSC
  mov r16,V_MicPower_akt
  cpi r16,0b10011010
  brlo Spannungen_mC_messen ;prüfen ob Mindestspannung am mC 
überschritten wurde

  sbi PORTA,PA4

mC_low_check:
  sbr Flags,1<<C_V_Busy|1<<Mic_V_Busy
L2_Mic_V_Busy:
  sbrc Flags,Mic_V_Busy
  rjmp L2_Mic_V_Busy
  sbi ADCSRA,ADSC
  mov r16,V_MicPower_akt
  cpi r16,0b10011000
  brsh mC_low_check  ;prüfen ob Mindestspannung unterschritten wurde.

  sbi PORTA,PA5

  mov r16,V_Cpower_akt
  cpi r16,60
  brlo Spannungen_C_messen ;prüfen ob mind. 0,6V am C

  sbi PORTA,PA0

  mov r17,V_Cpower_akt
  subi r17,30

I_C_Tr_Check:
  sbr Flags,1<<C_V_Busy
L3_C_V_Busy:
  sbrc Flags,C_V_Busy
  rjmp L3_C_V_Busy
  sbi ADCSRA,ADSC
  cp V_Cpower_akt,r17
  brsh I_C_Tr_Check ;warten bis am C, U um 0,3V gesunken.

  cbi PORTA,PA0

mC_fall_check:
  sbr Flags,1<<C_V_Busy|1<<Mic_V_Busy
L3_Mic_V_Busy:
  sbrc Flags,Mic_V_Busy
  rjmp L3_Mic_V_Busy
  sbi ADCSRA,ADSC
  cp V_MicPower_akt,V_MicPower_alt
  brsh mC_fall_check ;warte bis am mC U fällt.
  rjmp mC_low_check


ADC_Ready:
  wdr
  sbrs Flags,C_V_Busy  ;wenn C_V_Busy gesetzt dann ist das Ergebnis die 
Spannung am C
  rjmp ADC_Ready_MicC
  cbr Flags,1<<C_V_Busy
  mov V_Cpower_alt,V_Cpower_akt
  in r15,ADCH
  in V_Cpower_akt,ADCL
  ldi r22,0<<REFS1|1  ;Vorbereitung zu Mic_V Messung
  out ADMUX,r22
  sbrc Flags,Mic_V_Busy
  sbi ADCSRA,ADSC
  lsr r15
  ror V_Cpower_akt
  lsr r15
  ror V_Cpower_akt
  ldi r22,1<<REFS1|1  ;Vorbereitung zu Mic_V Messung rückgängig ?
  sbrs Flags,Mic_V_Busy
  out ADMUX,r22
  reti

ADC_Ready_MicC:
  sbrs Flags,Mic_V_Busy
  rjmp ADC_Ready_Exit
  sbi ADMUX,REFS1
  mov V_MicPower_alt,V_MicPower_akt
  clr V_MicPower_akt
  in r22,ADCH
  cpi r22,0
  brne ADC_Ready_Exit
  in r15,ADCL
  mov r22,V_Cpower_akt
  sub r22,r15
  brlo ADC_Ready_Exit ;Spannung < 4,4 Volt
  inc V_MicPower_akt
  lsl r22        ;Rest r22 maximal 51
  lsl r22

  ldi r21,2
  neg r15
DIVLOOP:
  add r22,r15
  rol r21
  sbrs r21,0
  sub r22,r15
  lsl r22
  sbrs r21,7
  rjmp DIVLOOP

  mov V_MicPower_akt,r21

ADC_Ready_Exit:
  cbr Flags,1<<C_V_Busy|1<<Mic_V_Busy
  reti

von Johannes M. (johnny-m)


Lesenswert?

Beim Auslesen des ADC-Datenregisters muss unbedingt zuerst ADCL 
gelesen werden und dann ADCH! Der ADC kann nach einem Lesezugriff auf 
ADCL erst dann wieder einen neuen Wert in die beiden Register schreiben, 
wenn ADCH gelesen wurde. Wenn ADCL nach ADCH gelesen wird, dann werden 
die Register blockiert.

von Jochen M. (taschenbuch)


Lesenswert?

>>Wenn ADCL nach ADCH gelesen wird, dann werden
>>die Register blockiert.

Ganz genau richtig!
Und das ist auch keine Schikane, sondern hat seinen guten Grund.
Nur so ist sichergestellt, dass Du BEIDE Register ungestört auslesen 
kannst und nicht (z.b. bei free-running-mode) ein neuer Wert dazwischen 
funkt.

Jochen Müller

von Christof Rieger (Gast)


Lesenswert?

Tausend Dank,
klar lesen von 16 Bit-Werten beim AVR. Ich Trottel, voll in die Falle 
getabt.

Ich Danke euch herzlich !!!!!!!!!!!!!!!!!!!!!!!!!!!

von Christof Rieger (Gast)


Lesenswert?

Ich werd verückt !
Eure Erklärung past genau auf das Fehler Bild, aber das Problem ist 
immer noch das Gleiche. Ich habe die Interruptroutine nun so geändert:
1
ADC_Ready:
2
  wdr
3
  sbrs Flags,C_V_Busy  ;wenn C_V_Busy gesetzt dann ist das Ergebnis die Spannung am C
4
  rjmp ADC_Ready_MicC
5
  cbr Flags,1<<C_V_Busy
6
  mov V_Cpower_alt,V_Cpower_akt
7
in V_Cpower_akt,ADCL
8
in r15,ADCH
9
  ldi r22,0<<REFS1|1  ;Vorbereitung zu Mic_V Messung
10
  out ADMUX,r22
11
  sbrc Flags,Mic_V_Busy
12
  sbi ADCSRA,ADSC
13
  lsr r15
14
  ror V_Cpower_akt
15
  lsr r15
16
  ror V_Cpower_akt
17
  ldi r22,1<<REFS1|1  ;Vorbereitung zu Mic_V Messung rückgängig ?
18
  sbrs Flags,Mic_V_Busy
19
  out ADMUX,r22
20
  reti
21
22
ADC_Ready_MicC:
23
  sbrs Flags,Mic_V_Busy
24
  rjmp ADC_Ready_Exit
25
  sbi ADMUX,REFS1
26
  mov V_MicPower_alt,V_MicPower_akt
27
  clr V_MicPower_akt
28
in r15,ADCL
29
in r22,ADCH
30
  cpi r22,0
31
  brne ADC_Ready_Exit
32
  mov r22,V_Cpower_akt
33
  sub r22,r15
34
  brlo ADC_Ready_Exit ;Spannung < 4,4 Volt
35
  inc V_MicPower_akt
36
  lsl r22        ;Rest r22 maximal 51
37
  lsl r22
38
39
  ldi r21,2
40
  neg r15  
41
DIVLOOP:
42
  add r22,r15
43
  rol r21
44
  sbrs r21,0
45
  sub r22,r15
46
  lsl r22
47
  sbrs r21,7
48
  rjmp DIVLOOP
49
50
  mov V_MicPower_akt,r21
51
52
ADC_Ready_Exit:
53
  cbr Flags,1<<C_V_Busy|1<<Mic_V_Busy
54
  reti

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.