Forum: Mikrocontroller und Digitale Elektronik UART Übertragungsfehler


von Jörg (Gast)


Lesenswert?

Ich versuche gerade vom PC zum AtMega168 via FT232RL einen String zu 
schicken der dann in meiner Variablen landet welche dann auf dem Display 
zu sehen sein sollte .
Folgenden Codeschnipsel habe ich hier :

                                             const char *standby_text_Z1 
;
                                             char * text;
                 char * dest;
          char   zeichen;

          while (zeichen != '\r')
          {
            zeichen = uartGetChar();
            text = &zeichen;
            strcat(dest,text);
            text++;
            standby_text_Z1 = "";
            print (dest);
            standby_text_Z1 = dest;
          }

Demnach sollte solange ich im Hyperterminal nicht Enter drücke die 
Schleife weiterlaufen und die Zeichen aneinanderketten .
Ich meine es wäre ein Variablenproblem weil ich hier gerne mal was 
durcheinanderschmeiße .
Auf dem Hyperterminal erhalte ich allerdings nichts oder wenn ich hier 
und da was umschreibe nur hyroglyphen .
Die Übertragung hardware und einstellungsmäßig ist übrigens einwandfrei 
das habe ich schon getestet .

von Falk B. (falk)


Lesenswert?


von Karl H. (kbuchegg)


Lesenswert?

Jörg schrieb:

> Ich meine es wäre ein Variablenproblem weil ich hier gerne mal was
> durcheinanderschmeiße .

Das würde ich auch sagen.
Schlag deas C-Buch deiner Wahl auf und lies dir das Kapitel über 
Stringverarbeitung und Pointer durch.

Wenn du noch kein C-Buch hast, dann bestell dir eines und lies in der 
Zwischenzeit die Kurzzusammenfassung über String-Verarbeitung hier 
durch:

http://www.mikrocontroller.net/articles/FAQ#Wie_funktioniert_String-Verarbeitung_in_C.3F

von Jörg (Gast)


Lesenswert?

Naja zur meiner Verteidigung muss ich sagen nicht kann nicht sein zumal 
ich mir ja z.B. "text" auf dem Hyperterminal ausgeben lassen kann .
Naja jeder fängt mal ganz vorne an...

von Karl H. (kbuchegg)


Lesenswert?

Jörg schrieb:
> Naja zur meiner Verteidigung muss ich sagen nicht kann nicht sein zumal
> ich mir ja z.B. "text" auf dem Hyperterminal ausgeben lassen kann .

Das mag schon sein.
Aber ein String benötigt zuallererst eine Speicherfläche (zb ein Array) 
in der er sich breit machen kann.
Ein Pointer ist aber keine Speicherfläche. Ein Pointer kann auf eine 
solche zeigen, aber er ist es selber nicht. Wann immer du einen Pointer 
siehst, musst du dich sofort fragen: Wo ist der Speicher auf den er 
zeigt? Zeigt er überhaupt auf einen Speicher?


Das hier
1
          char * text;
2
          char   zeichen;
3
4
          text = &zeichen;
5
          strcat(dest,text);
verrät mir, dass dir der Unterschied zwischen einem einzelnen Zeichen 
und einem String nicht klar ist. Nur weil du einen Pointer auf einen 
char bildest, wird aus dem einzelnen Zeichen noch lange kein String.

von Jörg (Gast)


Lesenswert?

char standby_text_Z1 [21]  ;




char   zeichen;
while (zeichen != '\r')
{
zeichen = uartGetChar();
strcat(standby_text_Z1,&zeichen);
print (standby_text_Z1);
}


so ich bin mal so frei und stelle meine neue Version hier rein .
Funktioniert auch soweit ganz gut nur wenn ich beispielsweise Hallo vom 
PC schicke bekomme ich auf dem Display Hallo und dann eine einstellige 
Hyroglyphe zu sehen .Kann das sein das es sich dabei um das 
Abschlusszeichen vom Array handelt ?! .

von Maxx (Gast)


Lesenswert?

Nein. Die Hyroglyphe bekommst du, weil du &zeichen als string 
behandelst. Das ist es aber nicht. ein String wird immer mit einer 0 
('\0') abgeschlossen.

