Forum: PC-Programmierung Visual c++ CLI Daten zusammen setzen aus chars


von Daniel H. (doomstar)


Lesenswert?

Hi

hab leider ein etwas komplizirteres Problem.

Versuche werte per rs232 an meine Pc zu senden.
Die Komunikation funktioniert einwandfrei das vorab.

Nun zum aufbau:

Auf meinem Controller nehm ich z.B. einen 16 int wert.

Ich teile den in 2 Byts mit einer Union.

Code:
//Umrechner 2Byte
union uni_2byte
{
  uint16_t  value;
  char    byte[2];
};

void sende()
{
char daten[5];
union uni_2byte wert;
wert.value = 5000;

daten[0] = 'b';
daten[1] = '1';
daten[2] = wert.byte[0];
daten[3] = wert.byte[1];
daten[4] = '#';

send_uart(daten);
}

das ganze versuche ich jetzt unter VC++ CLI wieder zusammen zu setzen.

union uni_2byte
{
unsigned short   value;
char   byte[2];
};

{...
unsigned short wert;

umrechner.byte[0] = command[2];
umrechner.byte[1] = command[3];
wert = umrechner.value;
...}

Jedoch ist mir aufgefallen das die Zeichen die der Controller raus gibt 
für die 2 Daten Bytes immer andere sind die VC++ Cali empfängt.

So ist mein wert immer ein Wenig unter dem gesendeten.

Hoffe mann kann mir so ein wenig helfen den der code auf Controller 
seite und in VC++ sind richtige Monster (Controller über 6000 Zeilen).

Wenn ich einfach nur text sende vom Controller aus z.b. ein "Hallo 
World" dann klappt das einwandfrei. Auch wenn ich nur ein Byte als wert 
sende klappt es wunderbar.

Mit freundlichem Gruß
Daniel

von Klaus W. (mfgkw)


Lesenswert?

Welcher Controller?

von Klaus W. (mfgkw)


Lesenswert?

send_uart(daten) sendet immer 5 Byte?

Oder bis zur abschließenden 0? Dann würde diese beim Senden fehlen.

von Klaus W. (mfgkw)


Lesenswert?

Kommen 'b' und '1' korrekt an?

von Klaus W. (mfgkw)


Lesenswert?

Du bist sicher, daß du 8 Bit überträgst (bei RS232 könnten es
auch 7 sein)?

von Daniel H. (doomstar)


Lesenswert?

Controller: Atmega 168

send_uart legt die daten in in FIFO der den stück für stück übertragen 
wird.

ja 'b' und '1' kommen korrekt an.

ja bin mir sicher dass er 8 Bit überträgt.

von Daniel H. (doomstar)


Lesenswert?

Noch etwas was zu anmerkung.

Es muss irgendwas mit dem Zeichensatz zu tun haben.

Wenn ich den Wert 8500 sende dan entspricht das
den Zeichen '4' und '!'.

Das kommt auch so im Programm an und wird richtig umgerechnet.

Was für ein Zeichensatz wird denn vom Controller aus benutzt?

von Karl H. (kbuchegg)


Lesenswert?

Lass dir die Bytes mal direkt als Hex-Zahlen ausgeben

von Thomas W. (thomas100)


Lesenswert?

Da du nicht schreibst, welchen Controller du benutzt. Könnte das Problem 
vielleicht bei Big endian, bzw. Little endian liegen?

Du schreibst, dass 8500 den Zeichen '4' und '!' entspricht. Das würde 
drauf hinweisen. (Wenn die Reihenfolge stimmt, wie du sie angibst)

Es sollte vollkommmen egal sein, welcher Zeichensatz benutzt wird. Du 
arbeitest hier ja direkt mit den Byte-Werten.

Gruß
Thomas

von Daniel H. (doomstar)


Lesenswert?

Hi Thomas

Hab doch geschrieben das es ein Atmega 168 ist.

Hab mal ein bischen weiter geschaut und herausgefunden das das Problem
auftritt sobald der wert einer Bytes über 127 ist. ab dann stimmen
auch die Zeichen nicht mehr überein die gesendet und empfangen werden.

Danke schon mal für die ganzen Antworten

von Thomas W. (thomas100)


Lesenswert?

Ups. Sorry. Überlesen.

Dass du andere Zeichen dargestellt bekommst mag schon sein. In deinem 
Fall ist es aber wichtig, welche Werte übertragen werden.

Siehst du denn in deinem VC++-Programm die Werte aus deinem char-array 
einzeln?
Guck dir mal die Werte im Debugger an.
Hast du irgend wo vielleicht signed und unsigned gemischt? Das könnte 
auch zu solchen Problemen führen. Grad wenn die Werte über 127 liegen

von Daniel H. (doomstar)


Lesenswert?

So glaube ich hab das jetzt.

Erstmal vielen dank an Thomas und Karl Heinz.


Ich hab die ganze Zeit die Werte als String aus dem Buffer
gelesen die dann in ein Char array gebackt und dann ausgewertet.

Das Problem dabei scheit zu sein das hier unterschiedliche
ASCII Sätze benutzt werden und so falsche werte herauskommen.

Wenn ich die Daten als Nackte Bytes lese und in dann in meine
Union packe dann funktioniert das ganze auch.

Jetzt muss ich halt schauen ab wann ich die "Roh Bytes"
als Daten interpretieren kann und ab Wann als ASCII zeichen.

Das heißt aber auch das alle Zeichen in der ASCII Tabelle über
127 beim anderen Teilnehmer eine andere bedeutung haben.

Werde mal schauen wie ich das löse.

Auf jeden fall hat sich für mich der Sonntag jetzt geloht. Mache
seit heute Mittag 2 Uhr daran rum und kann jetzt ganz in Ruhe ins
Bett gehen ;)

Vielen Dank nochmal und gute Nacht.

MFG
Daniel

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Daniel H. schrieb:
> Das heißt aber auch das alle Zeichen in der ASCII Tabelle über
> 127 beim anderen Teilnehmer eine andere bedeutung haben.

ASCII definiert nur die Zeichen für 0x00 bis 0x7F. Alles, was darüber 
liegt, hat mit ASCII nichts mehr zu tun.

Windows-Rechner nutzen üblicherweise den ANSI-Zeichensatz, das ist ein 
8-Bit-Zeichensatz, der in den ersten 128 Zeichen ASCII entspricht.

Dieser Zeichensatz wird auch als CP1252 bezeichnet, er entspricht auch 
weitestgehend ISO8859-1 oder Latin-1.

In einem Konsolenfenster ("Eingabeaufforderung", von vielen fälschlich 
"DOS"-Fenster genannt) nutzt Windows aber standardmäßig eine andere 
Zeichencodierung, und zwar die sogenannte DOS-Codierung, die als CP437 
bzw. CP850 bezeichnet wird. Auch hier entsprechen die ersten 128 Zeichen 
ASCII, aber die darüber liegenden Zeichen sind komplett anders codiert 
als bei ANSI.

Das Problem hier aber ist ein ganz anderes: Du überträgst Deine Werte 
nicht als Text, sondern in Form binärer Daten. Das Resultat ist dann 
kein sicher auswertbarer String, denn wenn der zu übertragende Wert z.B. 
8192 ist, wird als eines der beiden Bytes eine binäre Null übertragen. 
Das ist ein Stringendezeichen und hier ganz und gar nicht förderlich.

Du musst auf dem µC eine Textrepräsentation des Wertes erzeugen und 
die über die Schnittstelle übertragen.


> Wenn ich den Wert 8500 sende dan entspricht das
> den Zeichen '4' und '!'.

Hier musst Du die Zeichen '8', '5', '0' und '0' übertragen.

von Daniel H. (doomstar)


Lesenswert?

Hallo Rufus,

so edlich wieder gesund. Hab das nochmal probiert aber muss sagen da
hast du vollkommen recht. Es scheint nur zu gehen wenn ich die Zahlen
umwandele und sie Praktisch als Klartext sende. Das ist die einzigste 
möglichkeit die funktioniert.

Danke nochmal und viele Grüße

von Karl H. (kbuchegg)


Lesenswert?

Daniel H. schrieb:
> Hallo Rufus,
>
> so edlich wieder gesund. Hab das nochmal probiert aber muss sagen da
> hast du vollkommen recht. Es scheint nur zu gehen wenn ich die Zahlen
> umwandele und sie Praktisch als Klartext sende. Das ist die einzigste
> möglichkeit die funktioniert.

Na ja.
Das könnte man sicherlich auch hinkriegen
(der erste Schritt wäre der ganz dringende Hinweis, das man weder in C 
noch in C++ mit einem ordinären 'char' arbeitet, wenn man eingentlich 
Byte meint)

Aber dadurch, dass du grundsätzlich alles in Textform durch die Gegend 
schickst, sparst du dir viele Probleme. Angefangen von 
Synchronisierproblemen, Fehlerbehandlung, Byte-Sex und noch mehr.

Solange es keine zwingenden Laufzeitgründe gibt, fährt man in den 
meisten Fällen mit einer ASCII Text Übertragung meistens besser. 
Zumindest wenn man mehr als nur 1 Datenbyte übertragen muss und daher 
ein Protokoll benötigt.

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.