Hallo, ich habe ein 64 Bit Register mit verschiedenen Sachen drin. Und die einzelnen Werte werden manchmal über zwei Bytes verteilt, so dass das lsb bei Bit 19 beginnt und bei Bitt 23 endet, und das msb bei bit 15 beginnt und Richtung bit 8 geht. Hier nochmal zur verdeutlichung: Bit0--bit7: datenA bit8-bit15(MSB): datenB bit19(lsb)-bit23:datenB Ich will das nun zu einer Zahl zusammenfügen. Dazu shifte ich die Zahle aus bit19-23 nach rechts um 3 Stellen und die Zahl aus Bit8 - Bit15 um 5 Stellen nach links. Soweit richtig? Verknüpfe ich die nun durcch bitand?
Ich denke die richtige Schreibweise macht das deutlich. MSB links und LSB rechts.
uint64_t alles; uint8_t datenA = (uint8_t) alles & 0xFF; uint8_t datenB_lsb = (uint8_t) alles >> 8 & 0xFF; uint8_t datenB_msb = (uint8_t) alles >> 19 & 0x1F; uint16_t datenB = (uint16_t) datenB_msb << 8 | datenB_lsb; Wenn ich nichts durcheinander gebracht und alles richtig verstanden habe.
:
Bearbeitet durch User
Sieht auf den ersten Blick brauchbar aus. Probiere das doch einfach auf deinem PC mit einem Konsolen-Programm aus.
Danke, müsste so stimmen bin am schauen. Allerdings hast du lsb und msb vertauscht. MSB ist bei BIt 15 und lsb bei Bit 19.
bitshifter schrieb: > Danke, müsste so stimmen bin am schauen. Allerdings hast du lsb und msb > vertauscht. MSB ist bei BIt 15 und lsb bei Bit 19. Mit Excel sieht das Ganze übersichtlicher (und einfacher) aus...
:
Bearbeitet durch User
Dann habe ich ein Verständnisproblem. Also wenn meine Daten bei bit 19 im 3. Byte mit dem LSB anfangen und bei bit 8 (Byte 2) Richtung MSB Bit 15 weitergehen. Dann muss ich doch erstmal mein LSB an Bit 19 um 19 nach rechts verschieben und mit 0x1f verunden. Dann muss ich doch das byte 2 mit dem byte 1 bitor machen. Also wenn ich den Code von Top S. nehme:
1 | uint64_t alles; |
2 | uint8_t datenA = (uint8_t) alles & 0xFF; |
3 | |
4 | uint8_t datenB_lsb = (uint8_t) alles >> 8 & 0xFF; // das muss MSB sein |
5 | uint8_t datenB_msb = (uint8_t) alles >> 19 & 0x1F; //das muss doch mein datenB_lsb sein. |
6 | uint16_t datenB = (uint16_t) datenB_msb << 8 | datenB_lsb; |
bitshifter schrieb: > Dann habe ich ein Verständnisproblem. Nicht umsonst gibt es die Redewendung "Ein Bild sagt mehr als 1000 Worte." Zeichne es auf, bzw ändere die Grafik von Marc entsprechend deines Verständnisses ab. Außerdem wäre es gut die Endianess zu kennen.
:
Bearbeitet durch User
bitshifter schrieb: > Dann habe ich ein Verständnisproblem. Also wenn meine Daten bei bit 19 > im 3. Byte mit dem LSB anfangen und bei bit 8 (Byte 2) Richtung MSB Bit > 15 weitergehen. Dann muss ich doch erstmal mein LSB an Bit 19 um 19 nach > rechts verschieben und mit 0x1f verunden. Um es besser zu verstehen, mach doch mal Union daraus:
1 | union { |
2 | uint64_t alles; |
3 | uint8_t MyBytes[8]; |
4 | } unalles; |
Dann pick dir mal die 2 einzelnen Bytes heraus, mach daraus ein uint16_t und schiebe es 3 Mal nach rechts.
:
Bearbeitet durch User
Also ich möchte an DatenB herankommen, und der Aufbau ist wie in dem Bild. Der Erste Wert (LSB) meiner Daten beginnt bei Bit 19 und geht dann bis 23. Die Daten gehen bei Bit 8 weiter und enden mit dem MSB bei Bit 15. Somit wäre mein Datenframe wenn ich das richtig anordne beginnend mit dem LSB so: 19(LSB),20,21,22,23,8,9,10,11,12,13,14,15(MSB). somit wäre das doch die Lösung:
1 | uint64_t alles; |
2 | uint8_t datenA = alles & 0xFF; |
3 | |
4 | uint8_t datenB_lsb = alles >> 19 & 0x1F; |
5 | uint8_t datenB_msb = alles >> 8 & 0xFF; |
6 | uint16_t datenB = datenB_msb << 8 | datenB_lsb; |
Oder irre ich mich?
bitshifter schrieb: > Oder irre ich mich? Nein, du irrst dich nicht, du machst es nur zu kompliziert (für Compiler). Bei >> 8 macht der Compiler nur Byteswap, das ist schnell, aber bei >>19 ist der Compiler überfordert und muss entweder 2 Mal Byteswap machen und dann wieder >> 3 shiften oder gleich 19 Mal shiften. Bei Union pickt sich der Compiler gleich die richtigen Bytes und macht nur 3 Mal shift.
:
Bearbeitet durch User
Mach eine bitstruktur raus. Ja, ist nicht portabel, aber das lässt sich per Asserts absichern. Dann steht da einfach B=Feld.B; Und der Compiler kann es lösen, wie er will.
Marc V. schrieb: > Bei Union pickt sich der Compiler gleich die richtigen Bytes und > macht nur 3 Mal shift. Klingt intressant, wie soll das genau gehen? Ich lege ein Union mit einer Variable "uint64_t alles" an und dann? as schrieb: > Mach eine bitstruktur raus. Auch hier würde ich mich über ein Beispiel freuen. bitshifter schrieb: > 19(LSB),20,21,22,23,8,9,10,11,12,13,14,15(MSB). > somit wäre das doch die Lösung: >
1 | uint64_t alles; |
2 | > uint8_t datenA = alles & 0xFF; |
3 | >
|
4 | > uint8_t datenB_lsb = alles >> 19 & 0x1F; |
5 | > uint8_t datenB_msb = alles >> 8 & 0xFF; |
6 | > uint16_t datenB = datenB_msb << 8 | datenB_lsb; |
> Oder irre ich mich?
Noch eine Frage hier bezüglich. Wenn ich nicht nur eine Große Zahl habe,
sondern Byte-weise zahlen in Hexadezimalform habe. Dann muss ich
danteB_lsb nicht um 19, sondern es reicht wenn ich es um 3 Bitshifte
oder? Und DatenB_msb überhaupt nicht verschiebe. Wobei das
Zusammensetzen aber das geliche bleibt: uint16_t datenB = datenB_msb <<
8 | datenB_lsb;
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.