int-Wert als WORD schreiben



  • habe ein unsigned char array:

    unsigned char send[32];
    

    Ich habe ein Messgerät, an das 32 Byte gesendet werden sollen. An Byte 15 und 16 (also send[14] und send[15]) soll ein Integer Wert 80 als WORD geschrieben werden.
    Wie mach ich das?



  • Edit: Lösung gelöscht, stattdessen Gegenfrage:

    Wie liegt ein WORD denn im Speicher? Wie liegen die Arrayelemente im Speicher? Lässt sich da ein Zusammenhang herstellen?



  • rudpower schrieb:

    Ich habe ein Messgerät, an das 32 Byte gesendet werden sollen. An Byte 15 und 16 (also send[14] und send[15]) soll ein Integer Wert 80 als WORD geschrieben werden. Wie mach ich das?

    - In die Dokumentation des Messgerätes gucken, ob da etwas über die Byte-Reihenfolge drinsteht
    - Im Notfall beim Hersteller anrufen oder "little endian" annehmen/probieren.
    - Hi/Low-Bytes per binäre Operationen (>>, &) bestimmen und in das Array schreiben.


  • Mod

    Im Prinzip könntest du den Integer Wert an die Adresse schreibst, also:

    *(reinterpret_cast<int*>(send+14))=dein_integer;
    

    ABER: Das funktioniert nur, wenn

    1. sizeof(int)==2. Dies ist auf den wenigsten Systemen der Fall. Meinst du vielleicht einen short?
    2. Die Endianess deines Systems muss mit der erwarteten Endianess zusammenpassen.

    Die sicherere Methode ist es, selber zu rechnen. Dazu musst du aber wie Größe eines chars und die erwartete Endianess kennen. Ich gehe hier mal von 8 Bit pro char aus (kann man im limits Header prüfen) und Little-Endianess(steht in der Beschreibung deines Messgerätes):

    send[14] = (dein_integer >> 0) & 0xFF; // Wir fangen bei Verschiebung 0 an und gehen dann zu größeren Werten -> Little-Endianess
    send[15] = (dein_integer >> 8) & 0xFF; // Die magische Zahl 8 ist die Anzahl der Bits in einem char. Die magische Zahl 0xFF ist 2 hoch 8.
    

    Entsprechend anzupassen für andere Größen von char, für andere Endianess und für größere Datentypen.

    Dies speichert natürlich nur die letzten 16 Bit deines ints. Da, wie schon gesagt, int gewöhnlicherweise größer ist als 16 Bit, wird da potentiell etwas abgeschnitten.



  • Murmelmurmel... da ist mein didaktischer Auftrag dahin o.O



  • Big Endian ist es, also das höherwertige Byte steht an der niedrigeren Adresse


  • Mod

    rudpower schrieb:

    Big Endian ist es, also das höherwertige Byte steht an der niedrigeren Adresse

    Dann dürftest du den Rest doch hinbekommen. Oder ist noch etwas unklar, zum Beispiel wie das mit den Bitoperationen >> und & funktioniert?



  • ja hab das mit dem WORD noch nicht verstanden und den Verschiebeoperatoren. Beim Auslesen der Messwerte hatte ich auch das Problem. Das Gerät gab mir in ein unsigned char rec[128], an rec[20] den Wert 8(0x08) und an rec[21] den Wert 60(0x3C). Ich weiss von anderer Quelle, dass ich das höherwertige Byte, hier rec[20], nehmen muss. Dieses muss mit 256 multipliziert werden und mit dem anderen Byte addiert werden. Dann erhält man den Messwert 2108. Um den realen Messwert dann zu bekommen muss noch mit 100 dividiert werden, also 21,08.
    Ich weiss das man auch (rec[50]<<8)+rec[51] schreiben kann statt das mit 256 zu multiplizieren. Ich weiss auch das WORD sich aus den 2 Bytes zusammensetzt und der Verschiebeoperator alle Bits in die jeweilige Richtung verschiebt. Nur warum und wie das geschieht ist mir nicht ganz klar. Vielleicht hilft mir eine bitweise Erklärung um das zu verstehen.



  • siehe http://de.wikipedia.org/wiki/Stellenwertsystem

    Wenn Du eine Zahl mit 100 multiplizierst und dir die Dezimaldarstellunganguckst, wandern die Ziffern auch zwei Stellen weiter und es wird rechts mit Nullen aufgefüllt:

    123 * 100
       ///     |/
    = 12300    |
         ^^----+
    

    Das funktioniert nun genauso gut im Binärsystem, wobei 256 dort eine 1 mit 8 Nullen sind.



  • so recht ist es mirnicht klar. Um den Messwert 2108 darzustellen hat man 2 Byte genommen, da 1Byte also 8 Bit nur 256 Zustände hat und bei 2 Byte 65536 Zustände, richtig? Nehm ich jetzt die Zahl 8 und 60 und schreib sie als binär hab ich:
    00001000 00111100 -> das sind dann 2108, also mein Messwert. Das ist klar. Nur wie ich das jetzt in meine Form bring mit dem Verschiebeoperator will mir nicht in den Kopf.
    Bei dem Integer 80 den ich in das Messgerät als byte schreiben soll passt doch der Wert 80 schon in das 1. Byte also steht doch da:
    00000000 01010000
    da kann ich doch senden:
    send[14]=0;
    send[15]=80;
    oder:
    send[14]=0x0;
    send[15]=0x50;
    welches weiss ich nicht, aber das müsste ja egal sein


  • Mod

    Das ist beides das gleiche. 0x50 == 80.



  • also wär das mit

    send[14]=0x0;
    send[15]=0x50;
    

    richtig? Damit würd ich ja den int Wert 80 als WORD in das Array schreiben?

    Wär sehr dankbar wenn mir jmd nochmal erklärt wie das mit dem bitweisen Schieben mit meinem Beispiel funktionieren würde. Also

    rec[20] den Wert 8(0x08) und an rec[21] den Wert 60(0x3C)

    ich hätt doch dann 00001000 00111100. Dann schieb ich 8 Byte nach links also wird aus dem linken Byte 10000000 also 2048 und ich addier das rechte Byte dazu. Ich versteh zwar wie man das macht aber warum und der Zusammenhang fehlt mir.



  • Ich verstehe nicht, wo Dein Problem liegt.

    Lies Dir nochmal richtig den Wikipedia-Artikel zum Stellenwertsystem durch und rechne es einfach nach / leite es selbst her.

    Tipp: Vergiss nicht die "integral promotion". Wenn Du mit Ganzzahlen rechnest (+,-,*,/,%,<<,>>,&,|,...), werden die Werte von Typen "kleiner" als int -- also char und short -- erst zu int-Werten konvertiert. Und ints haben mindestens 16 Bits. Der Ausdruck a<<5, wobei a vom Typ unsigned char ist, ist also vom Typ int (höchstwahrscheinlich) oder unsigned int (wenn int nicht alle Werte von unsigned char darstellen kann, was dann der Fall ist, wenn sizeof(char)==sizeof(int) gilt).

    Streng Dich doch mal n bissel an!



  • das mit dem Stellenwertsystem kannte ich schon denn ich hab ja keine Probleme damit hex, bin umzurechnen. Aber ich denke beim durchgehen des ersten Beispiels ist es mir klar geworden. Da ja die 0x08 das höhere Byte ist und wir beim WORD 16 Byte statt 8 Byte haben muss es 8 STellen nach links verschoben werden. und das LowByte wird wie beim Stellenwertsystem einfach addiert.


Log in to reply