Hallo, ich habe ein Problem, an dem ich mir gerade die Zähne ausbeisse: Ich bekomme von einem CAN Bus 2 Bytes in Hex, die ich in ein signed Short umwandeln muß. Mit unsigned ist das simpel: LSB+(MSB*255) Mit signed bekomme ich es nicht hin. Gruß, Michael
Walter S. schrieb: > Michael Z. schrieb: >> 255 > > bist du da sicher? Nein, 256.... !! Tippfehler...... ;-)
Das höchste Bit zeigt das Vorzeichen an. Im Prinzip wie geschrieben umrechnen: Result = LSB +( MSB << 8) Wenn das Ergebnis > 32767 ist, Zweierkomplement berechnen: Result = (~Result) - 1. Mit int16 reicht schon Int16 Result = (int16) (LSB + (MSB << 8), das wird dann schon richtig interpretiert.
BS schrieb: > Result = LSB +( MSB << 8) > Wenn das Ergebnis > 32767 ist, Zweierkomplement berechnen: > Result = (~Result) - 1. Wenn das, was über den Bus angeliefert wird, schon ein signed short ist (wovon ich ausgehen), dann muß nichts mehr umgerechnet werden. Die beiden (unsigned) bytes in der richtigen Reihenfolge in einen usigned short schieben, das Ergebnis nach signed short casten, fertig. Oliver
:
Bearbeitet durch User
Oliver S. schrieb: > Wenn das, was über den Bus angeliefert wird, schon ein signed short ist > (wovon ich ausgehen), dann muß nichts mehr umgerechnet werden. Die > beiden (unsigned) bytes in der richtigen Reihenfolge in einen usigned > short schieben, das Ergebnis nach signed short casten, fertig. Vorsichtig. Das stimmt so nur, wenn Quell- und Zielsystem gleichermaßen zur Darstellung von negativen Zahlen das Zweierkomplement verwenden. Allerdings: wenn beide Systeme aus der Nach-Steinzeit stammen, kann man davon ausgehen, das es so ist... Aber nach der reinen Lehre muss man halt davon ausgehen, das es nicht so ist. Die C-Fetischisten fahren voll auf solchen historischen Dreck ab, genauso wie auf Bytes (ähm: chars), die keine 8 Bit haben usw. Das kommt davon, wenn eine Sprache viel zu alt ist und niemals sinnvoll weiterentwickelt wurde, was auch heißen muss: alte Zöpfe einfach mal irgendwann abzuschneiden. Hatte wohl niemand Lust, die Specs umzuschreiben, denn schon diese beiden kleinen Sachen zu "normalisieren" (sprich: an die objektive Realität anzupassen) rüttelt gehörig an den Grundfesten von C... Und es gäbe da noch einiges mehr zu "normalisieren"... Aber ich sehe das inzwischen gelassen. Auf Dauer wird die Evolution ihr Werk tun. Entweder C passt sich an oder es wird irgendwann verschwinden. So einfach ist das. Inzwischen (schon eine ganze Weile...) gibt es ja Sprachen mit modernen Konzepten, die all das können, was C kann, aber den ganzen historischen Ballast von C nicht mitschleppen müssen... Nur die riesige Codebasis rettet C bisher. Dank der vielen C&Pler, die sich "Programmierer" nennen...
Vielen Dank für eure Hilfe, ich habe es jetzt so gelöst: (((B1+(B0*256))-65536)+1)
c-hater schrieb: > Aber nach der reinen Lehre muss man halt davon ausgehen, das es nicht so > ist. > > Die C-Fetischisten fahren voll auf solchen historischen Dreck ab, > genauso wie auf Bytes (ähm: chars), die keine 8 Bit haben usw. > > Das kommt davon, wenn eine Sprache viel zu alt ist und niemals > sinnvoll weiterentwickelt wurde, was auch heißen muss: alte Zöpfe > einfach mal irgendwann abzuschneiden. Oh mann... Ja, du hast theoretisch recht, aber gib es zu: Auch dir ist noch nie ein System unter die Finger gekommen, welches was anders als Zweierkomplement zur Dastellung negativer Zahlen benutzt hat. Schon gar nicht eines, das so modern ist, daß es CAN-Bus hat (also weniger als 30-40 Jahr alt). Insofern ist das einfach Geschwafel. Michael Z. schrieb: > ich habe es jetzt so gelöst: > > (((B1+(B0*256))-65536)+1) Warum? Was genau bezweckst du damit? Oliver
:
Bearbeitet durch User
Michael Z. schrieb: > Umrechnung ins Zweierkomplement! Von was? Damit das nicht in hundert Beiträge mit je einer Zeile ausartet: Was ist das für ein Datentyp, der dir im zwei Bytes aufgeteilt über den Can-Bus angeliefert wird? Oliver
(int16_t)((MSB<<8)+LSB) sollte es auch tun (falls LSB und MSB jeweils uint8_t sind)
Oliver S. schrieb: > Michael Z. schrieb: >> Umrechnung ins Zweierkomplement! > > Von was? > Damit das nicht in hundert Beiträge mit je einer Zeile ausartet: > > Was ist das für ein Datentyp, der dir im zwei Bytes aufgeteilt über den > Can-Bus angeliefert wird? > > Oliver Nun, die definition des CAN Bus Protokolls ist 8 x ein Byte, nicht wahr? Wenn also ein Word übermittelt werden soll, geschieht das über 2 Bytes. Die definition, ob es signed oder unsigned ist, ist hier noch nicht festgelegt, sondern muß bei der Zusammenführung der beiden Bytes dann berücksichtigt werden. Der Datentyp ist signed Word!
Michael Z. schrieb: > Die definition, ob es signed oder unsigned ist, ist hier noch nicht > festgelegt, sondern muß bei der Zusammenführung der beiden Bytes dann > berücksichtigt werden. > Der Datentyp ist signed Word! Du hast es nicht verstanden... Natürlich sind die Bytes auf dem Bus einfach nur 8 bit. Aber die Definition, was diese Bits bedeuten, wird im Absender definiert. Der zerlegt einen 16-Bit Datentyp in zwei Bytes, und was das für ein Datentyp ist, und wie der den zerlegt, musst du in dessen Spec nachschauen. Und wie jetzt schon mehrfach geschrieben wurde, wäre alles andere als ein schlichtes aneinanderhängen der beiden Bytes im Empfänger äusserst seltsam. Ein manuelles Umrechnen von 16 bit unsigned in ein 16-bit-signed-Zweierkomplement ist dazu eh völlig sinnlos. Entweder interpretierst du die 16 Bit des Ausgangswertes als 16 bit unsigned, dann gibt es per Definition keine negativen Zahlen, oder du interpretierst die 16 bit des Ausgangswertes als signed, dann sind die schon im Zweierkomplement. Oliver
:
Bearbeitet durch User
Oliver S. schrieb: > Aber die Definition, was diese Bits bedeuten, wird im Absender > definiert. Der zerlegt einen 16-Bit Datentyp in zwei Bytes, und was das > für ein Datentyp ist, und wie der den zerlegt, musst du in dessen Spec > nachschauen. Ja, da habe ich dich wohl nicht richtig verstanden. Der Absender hat es als signed Word definiert!
Oliver S. schrieb: > Wenn das, was über den Bus angeliefert wird, schon ein signed short ist > (wovon ich ausgehen), dann muß nichts mehr umgerechnet werden. Die > beiden (unsigned) bytes in der richtigen Reihenfolge in einen usigned > short schieben, das Ergebnis nach signed short casten, fertig. Klaus S. schrieb: > (int16_t)((MSB<<8)+LSB) sollte es auch tun (falls LSB und MSB jeweils > uint8_t sind) Oliver
Genau für solche Fälle habe ich mein µSer-Bibliothek geschrieben, welche das Abbilden von beliebigen Binärformaten auf Sprach-Typen ermöglicht. Man definiert erst die Nachricht als "annotiertes struct" bestehend aus den einzelnen Datenfeldern und kann diese dann in einzelne Bytes umwandeln, und umgekehrt. Ein Beispiel:
1 | #include <cstdint> |
2 | #include <iostream> |
3 | #include <uSer.hh> |
4 | |
5 | // Nachricht definieren
|
6 | struct CanMessage1 { |
7 | USER_STRUCT (CanMessage1, uSer::AttrNone) |
8 | |
9 | // Felder der Nachricht
|
10 | std::int16_t a, b; |
11 | std::uint8_t c; |
12 | std::uint16_t d; |
13 | std::uint8_t e; |
14 | |
15 | // Felder bekannt machen
|
16 | USER_ENUM_MEM (a, b, c, d, e) |
17 | };
|
18 | |
19 | int main () { |
20 | |
21 | // Reserviere Bytes für Nachricht
|
22 | std::uint8_t raw [8]; |
23 | |
24 | // Simuliere Absenden einer Nachricht
|
25 | {
|
26 | // Nachricht anlegen
|
27 | CanMessage1 msg { -42, 37, 1, 7777, 3 }; |
28 | |
29 | // Nachricht in einzelne Bytes zerlegen
|
30 | uSer::serialize (raw, msg); |
31 | }
|
32 | |
33 | // Bytes ausgeben
|
34 | for (std::uint8_t r : raw) |
35 | std::cout << std::hex << std::setw(2) << "0x" << int { r } << ", "; |
36 | std::cout << std::endl; |
37 | |
38 | // Simuliere Empfang einer Nachricht
|
39 | {
|
40 | // Nachricht anlegen
|
41 | CanMessage1 msg; |
42 | |
43 | // Einzelne Bytes in Nachricht umwandeln
|
44 | uSer::deserialize (raw, msg); |
45 | |
46 | // Nachricht anzeigen
|
47 | std::cout << std::dec << "CanMessage1 { " << msg.a << ", " << msg.b << ", " << int { msg.c } << ", " << msg.d << ", " << int { msg.e } << " }" << std::endl; |
48 | }
|
49 | }
|
Beispiel-Ausgabe:
1 | 0xd6, 0xff, 0x25, 0x0, 0x1, 0x61, 0x1e, 0x3, |
2 | CanMessage1 { -42, 37, 1, 7777, 3 } |
Es ist zu sehen wie der negative Integer in die Bytes 0xD6 0xFF zerlegt und dann wieder zurück zu -42 zusammen gebaut wird. Die Bibliothek kann auch exotischere Vorzeichen-Formate (2er-Komplement, 1er-Komplement und Sign-And-Magnitude) und Byte-Reihenfolgen (Big Endian, Little Endian, PDP und beliebige eigene). Die Bibliothek macht keine Annahmen über die Eigenschaften der Host-Plattform und setzt nur das voraus was im Sprachstandard garantiert ist; daher hat der Code auf allen Plattformen exakt das gleiche Verhalten und ist somit auch auf Architekturen mit exotischen Integer-Typen portabel, solange der Compiler Standard-Konform ist. Die Verwendung auf Mikrocontrollern ist ohne Overhead möglich. Die Bibliothek: https://github.com/Erlkoenig90/uSer Mehr zum Thema: Serialisierung
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.