HEX in signed Short umrechnen

OP #6183084
Lesenswert?

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
Gast #6183169
Lesenswert?

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.
#6183376
Lesenswert?

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
Gast #6183952
Lesenswert?

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...
#6185319
Lesenswert?

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
OP #6185561
Lesenswert?

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!
#6185719
Lesenswert?

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
#6185874
Lesenswert?

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
Persönliche Seite #6185894
Lesenswert?

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren