Konvertieren des 32-Bit-Zweierkomplements in eine Dezimalzahl

Ich habe Daten von einem V9261F-Energiemesschip ( Link zum Datenblatt ), der Daten über einen UART an meinen Arduino-Mikrocontroller sendet. Wenn ich Register 0x0119 lese, lese ich die vom Chip gemessene Wirkleistung. Aber das Problem ist, dass dieses Feedback im 32-Bit-2er-Komplement ist und ich es nicht decodieren kann.

UART-Kommunikation

Ab dem 4. Byte im Stream befinden sich die Datenbytes, in denen die Messgrößen gespeichert werden (siehe Datenblatt S. 56 - 57). Für das Lesen von Register 0x0119 sollte dies in Datenbyte 10 - 11 - 12 und 13 (D1) jeweils 0x55, 0xE7, 0x0E und für Datenbyte 13 0x00 sein.

Das Feedback für die aktive Leistung aller Bytes zusammen, die ich habe, ist also 0x000EE755 -> 1 subtrahieren (für 1 Komplement) = 0x000EE754 -> invertieren, um eine Dezimalzahl zu werden = 0xFFF118AB (4293990571 dez). Diese wahnsinnig große Zahl soll aber nur eine Wirkleistung von 6,2 Watt darstellen.

Was mache ich falsch bei der Umwandlung vom 2er-Komplement in die Dezimalzahl? Wie soll das 6,2 Watt darstellen?

Antworten (3)

Ich glaube, Sie haben ein Missverständnis darüber, was "2er-Komplement" bedeutet. Eine positive Zweierkomplementzahl ist identisch mit einer positiven Binärzahl (das höchstwertige Bit muss Null sein). Für 8 Bit haben wir also 0x00 (Null) bis 0x7F (127). Zahlen kleiner als Null gehen von 0xFF (-1) bis 0x80 (-128). Um eine negative Zahl positiv zu machen, damit Sie sie als Minuszeichen vor einer positiven Zahl anzeigen können, können Sie das 2er-Komplement wie oben gezeigt berechnen. Beachten Sie den Sonderfall 0x80.

Mit 0x000EE754 haben Sie also eine positive Dezimalzahl von 976724. Es gibt einen Skalierungsfaktor zwischen diesem und 6,2 von 6,3478E-6.

Wahrscheinlich möchten Sie die Zahl in eine Gleitkommazahl umwandeln und die Berechnungen in Gleitkommazahlen durchführen. Es ist bereits im 32-Bit- Integer- Format mit Vorzeichen.

Das Zweierkomplement ist ein Format zur Beschreibung negativer Zahlen . Es gilt, wenn die Zahl negativ ist. Deine Berechnungen ergeben keinen Sinn. https://en.wikipedia.org/wiki/Two%27s_complement

Laut RTFM ist das Datenformat des Geräts 32-Bit-2er-Komplement-Little-Endian. Da Ihre MCU Little Endian ist (was bei AVR der Fall ist), müssen Sie nichts konvertieren. Speichern Sie das Ergebnis einfach in einer int32_t.

Das Datenformat für UART ist zuerst LSB und das Tool, das das Bild erstellt hat, scheint sich dessen bewusst zu sein. Wenn Sie also einige Daten wie 55e70e00 haben, dann sind das die tatsächlich gelesenen Daten. Da es sich um Little Endian handelt, entspricht es Hex 0x000ee755, Dezimal 976725. Dies ist der Wert, den Sie nach dem Lesen aus dem UART-Rx-Register erhalten sollten. Ob diese Zahl Sinn macht, keine Ahnung.

Das Zweierkomplement spielt keine Rolle, da die Zahl in diesem Fall positiv ist. Eine negative Zahl hätte eine binäre 1 im MSB.

OK danke für die Klärung. Ich werde prüfen, ob bei mehreren Lastmessungen kein Skalierungsfaktor verwendet wird. Eher seltsam, dass in den Datenblättern nichts vom Skalierungsfaktor vermerkt ist.
Die Aussage "Zweierkomplement ist ein Format zur Beschreibung negativer Zahlen." ist nicht genau. Das „Zweierkomplement“-Format beschreibt alle Zahlen, nicht nur negative. Es wird nur interessanter für negative Zahlen.
Vielmehr ist das Zweierkomplement eine Vorzeichenkonvention zur Darstellung ganzer Zahlen .

Die Art und Weise, wie ich über Zweierkomplementzahlen nachdenke, ist, darüber nachzudenken, was mit den unteren Bits einer Binärzahl beim Subtrahieren passiert. Wenn die unteren 4 Bits von x 0000 und die unteren 4 Bits von y 0001 sind, dann werden die unteren 4 Bits von xy 1111 sein, unabhängig davon, was die Bits darüber sind. Dies kann leicht für eine bestimmte Anzahl von Bits verallgemeinert werden (das Subtrahieren einer Zahl, deren untere Bits den Wert 1 ausdrücken, von einer Zahl, deren untere Bits den Wert 0 ausdrücken, ergibt eine Zahl, deren untere Bits alle gesetzt sind). Da dies für eine beliebige Anzahl von Bits funktioniert, kann es weiter verallgemeinert werden, um zu sagen, dass das Subtrahieren von Eins von Null eine Zahl mit einer unendlichen Anzahl von gesetzten Bits ergibt.

In der Praxis ist das Speichern einer unendlichen Anzahl von Bits nicht praktikabel. Für alle N>=1 haben jedoch alle Zahlen im Bereich -(2^N) bis (2^N)-1, jedoch alle Bits links vom N-ten Bit (nach links gezählt) den gleichen Wert wie das N-te Bit selbst und muss daher nicht gespeichert werden. Wenn Sie also 8-Bit-Zweierkomplementwerte verwenden, ist der Wert -1 nicht "wirklich" 10000000, sondern [unendlich viele Einsen]0000000, und der Wert 127 ist nicht 01111111, sondern [unendlich viele 0s]1111111. Wenn Sie die Dinge auf diese Weise betrachten, wird deutlich, wie Konvertierungen zwischen verschiedenen Größen von Werten funktionieren sollten.

Zum Beispiel würde das Konvertieren des 8-Bit-Werts in 16 Bit einfach dazu führen, dass ein Teil der unendlichen Zeichenfolge von 1s oder Nullen herauskopiert wird, während das Konvertieren eines 16-Bit-Werts im Bereich -128..127 in 8 Bit dazu führen würde, dass einige Duplikate gelöscht werden Bits. Wenn eine 16-Bit-Zahl außerhalb dieses Bereichs liegt, würde die Konvertierung in 8 Bits den Wert ergeben, der sich aus dem Herauskopieren des signifikantesten beibehaltenen Bits ergeben würde.

PS - Anwendung der Potenzsummenformel 1+2+4+8... ergibt -1. Das mag unsinnig erscheinen, passt aber perfekt zur Funktionsweise der Zweierkomplement-Mathematik. Wenn für jeden Wert von N alle unteren N Bits einer Zahl gesetzt sind, ergibt das Hinzufügen von 1 eine Zahl, deren untere N Bits alle gelöscht sind. Die einzige Zahl, für die die unteren N Bits für alle Werte von N frei sind, ist Null, und die einzige Zahl, die 0 ergibt, wenn 1 hinzugefügt wird, ist natürlich -1.