Was hinter &zeichen steht wird bei dir ebenfalls angehangen bis zur 
ersten 0.

von Karl H. (kbuchegg)


Lesenswert?

Jörg schrieb:
> char standby_text_Z1 [21]  ;
>
>
>
>
> char   zeichen;
> while (zeichen != '\r')
> {
> zeichen = uartGetChar();
> strcat(standby_text_Z1,&zeichen);
> print (standby_text_Z1);
> }
>
>
> so ich bin mal so frei und stelle meine neue Version hier rein .
> Funktioniert auch soweit ganz gut nur wenn ich beispielsweise Hallo vom
> PC schicke bekomme ich auf dem Display Hallo und dann eine einstellige
> Hyroglyphe zu sehen .Kann das sein das es sich dabei um das
> Abschlusszeichen vom Array handelt ?! .

Da gibt es mehrere Probleme.

strcat

  das erste Argument bezeichnet den String an den etwas angehängt wird.
  Die Betonung liegt auf String.
  In einem Array liegt genau dann ein String vor, wenn da 1 '\0' Zeichen
  drinn vorkommt, welches das Ende eines Strings markiert.

  Ein frisch erzeugtes Array hat undefinierten Inhalt. D.h. du kannst
  nicht davon ausgehen, dass du irgendetwas spezifisches da drinn
  enthalten ist. Mit Ausnahme von globalen Variablen bei denen
  garantiert ist, dass alles auf 0 steht.
  Aber funktionslokale Variablen haben irgendeinen Inhalt. Zufällig.
  Was gerade vorher dort im Speicher war.
  Wenn du also nicht den 'String' in standby_text_Z1 auf einen leeren
  String (also einen mit 0 Zeichen) initialisierst, tut es niemand
  anderer für dich.

  das zweite Argument zu strcat bezeichnet ebenfalls einen String.
  Ein einzelnes Zeichen ist aber kein String! Denn ein String benötigt
  immer ein '\0' Zeichen als Abschluss um anzuzeigen, wo der Text
  aufhört! Ein String, der aus einem Nutzzeichen besteht, hat also im
  Speicher mindestens die Länge 2. Ein Byte wird für das Zeichen
  gebraucht, das zweite für das '\0' Zeichen, welches erst den String
  ausmacht.


Nächstes Problem:
 char   zeichen;
 while (zeichen != '\r')

wie schon gesagt: funktionslokale Variablen haben irgendeinen zufälligen 
Inhalt, wenn die Funktion startet. Daher die Frage: Wenn die while 
Schleife das erste mal die Variable zeichen überprüft, welchen Inhalt 
hat dann 'zeichen'. Und die Antwort darauf lautet: Wir wissen es nicht. 
Es kann irgendwas sein. Zb könnte es zufälligerweise auch '\r' sein!
Die Auswirkungen auf deine Schleife kannst du dir hoffentlich ausmalen.

von Jörg (Gast)


Lesenswert?

Gut das habe ich soweit verstanden .Ich habe also das Zeichen als String 
deklariert,welches aber nicht wie es muss mit \0 terminiert wird .
Nur fällt mir einfach kein Workaround ein mit dem ich trotzdem nur ein 
Zeichen an den String hängen kann ?!
By the way gibt es eigentlich eine andere Möglichkeit ein Array zu 
leeren bis auf Feld für Feld zu leeren ?! .
Ich meine da gab es irgendwie einen Einzeiler also ohne schleife etc .

von Karl H. (kbuchegg)


Lesenswert?

> Gut das habe ich soweit verstanden .Ich habe also das Zeichen als String
> deklariert,

Nein hast du nicht.
Du hast es als char deklariert.
Ein char ist aber immer ein einzelnes Zeichen.
Damit du einen String mit 1 Nutzzeichen bilden kannst, brauchst du 
mindestens ein Array mit 2 Elementen: Eines fpr das Zeichen und eines 
für das '\0' Zeichen

> By the way gibt es eigentlich eine andere Möglichkeit ein Array zu
> leeren bis auf Feld für Feld zu leeren ?! .

Nein.

> Ich meine da gab es irgendwie einen Einzeiler also ohne schleife etc .

