Hallo!
Ich möchte über die Entladezeit eines Kondensators desssen Kapazität
bestimmen. Habe dazu den einen Pol an den Komparatoreingang AIN1
(PortA.2) und über einen Widerstand mit einem Portpin (PortA.3)
verbunden und den anderen Pol an Masse gelegt. Das Assemblerprogramm
lädt den Kondensator zunächst 1s lang. Direkt vor dem Entladen wird
Timer1 gestartet und soll im Komparator-Interrupt ausgelesen und im
EEPROM gespeichert werden.
Es scheint alles korrekt zu funktionieren (im Komparator-Interrupt wird
eine LED angeschaltet), jedoch finden sich nach Ablauf des Programms im
EEPROM unsinnige (viel zu kleine) Werte; das HIGH-Byte ist immer 0x00
und das LOW-Byte schwankt ungefähr zwischen 0x06 und 0xA4.
Bei der Simulation im AVR-Studio funktionierte alles wie gewünscht, ich
weiß echt nicht, wo der Fehler liegen könnte.
Hier der aktuelle Quelltext:
1
.include "tn24def.inc"
2
3
.macro ROT_AN
4
sbi PORTB,0
5
.endmacro
6
.macro ROT_AUS
7
cbi PORTB,0
8
.endmacro
9
.macro GRUEN_AN
10
sbi PORTB,1
11
.endmacro
12
.macro GRUEN_AUS
13
cbi PORTB,1
14
.endmacro
15
.macro C_LADEN
16
sbi PORTA,3
17
.endmacro
18
.macro C_ENTLADEN
19
cbi PORTA,3
20
.endmacro
21
22
.cseg
23
.org 0x0000
24
rjmp main
25
26
.org EXT_INT0addr ; External Interrupt Request 0
27
reti
28
.org PCI0addr ; Pin Change Interrupt Request 0
29
reti
30
.org PCI1addr ; Pin Change Interrupt Request 1
31
reti
32
.org WATCHDOGaddr ; Watchdog Time-out
33
reti
34
.org ICP1addr ; Timer/Counter1 Capture Event
35
reti
36
.org OC1Aaddr ; Timer/Counter1 Compare Match A
37
reti
38
.org OC1Baddr ; Timer/Counter1 Compare Match B
39
reti
40
.org OVF1addr ; Timer/Counter1 Overflow
41
reti
42
.org OC0Aaddr ; Timer/Counter0 Compare Match A
43
reti
44
.org OC0Baddr ; Timer/Counter0 Compare Match B
45
reti
46
.org OVF0addr ; Timer/Counter0 Overflow
47
reti
48
.org ACIaddr ; Analog Comparator
49
rjmp AC_Int
50
.org ADCCaddr ; ADC Conversion Complete
51
reti
52
.org ERDYaddr ; EEPROM Ready
53
reti
54
.org USI_STRaddr ; USI START
55
reti
56
.org USI_OVFaddr ; USI Overflow
57
reti
58
59
.org INT_VECTORS_SIZE
60
main:
61
ldi r16, RAMEND ;Stackpointer initialisieren
62
out SPL, r16
63
ldi r16, 0x03 ;Ausgänge aktivieren
64
out DDRB, r16
65
sbi DDRA, 3
66
ldi ZL, LOW(EEPROM_Daten)
67
ldi ZH, HIGH(EEPROM_Daten)
68
ROT_AN
69
GRUEN_AN
70
rcall wait1s
71
ROT_AUS
72
GRUEN_AUS
73
rcall wait1s
74
ROT_AN
75
GRUEN_AN
76
C_LADEN
77
rcall wait1s
78
ROT_AUS
79
GRUEN_AUS
80
cbi ADCSRB, ACME ;AIN0 und AIN1 als Eingänge verwenden (Mux aus)
81
cbi ACSR, ACIS1
82
cbi ACSR, ACIS0
83
sbi ACSR, ACIE ;Komparator aktivieren
84
ldi r16, 0x00
85
out TCCR1B, r16
86
out TCNT1H, r16
87
out TCNT1L, r16
88
ldi r16, (0<<CS12)|(0<<CS11)|(1<<CS10)
89
out TCCR1B, r16 ;Timer starten
90
sbi ACSR, ACI ;AC-Interrupt zurücksetzen
91
sei ;Interrupts global aktivieren
92
C_ENTLADEN
93
loop:
94
rjmp loop
95
96
AC_Int:
97
GRUEN_AN
98
; ldi r18, 0x00
99
; out TCCR1B, r18
100
in r18, TCNT1H
101
rcall EEPROM_Write
102
adiw ZL, 1
103
in r18, TCNT1L
104
rcall EEPROM_Write
105
cbi ACSR, ACIE
106
reti
107
108
EEPROM_Write:
109
sbic EECR, EEPE
110
rjmp EEPROM_Write
111
out EEARH, ZH
112
out EEARL, ZL
113
out EEDR, r18
114
in r18, sreg
115
cli
116
sbi EECR, EEMPE
117
sbi EECR, EEPE
118
out sreg, r18
119
ret
120
121
wait1s:
122
push r16
123
ldi r16, 0xFA
124
wait1s_inner:
125
rcall wait1ms
126
rcall wait1ms
127
rcall wait1ms
128
rcall wait1ms
129
dec r16
130
brne wait1s_inner
131
pop r16
132
ret
133
134
wait1ms:
135
push r16
136
push r17
137
ldi r16, 0x10
138
wait1ms_r16:
139
ldi r17, 0xA5
140
wait1ms_r17:
141
dec r17
142
brne wait1ms_r17
143
dec r16
144
brne wait1ms_r16
145
pop r17
146
pop r16
147
ret
148
149
.eseg
150
EEPROM_Daten:
Ich hoffe ihr könnt mir helfen.
Danke und Gruß
Ladde
Da mit bloßem Auge zu erkennen ist, dass die LED erst aus und nach
kurzer Zeit wieder an geht (~0,1s) sollte der Timer1 schon mehrfach
überlaufen bis er ausgelesen wird. Ich erwarte stark schwankende Werte
(auch im HIGH-Byte), bekomme jedoch auch bei Variation des
angeschlossenen Kondensators immer unwahrscheinlich kleine Werte
(HIGH-Byte 0x00, LOW-Byte =< 0xB0).
> in r18, TCNT1H> rcall EEPROM_Write> adiw ZL, 1> in r18, TCNT1L> rcall EEPROM_Write
Also, schau mal auf das Datenblatt, Seite 88, da steht etwas über die
16-Bit-Zugriffe. Quintessenz des Textes:
16 Bit Schreiben: erst High-Byte, dann Low-Byte
16 Bit Lesen: erst Low-Byte, dann High-Byte
Wenn Du Dir das Blockdiagramm und die Beschreibung auf Seite 92
durchliest, wird auch klar, warum. Beim Lesen des Low-Bytes wird das
High-Byte in das Zwischenregister kopiert. Das High-Byte wird danach aus
dem Zwischenregister gelesen. Liest Du zuerst das High-Byte, ist ja im
Zwischenregister noch nichts.
Versuch es mal anders herum.
Viel Erfolg.
Reinhard