Forum: Compiler & IDEs vier 8bit Variablen in eine 32bit Variable


von test (Gast)


Lesenswert?

Hallo,

ich möchte eine 32bit Zahl in ein CAN-Frame verpacken, vom RPi 
verschicken und in einem µC wieder entpacken.

Ist das so wie dargestellt richtig?
1
unsigned int _4567;
2
3
frame.data[4] = _4567;
4
frame.data[5] = _4567>>8;
5
frame.data[6] = _4567>>16;
6
frame.data[7] = _4567>>24;
7
8
[...]
9
sende ueber can 
10
[...]
11
12
uint32_t msg_in_32 = 0;
13
14
msg_in_32 = msg.data[7];
15
msg_in_32 = 8<<msg_in_32;
16
msg_in_32 = msg.data[6];
17
msg_in_32 = 8<<msg_in_32;
18
msg_in_32 = msg.data[5];
19
msg_in_32 = 8<<msg_in_32;
20
msg_in_32 = msg.data[4];

von Karl H. (kbuchegg)


Lesenswert?

test schrieb:

> msg_in_32 = msg.data[7];
> msg_in_32 = 8<<msg_in_32;
> msg_in_32 = msg.data[6];

Nope.
Hier überschreibst du dir ja msg_in_32 komplett!

Das ist nicht das was du willst. Denn selbst, wenn die vorhergehenden 
Operationen korrekt gewesen wären, wäre damit der 'Beitrag' von 
msg.data[7] komplett 'aus dem Rennen' genommen worden. Zuweisung ist 
Zuweisung. Und dabei wird der linke Teil von der Zuweisung unter 
Beachtung seines Datentyps komplett beschrieben.

Ausserdem stimmt die Angabe beim Verschieben nicht

    a << b

bedeutet: verschiebe den Inhalt von a um b Bits nach links.
Genauso wie

    a >> b

bedeutet: verschiebe den Inhalt von a um b Bits nach rechts.

Links von der Operation, egal ob << oder >>, steht das "womit". Und 
rechts von der Operation steht um "wieviele" Bits.
Liest du denn kein C Buch, ehe du mit programmieren anfängst? Da wirst 
du noch ein paar mal schön auf die Schnauze fallen.

von test (Gast)


Lesenswert?

Wie kann ich dann das Problem lösen?

von Tobias S. (x12z34)


Lesenswert?

Hallo,

ich denke*, Du suchst etwas wie das Folgende, wobei msg_in_32 den 
übertragenen Wert enthält, der in die 4 Array-Werte msg.data[x] 
"aufgesplittet" wird.
1
msg.data[4] = (msg_in_32 & 0x000F);
2
msg.data[5] = (msg_in_32 & 0x00F0) >> 8;
3
msg.data[6] = (msg_in_32 & 0x0F00) >> 16;
4
msg.data[7] = (msg_in_32 & 0xF000) >> 24;

*Oder habe ich mal wieder einen kapitalen Denkfehler gemacht? ;-)

von Karl H. (kbuchegg)


Lesenswert?

Tobias S. schrieb:
> Hallo,
>
> ich denke*, Du suchst etwas wie das Folgende, wobei msg_in_32 den
> übertragenen Wert enthält, der in die 4 Array-Werte msg.data[x]
> "aufgesplittet" wird.
>
>
1
msg.data[4] = (msg_in_32 & 0x000F);
2
> msg.data[5] = (msg_in_32 & 0x00F0) >> 8;
3
> msg.data[6] = (msg_in_32 & 0x0F00) >> 16;
4
> msg.data[7] = (msg_in_32 & 0xF000) >> 24;
>
> *Oder habe ich mal wieder einen kapitalen Denkfehler gemacht? ;-)

Falsche Datenflussrichtung.
Er hat die 4 Einzelwerte und will sie zusammensetzen.

von Karl H. (kbuchegg)


Lesenswert?

test schrieb:
> Wie kann ich dann das Problem lösen?

Na, ja.
Die 4 Bytes eben geeignet verschoben wieder zusammensetzen.
1
msg_in_32  = ( (uint32_t)msg.data[7] << 24 )   |
2
             ( (uint32_t)msg_data[6] << 16 )   |
3
             ( (uint32_t)msg_data[5] <<  8 )   |
4
             ( (uint32_t)msg_data[4]       );

ein bischen optimieren könnte man das noch bezüglich der Casts.

von Tobias S. (x12z34)


Lesenswert?