Brauchst du in dem Fall ja auch gar nicht.
Das erste '\0' zeichen zählt.
Wenn der String mit einem '\0' Zeichen beginnt, ist daher der String 
logischerweise leer. Was hinter diesem '\0' Zeichen sonst noch so im 
Speicher steht interessiert die str... Funktionen nicht.

1
viod foo()
2
{
3
  char standby_text_Z1 [21]  ;
4
  char zeichen[2];
5
6
  standby_text_Z1[0] = '\0';   // den String auf 0 Zeichen Länge setzen
7
  zeichen[1] = '\0';           // zeichen[0] wird später von getChar
8
                               // eingesetzt. Zusammen mit dieser '\0'
9
                               // ist das dann ein String
10
11
  zeichen[0] = uartGetChar();
12
  while (zeichen[0] != '\r')
13
  {
14
    strcat(standby_text_Z1,zeichen);
15
    print (standby_text_Z1);
16
    zeichen[0] = uartGetChar();
17
  }
18
}

von Jörg (Gast)


Lesenswert?

Ok danke soweit für die Erklärung .
char standby_text_Z1 [21]  ist im übrigen global deklariert .
Ich hatte sie nur so dazugeschrieben damit jeder weiß wie diese 
überhaupt deklariert ist .
mit der Variable Zeichen stimmt natürlich .Diese initialisiere ich am 
besten mal .
Ein größerers Problem für mich ist wirklich das Zeichen an den String 
anzuhängen  ?!

von Karl H. (kbuchegg)


Lesenswert?

Jörg schrieb:
> Ok danke soweit für die Erklärung .
> char standby_text_Z1 [21]  ist im übrigen global deklariert .
> Ich hatte sie nur so dazugeschrieben damit jeder weiß wie diese
> überhaupt deklariert ist .

OK.
Ist ok.
Wie du siehst, ist in manchen Fällen die Umgebung eines Codes wichtig. 
Das posten von irgendwelchen Auszügen ist daher oft keine gute Idee, 
weil wir dann wesentiche Teile nicht sehen können.

Was ist, wenn du die Einlesefunktionalität ein 2tes mal benutzt?

> mit der Variable Zeichen stimmt natürlich .Diese initialisiere ich am
> besten mal .
> Ein größerers Problem für mich ist wirklich das Zeichen an den String
> anzuhängen  ?!

Siehe vorhergehenden Post.

von Jörg (Gast)


Lesenswert?

Ok super schonmal vielen Dank für die ausführliche Hilfe :-).
Ich schäme mich :S .
Nur bei dieser Zeile müsste es doch

strcat(standby_text_Z1,&zeichen[0]);

heißen oder ?!

von Karl H. (kbuchegg)


Lesenswert?

Jörg schrieb:
> Ok super schonmal vielen Dank für die ausführliche Hilfe :-).
> Ich schäme mich :S .
> Nur bei dieser Zeile müsste es doch
>
> strcat(standby_text_Z1,&zeichen[0]);

Ich hatte beim Editieren das & vergessen rauszunehmen

  strcat( standby_text_Z1, zeichen );

Es gibt keinen Grund da jetzt grossmächtig mit [] und & rumzuwerfen. 
zeichen ist ein Array, genauso wie auch standby_text_Z1 ein Array ist. 
Und Arrays werden an Funktionen übergeben, indem die Startadresse (=die 
Adresse des ersten Arrayelements) übergeben wird.

von Falk B. (falk)


Lesenswert?

@Karl heinz Buchegger (kbuchegg) (Moderator)

>Es gibt keinen Grund da jetzt grossmächtig mit [] und & rumzuwerfen.
>zeichen ist ein Array,

Kein sonderlich kluger Name für ein Array.

>genauso wie auch standby_text_Z1 ein Array ist.
>Und Arrays werden an Funktionen übergeben, indem die Startadresse (=die
>Adresse des ersten Arrayelements) übergeben wird.

Dein Einsatz ist ja rührend, aber meinst du nicht, dass der Junge auch 
ein paar Sachen sich allein aneignen muss? Vor allem Grundlagen. Um es 
mal wie der KaLeun in "Das Boot" zu sagen "Da muss der Junge durch!". 
Sonst wird es nie ein Mann.

MfG
Falk

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.