Forum: Mikrocontroller und Digitale Elektronik Wie kann ich 4 Byte Werte in eine int32 Variable speichern?


von M. G. (ixil96)


Lesenswert?

Hallo,

ich habe folgendes Problem:

Aus einem Byte Array lese ich 4 Bytes aus (beginnend mit MSB) und möchte 
die Werte in eine uint32 Variable wie folgt speichern:
1
  baselineNewHighByte  = ( (baseline[0]<<8) + (baseline[1]) );
2
  baselineNewLowByte  = ( (baseline[3]<<8) + (baseline[4]) );
3
  baselineNew      = ( (baselineNewHighByte<<8) + (baselineNewLowByte) );

baseline[0] = 0x8f
baseline[1] = 0x40
baseline[3] = 0x8f
baseline[4] = 0x16

Für baselineNew erhalte ich aber 0x0000cf16
baselineNewHighByte und baselineNewLowByte sind uint16 Variablen. Die 
hier gespeicherten Werte mit 0x8f40 und 0x8f16 stimmen.

Muss ich für uint32 Variablen eine andere Vorgehensweise wählen?

von pegel (Gast)


Lesenswert?

Versuch mal "oder" statt "plus".

von Pink S. (pinkshell)


Lesenswert?

In der 3. Zeile muss es 16 statt 8 heißen. Und dann sollte type casting 
von 16 auf 32 bit stattfinden.

von Der Andere (Gast)


Lesenswert?

Wenn man 16 Bit Variablen schon im Namen als "byte" bezeichnet

M. G. schrieb:
> baselineNewHighByte

muss man sich nicht wundern wenn man sie nur 8 bit statt 16 schiebt:

