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);
Hier noch mal als Source das Einbetten des Codes hat nicht funktioniert.
Johann schrieb: > Hier noch mal als Source das Einbetten des Codes hat nicht funktioniert. Weil es richtig so geht
1 | [c][/c] |
mit [], nicht mit <>
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.
1 | test = adca_read(0); |
2 | usart_putchar(&USARTC0, (unsigned char) (test >> 8), WITHOUT_SLIP_PROTOCOL); |
3 | usart_putchar(&USARTC0, (unsigned char) test, WITHOUT_SLIP_PROTOCOL); |
4 | |
5 | test = adca_read(0); |
6 | usart_putchar(&USARTC0, (unsigned char) (test >> 8), WITHOUT_SLIP_PROTOCOL); |
7 | usart_putchar(&USARTC0, (unsigned char) test, WITHOUT_SLIP_PROTOCOL); |
Denn steht das hier noch in der Hilfe falsch: http://www.mikrocontroller.net/articles/Hilfe:Bearbeitungshilfe
sorry
1 | test = adca_read(0); |
2 | usart_putchar(&USARTC0, (unsigned char) (test >> 8), WITHOUT_SLIP_PROTOCOL); |
3 | usart_putchar(&USARTC0, (unsigned char) test, WITHOUT_SLIP_PROTOCOL); |
4 | |
5 | |
6 | adca_read2(0, &adc_data[0]); |
7 | usart_putchar(&USARTC0, adc_data[0], WITHOUT_SLIP_PROTOCOL); |
8 | usart_putchar(&USARTC0, adc_data[1], WITHOUT_SLIP_PROTOCOL); |
Die Sprünge hast du mut Variante 1 also nicht? wird sonst noch irgendwo auf
1 | adc_data
|
zugegriffen? Evtl. "funkt" dir da was dazwischen? ist aber ohne vollständigen Code schwierig zu beurteilen :-)
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
|
2 | void adca_read2(unsigned char channel, unsigned char *new_adc_sample) |
3 | {
|
4 | unsigned int data; |
5 | |
6 | ADC_CH_t *pch = &ADCA.CH0+channel; |
7 | |
8 | // Start the AD conversion
|
9 | pch->CTRL |= 1<<ADC_CH_START_bp; |
10 | |
11 | // Wait for the AD conversion to complete
|
12 | while ((pch->INTFLAGS & ADC_CH_CHIF_bm) == 0); |
13 | |
14 | // Clear the interrupt flag
|
15 | pch->INTFLAGS = ADC_CH_CHIF_bm; |
16 | |
17 | ((unsigned char *) &data)[0] = pch->RESL; |
18 | ((unsigned char *) &data)[1] = pch->RESH; |
19 | |
20 | new_adc_sample[0] = (unsigned char) (data >> 8); |
21 | new_adc_sample[1] = (unsigned char) data; |
22 | }
|
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!
ich denke da liegt dann auch das Problem. Wie gesagt, ohne VOLLSTÄNDIGEN Code ist es aber nur Raterei.
Sepp schrieb: >
1 | > volatile unsigned char adc_data[8]; |
2 | >
|
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.
:
Bearbeitet durch Moderator
@ 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] = (unsigned char) (ADC->CH0RES >> 8); |
3 | new_adc_sample[1] = (unsigned char) 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.
:
Bearbeitet durch User
@ 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 ...
:
Bearbeitet durch User
@ 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.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.