Atmega8 7 Analogwerte - ADC

Gast #2250594
Lesenswert?

Hallo Leute,

ich komme wieder nicht weiter.

Meine ersten versuche:
Ich Starte den ADC mittels Timer alle ca. 1/15s und springt per 
Interrupt in ADC_Start (Z und Y Pointer sind vorerst nirgens im Programm 
verwendet).
Danach soll er alle 7 Messwerte (nur die höherwertigen 8 bit) im SRAM 
ablegen.


Zum testen der Analogwerte habe ich folgedes Programm mit einer LED.
Mein Problem ist, dass die LED wenn sie aus sein sollte willkürlich 
flackert.
Wenn ich den Wert für ADMUX fix festlege (also mit ldi ....) oder wenn 
ich zwischen den einzelnen Messungen mehr als ca. 1-10 ms pause lasse 
funktioniert es richtig:

Bitte um Hilfe.

Test schleifen:
1
  ldi   XL, LOW(DSRAM_Analogwerte)             ; Adresse des Strings in den
2
    ldi   XH, HIGH(DSRAM_Analogwerte)            ; Z-Pointer laden
3

4
loop:
5

6

7
    ld temp4, X
8

9
    cpi temp4, 0x7F
10
    BRSH ADC_Test_H
11

12
    cpi temp4, 0x7D  
13
    BRLO ADC_Test_L  
14

15
  rjmp loop
16

17

18
ADC_Test_L:
19

20
    cbi PORTB, 0
21

22
    rjmp loop
23

24
ADC_Test_H:
25

26
    sbi PORTB, 0
27

28
    rjmp loop

ADC Routine
1
; ADC Routine
2

3
ADC_Start:
4

5

6
   
7
    ldi     ZL, LOW(DFlash_ADC_ADMUX*2)             ; Adresse des Strings in den
8
      ldi     ZH, HIGH(DFlash_ADC_ADMUX*2)            ; Z-Pointer laden
9
  
10
    ldi     YL, LOW(DSRAM_Analogwerte)             ; Adresse des Strings in den
11
      ldi     YH, HIGH(DSRAM_Analogwerte)            ; Z-Pointer laden
12

13
  
14
ADC_Messung_akt:  
15
    
16
      
17
    lpm temp1, Z
18
    cpi temp1, 0b00000000
19
    BREQ ADC_Messung_ende
20
                                                                                                   ;  ldi temp1, 0b11100000
21
    lpm temp1, Z+
22
    out ADMUX, temp1
23

24
    ldi temp1, 1<<ADEN | 1<<ADSC | 1<<ADIE | 1<<ADPS2 
25

26
    out ADCSRA, temp1
27
    
28
    ret
29

30
ADC_Messung_ende:
31

32
    ret
33
    
34
ADC_Messung_fertig:
35
  
36
  
37
    in temp1, ADCH
38
    st Y+, temp1
39

40
  
41

42
    rcall ADC_Messung_akt
43

44

45
    reti
46

47

48
; Datenbereich Flash
49

50

51
DFlash_ADC_ADMUX:         ;ADMUX Register ADC | REFS1 | REFS0 | ADLAR |     |  MUX3 | MUX2 | MUX1 | MUX0 | 
52

53
    .DB 0b11100000, 0b11100001, 0b11100010, 0b11100011, 0b11100100, 0b11100101, 0b11100110, 0b00000000
54
  
55
  
56
    ;  0b11100000,    ;0  ADC0 PC0 - Leuchtdauer Poti 
57
    ;  0b11100001    ;1  ADC1 PC1 - Helligkeit Poti
58
    ;  0b11100010,    ;2  ADC2 PC2 - Empfindlichkeit PIR Poti
59
    ;  0b11100011,    ;3  ADC3 PC3 - Heligkeit LDR
60
    ;  0b11100100,    ;4  ADC4 PC4 - Temperaur außen
61
    ;  0b11100101,    ;5  ADC5 PC5 - Batterie Spannung  
62
    ;  0b11100110,    ;6  ADC6 19 - PIR 
63
    ;  0b00000001,    ;7  Messungen fertig
64
    ;  0b11100111,    ;8  ADC7 22 - Res 
65
    
66

67
; Datenbereich SRAM
68
.DSEG
69

70
DSRAM_Analogwerte:
71

72
    .Byte 1        ;0  ADC0 PC0 - Leuchtdauer Poti 
73
    .Byte 1        ;1  ADC1 PC1 - Helligkeit Poti
74
    .Byte 1        ;2  ADC2 PC2 - Empfindlichkeit PIR Poti
75
    .Byte 1        ;3  ADC3 PC3 - Heligkeit LDR
76
    .Byte 1        ;4  ADC4 PC4 - Temperaur außen
