Ich habe eine Funktion zum Empfangen von Strings über USART geschrieben.
Dabei wurde ein String sowie ein Char Array global deklariert. Mein
Problem ist folgendes. Wenn ich ein String versende "hans wurst",
empfange ich auch "hans wurst". Dies kann ich unendlich oft machen und
alles klappt wunderbar. Sobald sich aber die Zeichenkette ändert, z.B:
von "hans wurst" in "hans peter" taucht nach dem ersten Empfang von
"hans peter" an der ersten Position des Strings ein nicht darstellbares
Zeichen "0x03". Danach kann ich "hans peter" so oft wie ich möchte
fehlerfrei senden. Wie ich festgestellt habe sehen die Daten im Char
Array noch ok aus. Also beim versenden von verschiedenen Zeichenketten
immer das richtige Ergebnis ohne "0x03". Nur halt beim Wechseln von
Zeichenketten. Gebe ich die Char_Array aus, ist die Welt heil. Also wird
das Problem beim Umkopieren vom Char Array nach String auftauchen, was
ich mir jedoch nicht erklären kann.
Hier ist mein Code:
1
char*my_str;
2
charchar_arr[127];
3
4
u8uart_getc(void){
5
6
while(!(UCSR1A&(1<<RXC1)));
7
returnUDR1;
8
}
9
10
voiduart_gets(u8max_size){
11
12
u8new_char;
13
staticu8len;
14
new_char=uart_getc();
15
16
17
if(new_char!=']'&&len<max_size){
18
char_arr[len]=new_char;
19
len++;
20
}
21
else{
22
my_str=char_arr;// ist das falsch?
23
my_str[len]='\0';
24
25
// release received string
26
len=0;
27
received=1;
28
29
/*
30
if (my_str[0] == 0x03) {
31
my_str += 1;
32
}
33
*/
34
}
35
36
}
37
38
ISR(USART1_RX_vect){
39
uart_gets(MAX_STR_LEN);
40
}
PS: Für my_str reserviere ich via malloc zum Programmstart 200 Bytes.
my_str = char_arr; // ist das falsch?
ja, vermutlich. Damit zeigt der pointer my_str bloss auf den String,
dabei wird überhaupt kein String kopiert und deine reserviere 200byte
sind für immer weg.
> Damit zeigt der pointer my_str bloss auf den String> dabei wird überhaupt kein String kopiert
Das ist eigentlich auch mein Ziel gewesen.
> und deine reserviere 200byte sind für immer weg.
das stimmt
> Versuch mal stattdessen:> memcpy ( my_str, &(char_arr[0]), len )
Das fürt komischerweise dazu, dass in my_str nichts mehr steht (getestet
mit printf), was ich mir überhaupt nicht erklären kann.
> > Damit zeigt der pointer my_str bloss auf den String> > dabei wird überhaupt kein String kopiert> Das ist eigentlich auch mein Ziel gewesen.
aber warum sollte man soetas machen, dann hast du 2 Variablen die auf
das gleiche zeigen. Beide sind global.
Warum nicht nur char char_arr[127]; verwenden?
Peter wrote:
>> > Damit zeigt der pointer my_str bloss auf den String>> > dabei wird überhaupt kein String kopiert>> Das ist eigentlich auch mein Ziel gewesen.> aber warum sollte man soetas machen, dann hast du 2 Variablen die auf> das gleiche zeigen. Beide sind global.> Warum nicht nur char char_arr[127]; verwenden?
Na weil vielleicht schon was neues eingelesen wird, während das alte
noch gebraucht wird :)
Du solltest zuerst einmal auf globale Variablen und statische
Funktionsvariablen verzichten. Beide raechen sich meist frueher oder
spaeter bitterlich.
Uebergib einfach das Array in das der String eingefuellt werden soll und
die maximale Laenge. Abfuellen, fertig und die Funktion hat keine
Seiteneffekte, ist Threadsafe, etc, pp.
In deinem konkreten Fall ist len beim ersten Aufruf nicht bewusst auf 0
initialisiert. Mit Glueck macht dein Compiler das fuer dich - je nach
Compiler aber auch nicht :-/
Kritisch an der Implementierung ist auch, dass Buffer max_size + 1 gross
sein muss, da du im Zweifelsfall die Terminierung auf my_str[len]
schreibst, wobei len = max_size ist. Hast du das beachtet?
Auch fraglich: Du liest ein Zeichen und pruefst erst dann, ob du noch
Platz im String hast. Ist der String schon voll, wirfst du das Zeichen
weg.
> Es muss aber gehen, siehe beweisfoto im anhang:
Ja so die graue Theorie :/
Ich wüsste auch nicht, was dagegen sprechen sollte.
>Du solltest zuerst einmal auf globale Variablen und statische>Funktionsvariablen verzichten. Beide raechen sich meist frueher oder>spaeter bitterlich.
Dass char_arr nicht global sein müsste gebe ich dir recht, my_str muss
aber.
>In deinem konkreten Fall ist len beim ersten Aufruf nicht bewusst auf 0>initialisiert. Mit Glueck macht dein Compiler das fuer dich - je nach>Compiler aber auch nicht :-/
Wieso mit Glück? Steht zumindest in der gcc Doku, dass es der Fall ist.
Kritisch an der Implementierung ist auch, dass Buffer max_size + 1 gross
sein muss, da du im Zweifelsfall die Terminierung auf my_str[len]
schreibst, wobei len = max_size ist. Hast du das beachtet?
> my_srt buffer ist auf jeden Fall größer.>Auch fraglich: Du liest ein Zeichen und pruefst erst dann, ob du noch>Platz im String hast. Ist der String schon voll, wirfst du das Zeichen>weg.
Oh ja, ist zwar nicht tötlich in meinem Fall, danke trotzdem. Werde
aufbessern.
Also, ich bin bis jetzt nicht wirklich zu einem Entschluss gekommen,
woran es liegt :(. Die STRINGS in AVR sind echt eine Sache für sich.
> >In deinem konkreten Fall ist len beim ersten Aufruf nicht bewusst auf 0> >initialisiert. Mit Glueck macht dein Compiler das fuer dich - je nach> >Compiler aber auch nicht :-/> Wieso mit Glück? Steht zumindest in der gcc Doku, dass es der Fall ist.
Sicher? bei den MS7 Compiler weiss ich das es nur in der Debug version
der fall ist, in der Release kann da alles drin stehen. Im ansi wird es
nicht definiert sein und ich würde mich bestimmt nicht darauf verlassen.
Uninitialisierte Variablen haben nachdem sie deklariert wurden einen
beliebigen Wert. Deswegen solltest du an der stelle auch ne
compilerwarnung bekommen.
∀ℜτ∪ℜ ΦΥΗΚ wrote:
>>Du solltest zuerst einmal auf globale Variablen und statische>>Funktionsvariablen verzichten. Beide raechen sich meist frueher oder>>spaeter bitterlich.> Dass char_arr nicht global sein müsste gebe ich dir recht, my_str muss> aber.
Nein, muss es nicht. Und ganz sicher musst du nicht aus einer
Hilfsfunktion darauf zugreifen.
>>In deinem konkreten Fall ist len beim ersten Aufruf nicht bewusst auf 0>>initialisiert. Mit Glueck macht dein Compiler das fuer dich - je nach>>Compiler aber auch nicht :-/> Wieso mit Glück? Steht zumindest in der gcc Doku, dass es der Fall ist.
Es gibt noch mehr Compiler als den gcc. Bricht es dir einen Zacken aus
der Krone, die Initialisierung zu machen?
> Kritisch an der Implementierung ist auch, dass Buffer max_size + 1 gross> sein muss, da du im Zweifelsfall die Terminierung auf my_str[len]> schreibst, wobei len = max_size ist. Hast du das beachtet?>> my_srt buffer ist auf jeden Fall größer.
Ah ja.
> Also, ich bin bis jetzt nicht wirklich zu einem Entschluss gekommen,> woran es liegt :(. Die STRINGS in AVR sind echt eine Sache für sich.
Nein, die sind ganz einfach. Du hast genuegend Tips bekommen, wo es
ueberall hakt - nun schreibe mal eine saubere Funktion, die auch einfach
testbar ist, dann geht das schon.
Wobei noch darauf geachtet werden muss, dass nicht während der
Verarbeitung von buffer_finished der enthaltene Zeiger durch den Empfang
des nächsten Textes umgebogen wird.
Gruß,
Roland
> In deinem konkreten Fall ist len beim ersten Aufruf nicht bewusst auf> 0 initialisiert. Mit Glueck macht dein Compiler das fuer dich - je> nach Compiler aber auch nicht :-/> Wieso mit Glück? Steht zumindest in der gcc Doku, dass es der Fall> ist.> Sicher? bei den MS7 Compiler weiss ich das es nur in der Debug version> der fall ist, in der Release kann da alles drin stehen.> Uninitialisierte Variablen haben nachdem sie deklariert wurden einen> beliebigen Wert. Deswegen solltest du an der stelle auch ne> compilerwarnung bekommen.
Ja was denn nun? Fragen wir doch den Gesetzgeber, und der sagt:
"If an object that has automatic storage duration is not initialized
explicitly, its value is indeterminate. If an object that has static
storage duration is not initialized explicitly, then:
— if it has pointer type, it is initialized to a null pointer;
— if it has arithmetic type, it is initialized to (positive or
unsigned) zero;
— if it is an aggregate, every member is initialized (recursively)
according to these rules;
— if it is a union, the first named member is initialized
(recursively) according to these rules."
len hat dank des /static/-Schlüsselworts "static storage duration" und
wird deswegen implizit mit 0 initialisiert.