mikrocontroller.net

Forum: PC-Programmierung HEX in signed Short umrechnen


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Michael Z. (buddhafragt)


Bewertung
0 lesenswert
nicht 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

von Walter S. (avatar)


Bewertung
1 lesenswert
nicht lesenswert
Michael Z. schrieb:
> 255

bist du da sicher?

von Michael Z. (buddhafragt)


Bewertung
0 lesenswert
nicht lesenswert
Walter S. schrieb:
> Michael Z. schrieb:
>> 255
>
> bist du da sicher?

Nein, 256.... !! Tippfehler...... ;-)

von BS (Gast)


Bewertung
0 lesenswert
nicht 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.

von Oliver S. (oliverso)


Bewertung
0 lesenswert
nicht 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

: Bearbeitet durch User
von GeraldB (Gast)


Bewertung
0 lesenswert
nicht lesenswert
BS schrieb:
> Result = (~Result) - 1.

Zweierkomplement ist aber
Result = (~Result) + 1.

von c-hater (Gast)


Bewertung
0 lesenswert
nicht 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...

von Michael Z. (buddhafragt)


Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für eure Hilfe,
ich habe es jetzt so gelöst:

(((B1+(B0*256))-65536)+1)

von Oliver S. (oliverso)


Bewertung
0 lesenswert
nicht 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

: Bearbeitet durch User
von Michael Z. (buddhafragt)


Bewertung
0 lesenswert
nicht lesenswert
Oliver S. schrieb:
> Warum? Was genau bezweckst du damit?

Umrechnung ins Zweierkomplement!

von zitter_ned_aso (Gast)


Bewertung
0 lesenswert
nicht lesenswert
steht "B" in MSB / LSB eigentlich nicht für "Bit"?

von Oliver S. (oliverso)


Bewertung
0 lesenswert
nicht lesenswert
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

von Klaus S. (skibby)


Bewertung
0 lesenswert
nicht lesenswert
(int16_t)((MSB<<8)+LSB) sollte es auch tun (falls LSB und MSB jeweils 
uint8_t sind)

von Michael Z. (buddhafragt)


Bewertung
0 lesenswert
nicht 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!

von NichtWichtig (Gast)


Bewertung
0 lesenswert
nicht lesenswert
zitter_ned_aso schrieb:
> steht "B" in MSB / LSB eigentlich nicht für "Bit"?

Jupp

Daumen hoch

von Oliver S. (oliverso)


Bewertung
0 lesenswert
nicht 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

: Bearbeitet durch User
von Michael Z. (buddhafragt)


Bewertung
0 lesenswert
nicht lesenswert
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!

von Oliver S. (oliverso)


Bewertung
0 lesenswert
nicht 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

von Niklas G. (erlkoenig) Benutzerseite


Bewertung
0 lesenswert
nicht 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:
#include <cstdint>
#include <iostream>
#include <uSer.hh>

// Nachricht definieren
struct CanMessage1 {
  USER_STRUCT (CanMessage1, uSer::AttrNone)

  // Felder der Nachricht
  std::int16_t a, b;
  std::uint8_t c;
  std::uint16_t d;
  std::uint8_t e;
  
  // Felder bekannt machen
  USER_ENUM_MEM (a, b, c, d, e)
};

int main () {
  
  // Reserviere Bytes für Nachricht
  std::uint8_t raw [8];
  
  // Simuliere Absenden einer Nachricht
  {
    // Nachricht anlegen
    CanMessage1 msg { -42, 37, 1, 7777, 3 };
    
    // Nachricht in einzelne Bytes zerlegen
    uSer::serialize (raw, msg);
  }
  
  // Bytes ausgeben
  for (std::uint8_t r : raw)
    std::cout << std::hex << std::setw(2) << "0x" << int { r } << ", ";
  std::cout << std::endl;
  
  // Simuliere Empfang einer Nachricht
  {
    // Nachricht anlegen
    CanMessage1 msg;
    
    // Einzelne Bytes in Nachricht umwandeln
    uSer::deserialize (raw, msg);
    
    // Nachricht anzeigen
    std::cout << std::dec << "CanMessage1 { " << msg.a << ", " << msg.b << ", " << int { msg.c } << ", " << msg.d << ", " << int { msg.e } << " }" << std::endl;
  }
}

Beispiel-Ausgabe:
0xd6, 0xff, 0x25, 0x0, 0x1, 0x61, 0x1e, 0x3, 
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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.