Hi,
ich habe ein ziemlich komisches Problem....
Ich versuche gerade, eine ADC-ISR zu programmieren, die 2 ADC-Kanäle des
AVRs im Wechsel ausliest.
Zunächst zu den Rahmenbedingungen:
Hardware: AtMega1284P @ 20MHz bei 3,3V (clean) auf eigener Platine
IDE/Toolchain: Atmel Studio 6 mit integrierter Toolchain
Gedebuggt habe ich mit meinem Dragon.
Hier mal mein Code:
while(count<maxcount);//abwarten bis alle Messwerte gesammelt wurden.
138
139
}
140
141
while(1);
142
143
return0;
144
}
145
146
ISR(ADC_vect){
147
chartxt[20];
148
149
count2=count2+1;//count2++; //auch ohne erfolg
150
151
count=countA+countB;
152
153
if(count<maxcount){
154
155
if(ADMUX&1){
156
sumA+=ADC;
157
countA++;
158
ADMUX=((3<<REFS0)|0);
159
}else{
160
sumB+=ADC;
161
countB++;
162
ADMUX=((3<<REFS0)|1);
163
}
164
165
ADCSRA|=(1<<ADSC);
166
167
}else{
168
countC++;
169
ADCSRA&=~((1<<ADIE)|(1<<ADSC));
170
}
171
172
}
Im Debugger läuft der Code ohne Weiteres, bis auf ein mal die Variable
count2 (a.k.a. R24, s.u.) z.B. von 0x12 auf 0x03 springt. Der Fehler
scheint irgendwie zur Laufzeit zu passierten, denn es scheint nicht vom
Wert von count2 abhängig, auch wenn der Fehler nie bei Werten unterhalb
0x10 passiert (vllt. wichtig?).
Das disassembly von count2 = count2 + 1; sieht folgendermaßen aus:
1
count2 = count2 + 1;
2
000001B7 LDS R24,0x013D Load direct from data space
3
000001B9 LDS R25,0x013E Load direct from data space
4
000001BB LDS R26,0x013F Load direct from data space
5
000001BD LDS R27,0x0140 Load direct from data space
6
7
000001BF ADIW R24,0x01 Add immediate to word
8
000001C0 ADC R26,R1 Add with carry
9
000001C1 ADC R27,R1 Add with carry
10
11
000001C2 STS 0x013D,R24 Store direct to data space
12
000001C4 STS 0x013E,R25 Store direct to data space
13
000001C6 STS 0x013F,R26 Store direct to data space
14
000001C8 STS 0x0140,R27 Store direct to data space
Der Fehler passiert bei ADIW R24,0x01. R24 wurde davor aus dem RAM mit
(z.B.) 0x12 geladen, und wenn ADIW R24,0x01 ausgeführt wird steht da in
R24 z.B. statt 0x13 0x03.
Es hat fast den Anschein, als wäre das obere Nibble auf dem Weg von der
ALU zurück abanden gekommen...
Ich bin jetzt ehrlichgesagt ratlos.
Habt ihr ne Idee? (Auch wie man der ganzen Sache noch näher auf den Zahn
fühlen könnte...? -> ich dachte zuerst an einen unerlaubten RAM-Zugriff,
aber das konnte ich durch einen Data-Breakpoint ausschließen...)
Danke euch,
Tobi
>Es hat fast den Anschein, als wäre das obere Nibble auf dem Weg von der>ALU zurück abanden gekommen...
Ja, so ist es. Auf Variablen die grösser 8Bit sind und die
in einem Interrupt verändert werden sollte man beim AVR
ausserhalb eines Interrupts nur mit Interruptsperre zugreifen.
Beispiel:
cli();
count2 = 0; //reset
sei();
Tobias Schlegel schrieb:> AtMega1284P @ 20MHz bei 3,3V
damit bewegst du dich übrigens bereits außerhalb der Spezifikation des
Prozessors.
Dein Problem muss zwar nicht unbedingt daran liegen, aber Fehlfunktionen
durch die zu niedrige Versorgungsspannung sind trotzdem nicht
auszuschließen.
Speed Grades
– 0 - 4 MHz @ 1.8 - 5.5V
– 0 - 10 MHz @ 2.7 - 5.5V
– 0 - 20 MHz @ 4.5 - 5.5V
lg
Chris
Hi,
holger schrieb:> Auf Variablen die grösser 8Bit sind und die> in einem Interrupt verändert werden sollte man beim AVR> ausserhalb eines Interrupts nur mit Interruptsperre zugreifen.
Zugegeben, ist nicht gerade guter Stil, generell eine ISR ohne
Interruptsperre zu implementieren, allerdings ist es geplant die ADC-ISR
als 'NOBLOCK' laufen zu lassen, da der AVR in dem eigentlichen Programm
noch 2 Phasenanschnittstreiber mit 100Hz bedienen soll, also noch andere
wichtige Dinge zu tun hat...
Der Debugger hat auch keinen Hinweis darauf geliefert, dass die ISR
durch einen anderen Interrupt unterbrochen wurde. Ausserdem passiert das
Malheur während 1 einzigen Instruktion.
chris schrieb:> damit bewegst du dich übrigens bereits außerhalb der Spezifikation des> Prozessors.
Whoops, da hast du recht!
chris schrieb:> Dein Problem muss zwar nicht unbedingt daran liegen, aber Fehlfunktionen> durch die zu niedrige Versorgungsspannung sind trotzdem nicht> auszuschließen.
Yep, ich werde das trotzdem gleich morgen mal mit 5V Versorgungsspannung
gegenchecken. Wäre ja schon doof wenns daran liegen würde...
Dann bräuchte ich zwar nen Pegelwandler fürs TFT ... naja.
Einen Tod muss man sterben...
Danke, ich werde das mal testen...
Tobi