Hallo Karl Heinz, ich zitiere mal von oben:
1
unsigned int _4567;
2
3
[...]
4
sende ueber can 
5
[...]
6
uint32_t msg_in_32 = 0;
7
msg_in_32 = msg.data[7];
8
[...]

für mich sah das so aus, dass er schon über CAN gesendet hat und den 
32bitter wieder auseinanderpfriemeln will, daher auch der Name 
msg_*in*_32.

Wie gesagt, wäre aber nicht das erste Mal, dass ich mich irre ;-)

von TomA. (Gast)


Lesenswert?

Hallo Test,

fasse deine Variablen, auf beiden Seiten, in einer "union" zusammen und 
das Problem ist gelöst.

Gruß. Tom

von Random .. (thorstendb) Benutzerseite


Lesenswert?

packed union, um sicherzugehen :-)

von Dr. Sommer (Gast)


Lesenswert?

TomA. schrieb:
> fasse deine Variablen, auf beiden Seiten, in einer "union" zusammen und
> das Problem ist gelöst.
Ja, aber nur wenn Ziel&Quell -Platform die selbe Endianness haben. 
Ansonsten sind die Bytes falsch herum. Wenn man hingegen Bitshifts wie 
oben verwendet, stellt der Compiler sicher dass sie immer die richtige 
Reihenfolge haben (LE in diesem Fall). So bleibt der Code portabel.

von test (Gast)


Lesenswert?

Karl Heinz schrieb:
1
> msg_in_32  = ( (uint32_t)msg.data[7] << 24 )   |
2
>              ( (uint32_t)msg_data[6] << 16 )   |
3
>              ( (uint32_t)msg_data[5] <<  8 )   |
4
>              ( (uint32_t)msg_data[4]       );

Ich werde es genau so machen.
Danke!

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Karl Heinz schrieb:
>>
1
msg.data[4] = (msg_in_32 & 0x000F);
2
>> msg.data[5] = (msg_in_32 & 0x00F0) >> 8;
3
>> msg.data[6] = (msg_in_32 & 0x0F00) >> 16;
4
>> msg.data[7] = (msg_in_32 & 0xF000) >> 24;
>>
>> *Oder habe ich mal wieder einen kapitalen Denkfehler gemacht? ;-)
>
> Falsche Datenflussrichtung.

Nicht nur das. Maskieren von Nibbles statt Bytes ist hier wenig 
zielführend. ;-)

von PittyJ (Gast)


Lesenswert?

msg.data[4] = (msg_in_32 & 0x000000FF);
 msg.data[5] = (msg_in_32 & 0x0000FF00) >> 8;
 msg.data[6] = (msg_in_32 & 0x00FF0000) >> 16;
 msg.data[7] = (msg_in_32 & 0xFF000000) >> 24;

oder erst schieben, und dann maskieren. ist dann immer 0xff:

..
 msg.data[4] = (msg_in_32 >>  0 ) & 0xff;
 msg.data[5] = (msg_in_32 >>  8 ) & 0xff;
 msg.data[6] = (msg_in_32 >> 16 ) & 0xff;
 msg.data[7] = (msg_in_32 >> 24 ) & 0xff;
..

von Jobst Q. (joquis)


Lesenswert?

Wenn msg.data[] vom typ unsigned char ist, kann man sich das maskieren 
mit 0xff sparen, weil nicht mehr Bits reinpassen.

von hp-freund (Gast)


Angehängte Dateien:

Lesenswert?

Mit Zeigern kann man das Ganze doch einfacher machen oder?

von Dr. Sommer (Gast)


Lesenswert?

hp-freund schrieb:
> Mit Zeigern kann man das Ganze doch einfacher machen oder?

Dann hast du aber genau das gleiche Problem wie mit unions:

Dr. Sommer schrieb:
> TomA. schrieb:
>> fasse deine Variablen, auf beiden Seiten, in einer "union" zusammen und
>> das Problem ist gelöst.
> Ja, aber nur wenn Ziel&Quell -Platform die selbe Endianness haben.
> Ansonsten sind die Bytes falsch herum. Wenn man hingegen Bitshifts wie
> oben verwendet, stellt der Compiler sicher dass sie immer die richtige
> Reihenfolge haben (LE in diesem Fall). So bleibt der Code portabel.

von hp-freund (Gast)


Lesenswert?

Ok. Das ist Richtig.

von Peter II (Gast)


Lesenswert?

hp-freund schrieb:
> Mit Zeigern kann man das Ganze doch einfacher machen oder?

nur wenn du immer auf gleichen (Big|Little) Edian-Systemen arbeitest.


Auch mit memcpy kann man arbeiten, aber das gleichen Problem.

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.