M. G. schrieb:
> (baselineNewHighByte<<8

Leute denkt doch mal für 2 Sekunden nach wie man seine variablen 
sinnvoll benamsd.

von Thomas M. (langhaarrocker)


Lesenswert?

Habs nicht weiter im Detail nachvollzogen, nachdem sich mir die Frage 
stellte: Wo schreibst Du baseline[2] (Index zwei) in baselineNewLowByte? 
Und gehört baseline[4] (Index vier) wirklich noch zu Deinem int32?

von Der Andere (Gast)


Lesenswert?

Pink S. schrieb:
> Und dann sollte type casting

Stimmt natürlich VORHER auf einen ausreichend großen Datentyp casten.

von Hmmm (Gast)


Lesenswert?

Du musst das High Word (das Du Byte nennst) 16 statt 8 Bits shiften.

Oder gleich alles zusammen:

baselineNew = (baseline[0]<<24)
              | (baseline[1]<<16)
              | (baseline[2]<<8)
              | baseline[3];

von Joachim B. (jar)


Lesenswert?

Der Andere schrieb:
> Wenn man 16 Bit Variablen schon im Namen als "byte" bezeichnet

würde auch word (besser uword) bevorzugen

von Curby23523 N. (Gast)


Lesenswert?

Sowas..?
1
union{
2
  uint8_t auc[4];
3
  uint32_t ul;
4
} unVariable;
5
6
uint8_t aucAnderevariable[4] = {0x12, 0x34, 0x56, 0x78};
7
8
unVariable.auc[0] = aucAnderevariable[0];
9
unVariable.auc[1] = aucAnderevariable[1];
10
unVariable.auc[2] = aucAnderevariable[2];
11
unVariable.auc[3] = aucAnderevariable[3];
12
13
if(unVariable.ul == 0x12345678){
14
  //HOORAY!
15
}

von Falk B. (falk)


Lesenswert?

@M. G. (ixil96)

>Aus einem Byte Array lese ich 4 Bytes aus (beginnend mit MSB) und möchte
>die Werte in eine uint32 Variable wie folgt speichern:
>  baselineNewHighByte  = ( (baseline[0]<<8) + (baseline[1]) );
>  baselineNewLowByte  = ( (baseline[3]<<8) + (baseline[4]) );
>  baselineNew      = ( (baselineNewHighByte<<8) + (baselineNewLowByte) );

Da fehlt ein Cast. Eher so.
1
  baselineNew      = (long)baseline[0] << 0 |
2
                     (long)baseline[1] << 8 |
3
                     (long)baseline[2] << 16 |
4
                     (long)baseline[3] << 24;

>baselineNewHighByte und baselineNewLowByte sind uint16 Variablen.

Das ist das Problem. Der Compiler rechnet bei diesen Schiebeoperationen 
nur mit 16 Bit, wodurch man niemals Daten in höhere Bits schieben kann. 
Mit dem Cast rechnet er mit 32 Bit.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

M. G. schrieb:
> Muss ich für uint32 Variablen eine andere Vorgehensweise wählen?
Nicht bei einem PC, denn dort ist der Integer 32 Bit breit.

Wenn du bei deinem unbekannten Compiler aber einen 16 Bit Integer hast, 
dann musst du ihm bei Rechenoperationen (auch und besonders mit 
Konstanten) mitteilen, dass er sie doch in 32 Bit Breite ausführen 
solle...

: Bearbeitet durch Moderator
von M. G. (ixil96)


Lesenswert?

Habs jetzt mit dem Typecast versucht
1
baselineNew = ( (long)(baseline[0]<<24) | (long)(baseline[1]<<16) | (long)(baseline[3]<<8) | (long)(baseline[4]) );

aber die obersten zwei bytes sind 0xffff

von Einer K. (Gast)


Lesenswert?

Weiterhin:
Du solltest lernen, wie man bis 4 zählt.
Im Moment klemmt es ab 1 noch etwas....

Und wie dein Cast wirkt, solltest du noch mal im Handbuch nachlesen.
Denn so wird das nichts.

von Falk B. (falk)


Lesenswert?

@M. G. (ixil96)

>Habs jetzt mit dem Typecast versucht
>baselineNew = ( (long)(baseline[0]<<24) | (long)(baseline[1]<<16) | 
(long)>(baseline[3]<<8) | (long)(baseline[4]) );

>aber die obersten zwei bytes sind 0xffff

Was wohl daran liegt, daß long vorzeichenbehaftet ist. Und wenn der 
Compiler eine 16 Bit Zahl auf 32 Bit vorzeichenrichtig erweitert, 
kopiert er Bit 15 in alle Bits 16-31.

von Adam P. (adamap)


Lesenswert?

M. G. schrieb:
> Habs jetzt mit dem Typecast versucht
> baselineNew = ( (long)(baseline[0]<<24) | (long)(baseline[1]<<16) |
> (long)(baseline[3]<<8) | (long)(baseline[4]) );
>
> aber die obersten zwei bytes sind 0xffff

Du muss bei Index 0 beginnen:
1
/* Generiert aus vier Byte Werten ein uint32_t */
2
static inline uint32_t u8u32(uint8_t *src)
3
{
4
   return ((src[3] << 24) | (src[2] << 16) | (src[1] << 8) | (src[0]));
5
}

Hier meine Lösung die ich verwende.

edit:

Über den Namen der Fkt. kann man sich streiten...
Kannst es dann so verwenden:
1
uint8_t buf[4];
2
uint32_t value;
3
4
// buf mit Werten befüllen
5
6
value = u8u32(&buf[0]);

: Bearbeitet durch User
von R. M. (rmax)


Lesenswert?

M. G. schrieb:
> Habs jetzt mit dem Typecast versucht

Leider an der falschen Stelle, Du mußt erst casten und dann schieben, 
nicht umgekehrt:

 (((uint32_t) baseline[0]) << 24)

: Bearbeitet durch User
von Codix (Gast)


Lesenswert?

Du solltest auch den Endian Deines Prozessors kennen.
Bitte dieses einmal lesen: 
https://de.wikipedia.org/wiki/Byte-Reihenfolge#Beispiel:_Speicherung_einer_32_Bit-Ganzzahl_in_4_Bytes

von Der Andere (Gast)


Lesenswert?

Falk B. schrieb:
> baselineNew      = (long)baseline[0] << 0 |
>                      (long)baseline[1] << 8 |
>                      (long)baseline[2] << 16 |
>                      (long)baseline[3] << 24;

Umgekehrte Reihenfolge.
Das MSByte steht wohl in baseline[0].
Siehe:

M. G. schrieb:
> Aus einem Byte Array lese ich 4 Bytes aus (beginnend mit MSB) und möchte
> die Werte in eine uint32 Variable wie folgt speichern:
>   baselineNewHighByte  = ( (baseline[0]<<8) + (baseline[1]) );

von M. G. (ixil96)


Lesenswert?

R. M. schrieb:
> M. G. schrieb:
>> Habs jetzt mit dem Typecast versucht
>
> Leider an der falschen Stelle, Du mußt erst casten und dann schieben,
> nicht umgekehrt:
>
>  (((uint32_t) baseline[0]) << 24)

Jetzt funzt es!

Danke!

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.