77
    .Byte 1        ;5  ADC5 PC5 - Batterie Spannung
78
    .Byte 1        ;6  ADC6 19 - PIR 
79
    .Byte 1        ;7  ADC7 22 - Res
Gast #2250617
Lesenswert?

1
.include "m8def.inc"
2

3

4

5
.def temp1 = r16
6
.def temp2 = r17
7
.def temp3 = r18
8
.def temp4 = r19
9
.def temp5 = r20
10

11

12

13
.equ XTAL = 419500
14

15

16
.org 0x000          ; Reset Handler
17
         rjmp init            
18

19
.org 0x005          ; Timer 1 Overflow
20
    rjmp Timer_reset
21

22
    reti
23

24
 
25
.org 0x008           ; Capture Event 
26
    rjmp PWM_1
27

28
.org 0x009          ; Timer 0 Overflow
29
        
30
  rcall ADC_Start
31
  
32

33
  
34
  reti
35

36
.org 0x00E          ; ADC Conversion Complete
37
  rjmp ADC_Messung_fertig
38
    
39
    reti
40

41
init: 
42

43
    ldi      temp1, HIGH(RAMEND)     ; Stackpointer initialisieren
44
    out      SPH, temp1
45
    ldi      temp1, LOW(RAMEND)
46
    out      SPL, temp1
47
  
48

49

50
; TIMER 0 für Takt
51

52
  ldi temp1, 1<<CS02  | 1<<CS00    ; Vorteiler Timer 0 aus 1024
53
  out TCCR0, temp1
54
  
55
  ldi temp1, 1<<TOIE0          ; Overflow Timer 0 Enable
56
  out TIMSK, temp1
57
  
58

59
; ADC init
60

61
  ldi temp1, 1<<ADEN | 1<<ADIE | 1<<ADPS2  
62
  out ADCSRA, temp1
63

64

65

66
    
67
 
68
  ldi   XL, LOW(DSRAM_Analogwerte)             ; Adresse des Strings in den
69
    ldi   XH, HIGH(DSRAM_Analogwerte)            ; Z-Pointer laden
70

71

72

73
  sei
74

75

76

77
loop:
78

79

80
    ld temp4, X
81

82
    cpi temp4, 0x7F
83
    BRSH ADC_Test_H
84

85
    cpi temp4, 0x7D  
86
    BRLO ADC_Test_L  
87

88
  rjmp loop
89

90

91
ADC_Test_L:
92

93
    cbi PORTB, 0
94

95
    rjmp loop
96

97
ADC_Test_H:
98

99
    sbi PORTB, 0
100

101
    rjmp loop
102

103

104

105
; ADC Routine
106

107
ADC_Start:
108

109

110
   
111
    ldi     ZL, LOW(DFlash_ADC_ADMUX*2)             ; Adresse des Strings in den
112
      ldi     ZH, HIGH(DFlash_ADC_ADMUX*2)            ; Z-Pointer laden
113
  
114
    ldi     YL, LOW(DSRAM_Analogwerte)             ; Adresse des Strings in den
115
      ldi     YH, HIGH(DSRAM_Analogwerte)            ; Z-Pointer laden
116

117
  
118
ADC_Messung_akt:  
119
    
120
      
121
    lpm temp1, Z
122
    cpi temp1, 0b00000000
123
    BREQ ADC_Messung_ende
124
                                                                                                   ;  ldi temp1, 0b11100000
125
    lpm temp1, Z+
126
    out ADMUX, temp1
127

128
    ldi temp1, 1<<ADEN | 1<<ADSC | 1<<ADIE | 1<<ADPS2 
129

130
    out ADCSRA, temp1
131
    
132
    ret
133

134
ADC_Messung_ende:
135

136
    ret
137
    
138
ADC_Messung_fertig:
139
  
140
  
141
    in temp1, ADCH
142
    st Y+, temp1
143

144
  ;
145

146
    rcall ADC_Messung_akt
147

148

149
    reti
150

151

152
; Datenbereich Flash
153

154

155

156
DFlash_ADC_ADMUX:         ;ADMUX Register ADC | REFS1 | REFS0 | ADLAR |     |  MUX3 | MUX2 | MUX1 | MUX0 | 
157

158
    .DB 0b11100000, 0b11100001, 0b11100010, 0b11100011, 0b11100100, 0b11100101, 0b11100110, 0b00000000
159
  
160
  
161
    ;  0b11100000,    ;0  ADC0 PC0 - Leuchtdauer Poti 
162
    ;  0b11100001    ;1  ADC1 PC1 - Helligkeit Poti
163
    ;  0b11100010,    ;2  ADC2 PC2 - Empfindlichkeit PIR Poti
