Forum: Compiler & IDEs 24 bit signed in einer 32bit variablen?


von simon (Gast)


Angehängte Dateien:

Lesenswert?

oh man, da hab ich mir echt nichts einfaches Ausgesucht.

Ich lese per SPI 1 byte weise 32 bit aus.

jedoch ist das eine 24 Bit variable mit Bit 23 als sign Bit

Hinzu kommt das mir nicht ganz klar ist wo Microchip XC18 das sign bit 
haben will da gab es doch auch eine Besonderheit.

Mal ein Beispiel:

Wenn ich hier also -8 als Zahl darstellen will
1
0000 XXXX S0000000000000000001000
2
(X = egal, S = Sign Bit)
3
Bit 23 = 1 bedeutet dann wohl negative Zahl.
4
0000 XXXX 10000000000000000001000

Nur wie kann ich diese Zahl dann verwenden z.b. in einer 32 Bit signed 
variable?
Einfach ein left shift? wird nicht gehen da ziehe ich ja die hintere 1 
(entsporicht 8) auf eine ganz andere Stelle.

von Martin B. (martin_b35)


Lesenswert?

Setze einfach die höchsten 8 Bit ([31:24]) gleich Bit 23 (also dem MSB 
von [23:0]).

Dank Zweierkomplement klappt das :)

Grüße, Martin

von simon (Gast)


Lesenswert?

Ich checks nicht.

Sowas wie mit & und einer maske abfragen und zuweisen?

von holger (Gast)


Lesenswert?

>Ich checks nicht.

Viele andere auch nicht. Macht es euch doch nicht so schwer.
Betrachte erstmal jedes Byte was per SPI übertragen wird als
unsigned. SPI kennt kein Vorzeichen. Dann schiebt man den
ganzen Kram unsigned an die richtigen Stellen:

uint32_t temp =  ((uint32_t)MSB << 16) + ((uint32_t)MLSB << 8) + LSB;

So, jetzt stehen die Bytes an der richtigen Stelle in temp.
Dann musst du abfragen ob die Zahl negativ ist. Das Vorzeichen
steht in MSB D7. Wenn 1 dann musst du die oberen 8 Bits von temp
alle auf 1 setzen. Wenn Null machst du gar nichts.

if(MSB & 0x80) temp |= 0xFF000000;

Jetzt noch einen beherzten cast auf signed:

int32_t temp2 = (int32_t)temp;

Fertig.


Oder ein union nehmen und darin rumpfuschen.

von Lui S. (lute)


Lesenswert?

Moin,

variable<<=8 und dann variable /= 256.
Durch das shiften steht dein Wert ganz links und "hinten" hast du mit 
Nullen aufgefüllt. Beim Teilen durch 256 bleibt das Vorzeichen erhalten.

Gruß, Lui

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Teilen ist ne ganz schlechte Idee

von Ralf G. (ralg)


Lesenswert?

simon schrieb:
> Mal ein Beispiel:
>
> Wenn ich hier also -8 als Zahl darstellen will
1
0000 XXXX S0000000000000000001000
2
 (X = egal, S = Sign Bit)
3
 Bit 23 = 1 bedeutet dann wohl negative Zahl.
4
0000 XXXX 10000000000000000001000

Martin B. schrieb:
> Setze einfach die höchsten 8 Bit ([31:24]) gleich Bit 23 (also dem MSB
> von [23:0]).
>
> Dank Zweierkomplement klappt das :)

Das ist aber kein Zweierkomplement im Beispiel.

von Patrick D. (oldbug) Benutzerseite


Lesenswert?

Wenn man nicht wissen will, wo das sign-Bit auf dem Ziel hin muss, 
überlässt man das einfach dem Compiler:
1
if(signed) {
2
    val = val * (-1);
3
}

...oder habe ich da jetzt was verpasst?

[edit]
signed muss natürlich durch die tatsächliche Prüfung des sign-Bits 
ersetzt werden!

von B. S. (bestucki)


Lesenswert?

simon schrieb:
> Microchip XC18
Den gibst nicht. Microchip führt nur XC8, XC16 und XC32.
http://www.microchip.com/pagehandler/en_us/devtools/mplabxc/

Der XC8 beherrscht auch 24 Bit Variablen, schau mal nach, ob das deiner 
auch kann.

von simon (Gast)


Angehängte Dateien:

Lesenswert?

> Der XC8 beherrscht auch 24 Bit Variablen, schau mal nach, ob das deiner
> auch kann.

Nicht alle, also schon beim wechsel auf XC32 gibts dann Probleme.


Also dadurch das dieser IC verschiedene Register hat macht es nicht 
einfach eine einzige funktion zu schreiben die damit klar kommt.

es gibt 32, 24(wird als 32 uebertragen), 16 , 8

Und jedesmal natürlich signed und unsigned.

Da bleibt einem doch nur für jeden einzelnen dieser fälle was zu 
schreiben.

von Ralf G. (ralg)


Lesenswert?

Patrick Dohmen schrieb:
> ...oder habe ich da jetzt was verpasst?

Nee, da kommt sicher noch was. ;-)
Ist es nun Zweierkomplement oder stimmt das Beispiel?

von (prx) A. K. (prx)


Lesenswert?

holger schrieb:
> Macht es euch doch nicht so schwer.
> uint32_t temp =  ((uint32_t)MSB << 16) + ((uint32_t)MLSB << 8) + LSB;

Und das ganze dann noch mit Vorzeichen:
int32_t temp =  ((int32_t)(int8_t)MSB << 16) + (MLSB << 8) + 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
Noch kein Account? Hier anmelden.