Forum: Mikrocontroller und Digitale Elektronik Ich sehe eine den Fehler nicht


von Johann (Gast)


Lesenswert?

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);

von Johann (Gast)


Angehängte Dateien:

Lesenswert?

Hier noch mal als Source das Einbetten des Codes hat nicht funktioniert.

von Max H. (hartl192)


Lesenswert?

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 <>

von Sepp (Gast)


Lesenswert?

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?

von Sepp (Gast)


Lesenswert?

WAS genau funktioniert denn nicht?

von Johann (Gast)


Lesenswert?

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

von Johann (Gast)


Lesenswert?

sporadische :-)

von Johann (Gast)


Lesenswert?

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);

von Sepp (Gast)


Lesenswert?

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 :-)

von Route_66 H. (route_66)


Lesenswert?

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.

von Johann (Gast)


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Johann (Gast)


Lesenswert?

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
}

von MaWin (Gast)


Lesenswert?

Wie ist denn &adc_data deklariert ?

von Johann (Gast)


Lesenswert?

1
unsigned char adc_data[8];

von Sepp (Gast)


Lesenswert?

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!

von Sepp (Gast)


Lesenswert?

ich denke da liegt dann auch das Problem.

Wie gesagt, ohne VOLLSTÄNDIGEN Code ist es aber nur Raterei.

von Sepp (Gast)


Lesenswert?

1
volatile unsigned char adc_data[8];

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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
von Johann (Gast)


Lesenswert?

@ 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.

von Bernhard F. (bernhard_fr)


Lesenswert?

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
von Johann (Gast)


Lesenswert?

@ 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.

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

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 ;-)

von Route_66 H. (route_66)


Lesenswert?

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?

von uwe (Gast)


Lesenswert?

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?

von uwe (Gast)


Lesenswert?

ups zu langsam...

von Bernhard F. (bernhard_fr)


Lesenswert?

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
von Johann (Gast)


Lesenswert?

@ 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
Noch kein Account? Hier anmelden.