Hallo,
Ich bin jetzt schon seit einigen Stunden am verzweifeln. Ich habe mir
eine Funktion geschrieben die einen externen ADC ausliest. Ich übergebe
der Funktion die Adresse des Puffers:
1
// Definition: unsigned short ext_ADC_val[8];
2
read_adc_complete(&ext_ADC_val[0]);
Die Funktion besteht aus drei Teilen: Daten werden vom GPIO geholt und
in lokale Variablen geladen. Inhalt der Variablen wird an die Adresse
des Puffers geschrieben. Die lokale Variablen werden zum Debuggen
ausgegeben.
Jetzt das Problem: Wenn ich den zweiten Teil, die Übergabe an den Puffer
mithilfe von Pointern weglasse, dann funktioniert die Funktion. Wenn ich
den mittleren Teil jedoch nicht auskommentiere, dann werden falsche
Daten in den Puffer geschrieben und auch die Debugausgabe funktioniert
nicht mehr. Das obere Byte ist dann immer FF aber das untere ist
richtig. Das passiert sowohl in der Debug, als auch in der Release
Einstellung.
µC: AVR32, Software: Atmel Studio 6
Vielen Dank. Welchen Teil brauchst du?
Hier ist mal die Portauslesefunktion. (Als Inline) Der ADC hängt an den
Ports 0..7 und 11..18. (Danke Atmel für die Anordnung der Ports am
Gehäuse!)
Matthias xxx schrieb:> Vielen Dank. Welchen Teil brauchst du?
Alles was relevant ist.
Idealfall: ein in sich komplettes Minimalprogramm, welches den
beobachteten Effekt zeigt.
> Hier ist mal die Portauslesefunktion.
Die dürfte ziemlich sicher nicht zum Problem beitragen. Denn die liefert
ja ihre Werte korrekt.
Minimalprogramm, welches ein main zeigt, in dem
UART initialisierst wird
ADC initialisiert wird
in der Hauptschleife der Aufruf in deine ADC Funktion statt findet
Ausgabefunktion auf die UART
Wenn du extra ein Programm dafür zurecht machen musst, dann klär vorher
ab, ob du in diesem Minimalprogramm den beschriebenen Effekt noch siehst
oder nicht.
800007FE ld.w R11, R7[1120] //liest das Register ein
5
return (tmph | tmpl);
6
80000802 asr R12, R11, 3 //das High byte um 3 nach rechts
7
80000806 andl R12, 0xff00, COH // & 0xFF00
8
8000080A or R11, R12, R11 << 0 // Oderverknüpfung High und Low
9
*adresse=adcExternGetPort();
10
8000080E st.h R9[0], R11 //Speichern an die Adresse im Puffer
11
ADC_EXTERN_RD_HIGH; //
12
80000810 st.w R7[1108], R8
Wo ist da die die implementierung für
int tmpl = (0xFF & (tmp>>ADC_EXTERN_DATA_LOW)); // >> 0
?????
Ok das um 0 nach rechts schieben kann sich der compiler sparen, aber
nicht die 0xFF Verknüpfung??
Wenn ich ohne Pointer arbeite und die den Inhalt der Variable nicht in
den Puffer schreibe, dann macht der Compiler:
1
usart_debug_write_16bitInt((adc4));
2
80000848 lddsp R12, SP[0xc] //Portinhalt wurde vorher in den Stack geschrieben
3
8000084A lsr R12, 3 //um 3 nach rechts
4
8000084C andl R12, 0xff00, COH // & 0xFF00
5
80000850 castu.b R3 // & 0xFF
6
80000852 or R12, R3 //High und Low zusammenbringen
Letzter Versuch, dann geh ich schreiend nach Hause:
Beim Auslesen des ADCs speichere ich die Portbelegung jetzt direkt als
unsigned int:
adc0 = AVR32_GPIO.port[ADC_EXTERN_PORT].pvr;
Das Einlesen funktioniert auch. Der Compiler liest die 8 Kanäle in
jeweils ein Register.
Nachdem alles ausgelesen wurde mache ich die Operationen:
Pins 11..18 sollen der Highteil meines 16bit ADC Wert sein
Pins 0..7 sollen der Lowteil meines 16bit ADC Wert sein
das realisiere ich mit:
Konnte mich doch nicht von dem Problem lösen;)
ich habe folgendes geändert:
1
(0xFF00&(data>>3))|(0xff&data)
ergibt im ASM:
1
lsr R8, R12, 3
2
andl R8, 0xff00, COH
3
or R12, R8, R12 << 0
geändert in:
1
(0xFF00&(data>>3))+(0xff&data)
1
lsr R8, R12, 3
2
andl R8, 0xff00
3
castu.b R12
4
add R12, R8
Mathematisch gesehen macht hier die Addition das gleiche wie die
Oderverknüfung. Aber nur wenn ich addiere, dann castet der Compiler auch
mein Low-byte richtig. Ist das ein Bug?