Halle Leute,
ich habe 2 Funktionen. Die Funktionen unterscheiden sich im
Rückgabewert. Die 1 Funktion gibt einen integer zurück, währen die 2.
Funktion einen Zeiger auf Char Array übergeben bekommt.
Nur leider ist es so das die Funktion mit dem Rückgabewert funktioniert
und die mit dem Array leider nicht. Jedoch benötige ich die Funktion mit
dem Array, da ich noch mehr Werte zurückgeben möchte.
<c>
// ADCA channel data read function using polled mode
unsigned int adca_read(unsigned char channel)
{
unsigned int data;
ADC_CH_t *pch = &ADCA.CH0+channel;
// Start the AD conversion
pch->CTRL |= 1<<ADC_CH_START_bp;
// Wait for the AD conversion to complete
while ((pch->INTFLAGS & ADC_CH_CHIF_bm) == 0);
// Clear the interrupt flag
pch->INTFLAGS = ADC_CH_CHIF_bm;
// Read the AD conversion result
((unsigned char *) &data)[0] = pch->RESL;
((unsigned char *) &data)[1] = pch->RESH;
return data;
}
// ADCA channel data read function using polled mode
void adca_read2(unsigned char channel, unsigned char *new_adc_sample)
{
ADC_CH_t *pch = &ADCA.CH0+channel;
// Start the AD conversion
pch->CTRL |= 1<<ADC_CH_START_bp;
// Wait for the AD conversion to complete
while ((pch->INTFLAGS & ADC_CH_CHIF_bm) == 0);
// Clear the interrupt flag
pch->INTFLAGS = ADC_CH_CHIF_bm;
new_adc_sample[0] = pch->RESH;
new_adc_sample[1] = pch->RESL;
}
</c>
hier noch der Funktionsaufruf:
test = adca_read(0);
usart_putchar(&USARTC0, (unsigned char) (test >> 8),
WITHOUT_SLIP_PROTOCOL);
usart_putchar(&USARTC0, (unsigned char) test, WITHOUT_SLIP_PROTOCOL);
adca_read2(0, &adc_data[0]);
usart_putchar(&USARTC0, adc_data[0], WITHOUT_SLIP_PROTOCOL);
Ganz gleich sind die zwei Funktion nicht!
Johann schrieb:> new_adc_sample[0] = pch->RESH;> new_adc_sample[1] = pch->RESL;Johann schrieb:> ((unsigned char *) &data)[0] = pch->RESL;> ((unsigned char *) &data)[1] = pch->RESH;
Low und High Byte vertauscht?
Ich bekomme sporalische digitale Sprünge, die ich mir nichr erklären
kann.
Das mit dem High und Low-Byte drehe ich wieder bei der USART
Übertragung. Bei der USART Übertragung sende ich zuerst das High-Byte
und anschließend das Low-Byte.
Hallo!
Ich habe nirgends gelesen, um welchen Controller es hier geht. Ist es
aber nicht so, dass es wichtig ist, in welecher Reihenfolge Low- und
High-Teil geschrieben und gelesen werden, weil der andere Teil temporär
zwischengespeichert wird? So könnten jedenfalls Sprünge zustandekommen,
wenn L-Teil und H-Teil nicht aus der gleichen Umsetzung kommen.
ich verwende den xmega32a4u von Atmel. Bei der Varainte mit dem
Rückgabewert ist dieser Fehler nicht vorhanden.
Der Code kann von keiner Interruptroutine unterbrochen werden, da er nur
in einer Interruptroutine ausgeführt wird.
Johann schrieb:> Der Code kann von keiner Interruptroutine unterbrochen werden, da er nur> in einer Interruptroutine ausgeführt wird.
Du machst in einer ISR ADC-Warteschleifen und auch USART-putchars???
Ich bin jetzt mit dem xmega nicht so bewandert und weiß nicht, was sich
hinter usart_putchar() verbirgt.... eventuell noch eine Warteschleife?
Aua.
Ich muss jetzt die Funktion ändern. Ich speicher den ADC Wert (HighByte
und LowByte) zuerst in einem Integer Temp Wert. Anschließend speicher
ich den TempWert in dem Char Array ab.
Das ärgert mich so das ich es doppelt machen muss aber so funktioniert
es ohne digitale Sprünge.
1
// ADCA channel data read function using polled mode
Also IN der ISR?
Dan müsste adc_data volatile sein!
Aber ich würde das anders machen.
ISR nur kurz, also KEINE Wartezyklen. Und die Putchars auch raus!
Wenn adc_data nur innerhalb der ISR und den von dort aus aufgerufenen
Funktionen benutzt wird, ist das volatile hyperfluid. Und so sieht das
auch aus, jedenfalls was die Codefragmente an Informationen liefern.
adc_data wird offenbar aus der ISR als Parameter (Pointer) übergeben.
Wenn es nicht global anderweitig verwendet wird, ist das volatile eher
kontraproduktiv.
Aber solange da zig Warteschleifen (ADC und UART) aus der ISR heraus
gemacht werden, sind alle weiteren Aussagen ohne kompletten Code
Spekulation. Sowas macht man einfach nicht.
@ Sepp
volatile muss ich nur dann benutzen wenn ich das array außerdalb einer
ISR deklariere. Da ich es aber innerhalb der ISR mach muss ich dies
nicht machen.
Ich habe jetzt den Fehler eingegrenzt und bin der Meinung das dies ein
Compiler Bug ist
1
// Read the AD conversion result
2
new_adc_sample[0]=(unsignedchar)(ADC->CH0RES>>8);
3
new_adc_sample[1]=(unsignedchar)ADC->CH0RES;
4
5
new_adc_sample[0]=ADC->CH0RESH;
6
new_adc_sample[1]=ADC->CH0RESL;
Die obere Variante funktioniert und die untere Variante erzeugt die
digitalen Fehler. Der XMEGA ADC schreibt das Ergebnis in 2 seperate
Bytes. dem RESL und dem RESH. Demnach muss ich auch darauf zugreifen
können. Jedoch wenn dies mache erhalte ich den Fehler.
Der Compiler bietet zwei möglichkeiten auf das Ergebnis Register
zuzugreifen. Nur leider funktioniert nur eine Variante ohne Fehler.
Die Lösung deines Problems wurde vor nichtmal einem Tag im Forum
gepostet...
Bezeichnenderweise heißt der Thread auch noch "Digitale Sprünge beim
XMEGA ADC"
Beitrag "Re: Digitale Sprünge beim XMEGA ADC"
Ganz einfach das Low-Byte muss zuerst ausgelesen werden...
War schon beim ATmega so und ist beim X-Mega nicht anders.
edit: und nochwas
Wobei ich eh nicht einsehe wozu du 2 Zeilen Code brauchst um das in dein
Array zu schreiben ...
Wenn du den 16bit Wert an die Position 8bit_array[0] schreibst, dann
steht an 8bit_array[0] das Highbyte und an 8bit_array[1] das Lowbyte.
Das ist C und nicht Assembler. Für die Details gibts den Compiler und
wenn der noch Warnungen ausspuckt wird halt noch der typecast benutzt.
Nebenbei bemerkt: Ich würde auch nicht unbedingt unsigned int benutzen
sondern Atmel hat so nette Kürzel wie unint8_t und uint16_t vorgesehen.
@ Bernhard
vielen Dank für diesen Hinweis. Ich habe den Thread heute aus den Augen
verloren.
Ich bin EUCH wirklich sehr sehr, sehr dankbar. Endlich ist das Problem
gelöst. Ich war wirklich verzweifelt. Die Information das es sich um ein
16Bit Register handelt habe ich überlesen. Ohne Euch hätte ich den
Fehler nicht gefunden. Deshalb noch mal Tausend Dank für die Geduld und
die Hilfe. Ich ware halt schon angefressen und hatte wegen dem ADC
schlecht geschlafen deshalb noch mal sorry für den manchmal nicht so
freundlichen Umgang.
Johann schrieb:> Ich habe jetzt den Fehler eingegrenzt und bin der Meinung das dies ein> Compiler Bug ist
solche Annahmen sind genau so plausibel wie die Annahme, daß ein Auto
einen Konstuktionsfehler hat, weil es gegen den Baum gefahren ist.
In den allermeisten Fällen sitzt das Problem vor, und nicht hinter dem
Bildschirm ;-)
Bernhard F. schrieb:> Ganz einfach das Low-Byte muss zuerst ausgelesen werden...
Hatte ich bereits 14:21 geschrieben. Wenn man das aber nicht liest, wozu
bittet man dann hier um Hilfe?
route_66 schrieb schon um 14:20 Uhr:
>Hallo!>Ich habe nirgends gelesen, um welchen Controller es hier geht. Ist es>aber nicht so, dass es wichtig ist, in welecher Reihenfolge Low- und>High-Teil geschrieben und gelesen werden, weil der andere Teil temporär>zwischengespeichert wird? So könnten jedenfalls Sprünge zustandekommen,>wenn L-Teil und H-Teil nicht aus der gleichen Umsetzung kommen.
Warum bist du da nicht drauf eingegangen?
Route 66 schrieb:> Bernhard F. schrieb:>> Ganz einfach das Low-Byte muss zuerst ausgelesen werden...>> Hatte ich bereits 14:21 geschrieben. Wenn man das aber nicht liest, wozu> bittet man dann hier um Hilfe?
In 2 Threads btw...
und tut mir Leid, ich hab den kompletten Thread nicht gelesen sonst
hätte ich mich darauf auch noch bezogen. Aber beim Compilerfehler musste
ich einfach was schreiben ...
@ route_66
sorry aber aus Deiner Beschreibung bin ich wirklich nicht schlau
geworden. Bernhard hat es einfach auf den Punkt gebracht.
bezüglich Compiler Fehler. Ich hatte vor kurzen einem Compiler Fehler
beim CRC. Dies lag an dem Fehler in der Struktur. Hier wurde ein Byte
vergessen dadurch stimmte die Adresszuordnung nicht mehr. Inzwischen
wurde dieses von Codevision korrigiert.