164
    ;  0b11100011,    ;3  ADC3 PC3 - Heligkeit LDR
165
    ;  0b11100100,    ;4  ADC4 PC4 - Temperaur außen
166
    ;  0b11100101,    ;5  ADC5 PC5 - Batterie Spannung  
167
    ;  0b11100110,    ;6  ADC6 19 - PIR 
168
    ;  0b00000001,    ;7  Messungen fertig
169
    ;  0b11100111,    ;8  ADC7 22 - Res 
170
    
171

172
; Datenbereich SRAM
173
.DSEG
174

175
DSRAM_Analogwerte:
176

177
    .Byte 1        ;0  ADC0 PC0 - Leuchtdauer Poti 
178
    .Byte 1        ;1  ADC1 PC1 - Helligkeit Poti
179
    .Byte 1        ;2  ADC2 PC2 - Empfindlichkeit PIR Poti
180
    .Byte 1        ;3  ADC3 PC3 - Heligkeit LDR
181
    .Byte 1        ;4  ADC4 PC4 - Temperaur außen
182
    .Byte 1        ;5  ADC5 PC5 - Batterie Spannung
183
    .Byte 1        ;6  ADC6 19 - PIR 
184
    .Byte 1        ;7  ADC7 22 - Res
#2250629
Lesenswert?

SREG sichern ist auf jeden Fall wichtig.

Das andere:
Es könnte sein, dass die Umschaltung zwischen den ADC Kanälen zu schnell 
erfolgt und sich daher die Sample&Hold Stufe am Eingang nicht schnell 
genug auf den nächsten Eingang einstellen kann. Meistens macht man es 
so, dass man die erste Messung nach dem Umschalten des Kanals verwirft 
und erst die 2.te nimmt. Zumindest sieht man das so in vielen 
Programmen. Was wirklich dahinter steckt und ob es notwendig ist, kann 
ich dir jetzt so auch nicht sagen.
Gast #2250670
Lesenswert?

Hi

> Meistens macht man es
>so, dass man die erste Messung nach dem Umschalten des Kanals verwirft
>und erst die 2.te nimmt. Zumindest sieht man das so in vielen
>Programmen. Was wirklich dahinter steckt und ob es notwendig ist, kann
>ich dir jetzt so auch nicht sagen.

Das wird eigentlich nur nach Umschaltung der Referenzspannungsquelle 
empfohlen. Bei Messungen alle 66ms sehe ich da nicht das Problem.

@Matthias (Gast)

Ich empfehle dir folgendes:

Den ADC einmal mit den relevanten Einstellungen außer ADSC und MUX3..0 
zu initialisieren

Eine Speicherstelle für den Kanal festlegen (ich bevorzuge RAM). Dient 
gleichzeitig als Offset zum Speichern

Im Timer0-Overflow-Interrupt den ADC starten (->Adsc)

Im ADC Complete Interrupt den ADC auslesen, speichern und auf den 
nächsten Kanal umschalten

MfG Spess
#2250683
Lesenswert?

spess53 schrieb:
> Hi
>
>> Meistens macht man es
>>so, dass man die erste Messung nach dem Umschalten des Kanals verwirft
>>und erst die 2.te nimmt. Zumindest sieht man das so in vielen
>>Programmen. Was wirklich dahinter steckt und ob es notwendig ist, kann
>>ich dir jetzt so auch nicht sagen.
>
> Das wird eigentlich nur nach Umschaltung der Referenzspannungsquelle
> empfohlen. Bei Messungen alle 66ms sehe ich da nicht das Problem.

Oh. Die idee in seinem Code ist aber nicht alle 66ms zu messen.

Mit dem Timer startet er eine Kette von Ereignissen. Der ADC läuft auf 
Interrupt. Mit jedem Interrupt holt er das Ergebnis, stellt den Kanal um 
und startet die nächste Wandlung, bis am Ende dann der ADC nicht mehr 
gestartet wird und alles zum Erliegen kommt, bis dann der Timer erneut 
alles triggert.
Ich bin mir auch noch nicht sicher, ob ich das so machen würde bzw. was 
ich davon halten soll.


> Ich empfehle dir folgendes:
>
> Den ADC einmal mit den relevanten Einstellungen außer ADSC und MUX3..0
> zu initialisieren
>
> Eine Speicherstelle für den Kanal festlegen (ich bevorzuge RAM). Dient
> gleichzeitig als Offset zum Speichern
>
> Im Timer0-Overflow-Interrupt den ADC starten (->Adsc)
>
> Im ADC Complete Interrupt den ADC auslesen, speichern und auf den
> nächsten Kanal umschalten

Hmm.
Genau das macht er doch.
Jetzt bin ich verwirrt.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren