Hallo,
Ich programmiere zur Zeit einen Atmega328p mit einem W5100 Wiznet Chip
für die Ethernet Schnittstelle. Diese beiden kommunizieren über eine SPI
Schnittstelle.
Die Implementierung hat uach wunderbar geklappt, Verbindungsaufbau /
-abbau, senden und empfangen klappt soweit.
Jetzt habe ich die Aufgabe bekommen, Daten nach einem bestimmten
Anwendungsprotokoll zu senden und zu empfangen:
Anfrage:
|NachrichtenLänge|NachrichtenTyp|anzSamples|16x bool Kanäle|
|uint32|uint16|uint32|uint16|
Antwort:
|NachrichtenLänge|NachrichtenTyp| chan sample anz|
|uint32|uint16|chan anz double|
Mein Empfangsbefehl fürs Ethernet:
ETH_recv(uint8_t *buf,uint16_t len);
Problem:
Ich habe probleme beim Einlesen der Request Anfrage.
ms_len = ((unsigned long) buf[0] << 24)
+ ((unsigned long) buf[1] << 16)
+ ((unsigned long) buf[2] << 8)
+ ((unsigned long) buf[3]);
uint16_t ms_typ = ((unsigned short) buf[4] << 8) +
((unsigned short) buf[5]);
Diese Methode habe ich versucht, aber erhalte ich keine
Nachvollziehbaren Daten.
Kann mir jemand helfen, wie ich dieses Problem am besten realisieren
kann oder wo mein Denkfehler liegt?
Grüße Cassidy
Cassidy schrieb:> Problem:> Ich habe probleme beim Einlesen der Request Anfrage.>> ms_len = ((unsigned long) buf[0] << 24)> + ((unsigned long) buf[1] << 16)> + ((unsigned long) buf[2] << 8)> + ((unsigned long) buf[3]);> uint16_t ms_typ = ((unsigned short) buf[4] << 8) +> ((unsigned short) buf[5]);
Dir ist aber schon klar, dass du hier allerhand Annahmen über die
Bytereihenfolge triffst?
zb das das höherwertigste Byte zuerst im Datenstrom kommt.
Das muss aber nicht so sein. Das hängt unter anderem auch davon ab, wie
der Sender die Daten auf den Weg bringt.
> Diese Methode habe ich versucht, aber erhalte ich keine> Nachvollziehbaren Daten.
Hast du dir schon mal die Einzelbytes angesehen?
Also: Noch ehe du sie zu größeren Einheiten zusammensetzt.
Cassidy schrieb:> Kann mir jemand helfen, wie ich dieses Problem am besten realisieren> kann
Bei solchen Problemen fängt man immer damit an, dass man sich zuerst auf
tifster Ebene erst mal die Bytes ansieht, die aus einer Verbindung
herauspurzeln und sich ansieht, ob die plausibel und richtig sein
können. Und zwar sieht man sich die Bytes so an, wie sie ankommen: Als
Bytes.
Stimmen die schon nicht, ist es sinnlos auf höheren Ebenen nach Fehlern
zu suchen.
Karl heinz Buchegger schrieb:> Dir ist aber schon klar, dass du hier allerhand Annahmen über die> Bytereihenfolge triffst?> zb das das höherwertigste Byte zuerst im Datenstrom kommt.>> Das muss aber nicht so sein. Das hängt unter anderem auch davon ab, wie> der Sender die Daten auf den Weg bringt.>>> Diese Methode habe ich versucht, aber erhalte ich keine>> Nachvollziehbaren Daten.>> Hast du dir schon mal die Einzelbytes angesehen?> Also: Noch ehe du sie zu größeren Einheiten zusammensetzt.
Also Ich hatte vorher ein Programm, welches Zeichenketten (mit
Trennzeichen) gesendet hat,
dort kamen die Zeichen geordnet an und es konnte alles richtig
interpretiert werden.
Deshalb gehe ich davon aus, dass meine Bytes die übertragen werden
ebenso geordnet ankommen, da ich meine Bytes ja als Chars übertrage.
Vielleicht habe ich auch gerade einen Denkfehler, oder übersehe etwas,
da ich in dem Bereich der Programmierung noch recht neu bin.
Könnte es sein, dass meine 0-Bytes den Datenstrom terminieren, da ich ja
über char-arrays sende? Und wenn ja, welche möglichkeit habe ich, das zu
unterbinden?
Grüße Cassidy
Cassidy schrieb:>> Hast du dir schon mal die Einzelbytes angesehen?>> Also: Noch ehe du sie zu größeren Einheiten zusammensetzt.>> Also Ich hatte vorher ein Programm, welches Zeichenketten (mit> Trennzeichen) gesendet hat,> dort kamen die Zeichen geordnet an und es konnte alles richtig> interpretiert werden.
Zeichenketten sind uninteresant für diesen konkreten Fall.
> Deshalb gehe ich davon aus, dass meine Bytes die übertragen werden> ebenso geordnet ankommen, da ich meine Bytes ja als Chars übertrage.
Das ist nicht die Frage.
Nehmen wir 2 Byte Zahlen.
zb die Zahl 23598
die interne Repräsentierung dieser Zahl ist 0x5C2E
sie bestehst aus 2 Byte.
Aber das bedeute nicht, dass diese Bytes in dieser Reihenfolge auch so
im Speicher liegen!
AUf einem Motorola Rechner liegen sie so im Speicher: 0x5C 0x2E
Auf einem Intel Rechner liegen sie so im Speicher: 0x2E 0x5C
Schickst du einfach die Bytes in der Reihenfolge, wie sie im Speicher
liegen weg, so erhält sie der Empfänger in einer der beiden
Reihenfolgen. Setzt er sie falsch zusammen, dann erhält er eine ganz
andere Zahl.
Bei 4 Bytes gibt es dann noch mehr Möglichkeiten
> Vielleicht habe ich auch gerade einen Denkfehler, oder übersehe etwas,> da ich in dem Bereich der Programmierung noch recht neu bin.
Schau dir endlich die Einzelbytes an, die dein Programm erhält. Und zwar
als Hex-Zahlen.
> Könnte es sein, dass meine 0-Bytes den Datenstrom terminieren, da ich ja> über char-arrays sende?
Wie sieht dein Sendecode aus?
Du musst strikt zwischen einer reinen binären Übertragung und einer
Übertragung in Textform unterscheiden. Das sind andere Funktionsaufrufe.
Bei einer reinen binären Übertragung gibt es auch dein 0-Byte welches
irgendwas terminieren könnte. Jedes Byte wird übertragen so wie es eben
ist.
Also was machst du jetzt eigentlich:
Übertragung in Textform
oder rein binäre Übertragung?
Die Übertragung ist rein binär.
Da ich jetzt die Paketgröße berechnet habe und vorgegeben habe, klappt
die Übertragung an sich auch. Allerdings stellt sich ein neues Problem.
Die Daten kopiere ich per memcpy() in den Buffer.
Allerdings werden die Werte "invertiert" gesendet, da ich ein
Little-Endian System habe.
Gibt es eine Möglichkeit dies zu ändern bzw. eine einheitliche
Reihenfolge unabhängig vom System zu haben.
Gruß Cassidy
Wenn Du über Ethernet sendest und ich mich nicht ganz irre, dann gibt es
dafür ein fixes Byte ordering genannt "Network byte ordering". Soweit
ich mich erinnere ist das für Ethernet Big Endian.
Little Endian Systeme konvertieren ihre Zahlen dann normalerweise in der
Netztzugriffs-API.
Es gibt normalerweise Funktionen
htons Host to Network Short
htonl Host to Network Long
ntohs Network to Host Short
ntohl Network to Host Long
gemeint ist jeweils: Die Byteorder auf/zu dem auf dem Hostsystem
vorliegenden Endianess umdrehen.
Ob du sie auf deinem System hast oder nicht (kommt mit den TCP/IP
Libararies) musst du abklären. Wenn nicht solltest du dir die
entsprechenden Funktionen machen und die dann benutzen anstatt deinen
Code an allen möglichen Stellen mit den entsprechenden händischen
Konvertierungen zu spicken.
Ach ja: Der Sendcode sollte ebenfalls sein Daten mit den entsprechenden
Aufrufen in die Standard-Network Byteorder umkonvertieren. Das vermeidet
zukünftige Probleme.