C++ Aus 2 Byte ein signed short machen (komplizierter)

fandre

Commander
Registriert
Nov. 2005
Beiträge
2.527
Hallo in die Runde,

mein Problem ist im Grunde, aus 2 Byte ein signed short zu machen, was an sich trivial zu lösen ist.

Die Herausforderung bei mir ist aber, das von 2 Byte nur 12 Bit genutzt werden und diese zusammen einen Messpunkt aus einer Versuchsreihe mit einem Wert von -1024 bis +3072 repräsentieren.

Nummerierung der Bits ist von 15-0 (Erste -> Letzte). Die Bits 15-12 enthalten irgendwelche Flags, die Bits 11-0 dann eben den Messwert als 12 Bit Wert.

Wie kann ich das nun in ein signed short umwandeln, welches einen entsprechenden Wert enthält?

Danke.
fande
 
Kenne mich in C++ leider nicht wirklich aus, allerdings sollte dies mit Shift Operatoren einfach umsetzbar sein...
 
Hallo!

Das ist gar nicht sooo schwierig:

Du hast 2 Byte (16 Bit) z.b.:

1111 0000 | 1111 0000

Dich interessieren die erstne 4 Bit nicht also verknüpfst du das ganze mit dem Operanten & und maskierst die Bits aus die du nicht brauchst:

1111 0000 | 1111 0000
&
0000 1111 | 1111 1111


Das Ergebnis daraus ist:
0000 0000 | 1111 0000

Schwupps fertig ! :-)
 
Kennst du die Bitwise-Operations?
http://www.fredosaurus.com/notes-cpp/expressions/bitops.html zB, oder halt nach dem Begriff googlen.

Damit ist es leicht möglich nacheinander die beiden byte in einen Datentyp zu bekommen.

Zb initialisierst du deinen signed short mit lauter nullen ("my_ushort = 0;"), kopierst die oberen interessanten 4 bits in deine variable mit etwas wie
my_ushort = byte_9_bis_12 & "00001111";

Anschließend machst du 8 bitshifts und holst die restlichen 8 interessanten bits in deunen my_ushort

Das sollte es eigtl schon sein?

In was für einen Format liegen deine bytes denn vor? als char vermute ich mal? Kannst ja casten, falls es deswegen probleme gibt
 
Code:
short value = input & 0xfff,
  flags = (input >> 12) & 0xf;
ungetestet, sollte theoretisch aber funktionieren. ;) hab bei bit-shifts manchmal nen kleinen denkfehler, aber du siehst ja zumindest wie es funktioniert.
 
Moinsen!

Da deine Variable ja schon 16 bit versuchs mal in etwa so:

signed short* tmp;
var = "dein datentyp"

tmp = reinterpret_cast<short*>(&var);
*tmp & (short)(4095);

Die 4095 sollte denke ich dem Bitmuster 0000 1111 1111 1111 entsprechen. Was da gemacht wird mit dem &-Operator kannst du z.B. hier:
http://www.willemer.de/informatik/cpp/sysprog.htm
nachlesen.

MfG
 
fandre,
was mich wundert ist dass der genannte Zahlenbereich sich nicht mit 12 Bit darstellen lässt.
meintest du eventuel: -1024 bis +3071 ?
Des weitern gilt hier dann ja(?): 0 müsste mit 1024 kodiert sein
Code:
short sw;
unsigned short input= ...;
sw = (input&0xfff)-1024;
 
Danke für die zahlreichen Antworten :-)

Bitoperatoren kenne ich aber ich hab es zu meiner Schande nicht hinbekommen, diese so einzusetzen. Werds gleich mal ausprobieren.
 
Legenbaer schrieb:
signed short* tmp;
var = "dein datentyp"

tmp = reinterpret_cast<short*>(&var);
*tmp & (short)(4095);
Ultrafieser Bug beim Dereferenzieren von tmp, wenn var nicht das gleiche Alignment wie short hat. Bestenfalls synthetisiert der Prozessor das, schlimmstenfalls steigt er mit ner Trap aus.

Zum eigentlichen Problem bleibt noch die Frage, wie dieser asymetrische Wertebereich binär repräsentiert ist (Komplement-Darstellung, Endianess). Die Kunst ist dann noch, sich nicht auf die binäre Repräsentation der eigenen Plattform zu verlassen.

Dass short 2 Byte hat, garantiert einem natürlich auch niemand. Hier kann z.B. mit Typselektoren aus Boost einen 2-Byte-Datentyp auswählen, sofern der Compiler einen anbietet.
 
7H3 N4C3R schrieb:
Zum eigentlichen Problem bleibt noch die Frage, wie dieser asymetrische Wertebereich binär repräsentiert ist (Komplement-Darstellung, Endianess).

Ja das stimmt leider :-/ War aber auch positiv überrascht, das mit meinem zweiten Versuch anscheinend die richtigen Ergebnisse rauskamen. Allerdings passen bei mir noch ein paar Sachen nicht und ich werde das morgen weiter testen.

Besten Dank für alle Antworten.
 
Code:
int16_t messwertwandeln (uint16_t wert) {
	wert &= 0x0fff;
	wert = (wert<<4);
	return (int16_t)wert - 1024;
}

So siehts zumindest in C für den AVR aus.
 
Zuletzt bearbeitet:
Zurück
Oben