Forum: Mikrocontroller und Digitale Elektronik 32bit long in 4 byte aufteilen


von tobias hofer (Gast)


Lesenswert?

hallo

wie kann ich am effizientesten einen 32 bit wert,
zb 1000100010001000....in 4 byte aufteilen,
-> 10001000;10001000;....
   Byte 4  ;Byte 3

besten dank tobias

von Nik Bamert (Gast)


Lesenswert?

Hi Tobias,

Ich hab ein ähnliches Problem jedoch mit Word->2* byte
Wenn du mit einem Basic Compiler arbeitet könntest du zuerst den Wert
in einen 32 Byte String umwandeln, danach mit der Funktion Mid in 4
Teile einteilen(immernoch  Strings). Und Schlussendlich mit einem
Kleinen Progrämmchen, die Strings mit einsen und Nullen, wieder in
Bytes umwandeln. Klingt zwar etwas kompliziert, sollte aber gehen..

MFG Nik

von tobias hofer (Gast)


Lesenswert?

ich würde das ganze gerne in c oder sonst halt in assembler lösen.
es gibt sicherlich einen mathematischen weg. weiss nur noch nicht
wie.

tobias

von Stefan (Gast)


Lesenswert?

Probier mal, ein union zu definieren aus
a.) 4 Bytes und
b.) 1 long.

Das gabs hier schonmal, schau mal das hier an:

http://www.mikrocontroller.net/forum/read-1-27159.html#27159

Mit der String-Methode schaffst Du es sicher auch ins Guiness-Buch,
aber sicher nicht für den effizientesten Code ;-)

Stefan

von Darko Sabljo (Gast)


Lesenswert?

Hi liesst du den Wert Seriell ein?
oder hast du den schon irgendwie in einer 32 Bit Variabel?

Also bei mir war das so, das der Sensor nen 32 Bit Wer ausgibt,
Seriell, zum Clock bei jeder Flanke.
Da hab ich mir in Assembler sowas gebastelt für:

byteout:

    cpi r20 , 8
    brsh j24to8_1
    lsl r21
    in r24 , PINC
    andi r24 , 0b00000001
    or r21, r24
    inc r20
    rjmp bitout_out

  j24to8_1:
    cpi r20 , 16
    brsh j24to8_2
    lsl r22
    in r24 , PINC
    andi r24 , 0b00000001
    or r22, r24
    inc r20
    rjmp bitout_out

  j24to8_2:
    cpi r20 , 24
    brsh bitout_out
    lsl r23
    in r24 , PINC
    andi r24 , 0b00000001
    or r23, r24
    inc r20


  bitout_out:
ret

Das speichert mir meinen Seriellen Wert in den Registern R21-R24
Vor diesem Programm ist nur noch ein klein bischen Code um mir meine HL
und LH Flanke zu detektieren. Das hab ich jetzt hier mal weggelassen
:)

Gruss
Darko

von tobias hofer (Gast)


Lesenswert?

nein, ich lesen den wert nicht seriell ein.
ich mache eine berechnung und das ergebniss ist dann ein long,
und diesen long wert muss ich nun in 4byte aufteilen.

tobias

von Matthias (Gast)


Lesenswert?

Hi

entweder über ein union (wobei ich da immer bedenken habe wegen der
Portierung auf andere Systeme) oder aber:

unsigned char b1,b2,b3,b4;
unsigned long l;

b1=l&0xff;
b2=(l>>8)&0xff;
b3=(l>>16)&0xff;
b4=(l>>24)&0xff;

Matthias

von tobias hofer (Gast)


Lesenswert?

danke matthias, werde das gleich mal ausprobieren.

tobias

von Nik Bamert (Gast)


Lesenswert?

Hi!

Du kannst das auch auf diese Weise Lösen:(nur so ne art Pseudo-Code)

wert = (deine 32 bit zahl als long-variable)

if wert = 4294967296 then firstbyte = 255 : secondbyte = 255 :
thirdbyte = 255 : fourtbyte = 255wenn die zahl gleich die
höchstmögliche ist dann alle bits auf 1 setzen

'wenn nicht dann alles Abklappern, bis der gewünschte wert
ausgerechnet ist
'///////////////////////////////////
'erstes byte auffüllen
if wert > 2147483648 then firstbyte = firstbyte + 128 : wert = wert
-2147483648
if wert > 1073741824 then firstbyte = firstbyte + 64 : wert = wert -
1073741824
if wert > 536870912 then firstbyte = firstbyte + 32 : wert = wert -
536870912
if wert > 268435456 then firstbyte = firstbyte + 16 : wert = wert -
268435456
if wert > 134217728 then firstbyte = firstbyte + 8 : wert = wert -
134217728
if wert > 67108864 then firstbyte = firstbyte + 4 : wert = wert -
67108864
if wert > 33554432 then firstbyte = firstbyte + 2 : wert = wert -
33554432
if wert > 16777216 then firstbyte = firstbyte + 1 : wert = wert -
16777216
'//////////////////////////////////
'zweites Byte auffüllen
if wert > 8388608 then secondbyte = secondbyte + 128 : wert = wert
-8388608
if wert > 4194304 then secondbyte = secondbyte + 64 : wert = wert -
4194304
if wert > 2097152 then secondbyte = secondbyte + 32 : wert = wert -
2097152
if wert > 1048576 then secondbyte = secondbyte + 16 : wert = wert -
1048576
if wert > 524288 then secondbyte = secondbyte + 8 : wert = wert -
524288
if wert > 262144 then secondbyte = secondbyte + 4 : wert = wert -
262144
if wert > 131072 then secondbyte = secondbyte + 2 : wert = wert -
131072
if wert > 65536 then secondbyte = secondbyte + 1 : wert = wert - 65536

'//////////////////////////////////
'drittes Byte auffüllen
if wert > 32768 then thirdbyte = thirdbyte + 128 : wert = wert -32768
if wert > 16384 then thirdbyte = thirdbyte + 64 : wert = wert - 16394
if wert > 8192 then thirdbyte = thirdbyte + 32 : wert = wert - 8192
if wert > 4096 then thirdbyte = thirdbyte + 16 : wert = wert - 4096
if wert > 2048 then thirdbyte = thirdbyte + 8 : wert = wert - 2048
if wert > 1024 then thirdbyte = thirdbyte + 4 : wert = wert - 1024
if wert > 512 then thirdbyte = thirdbyte + 2 : wert = wert - 512
if wert > 256 then thirdbyte = thirdbyte + 1 : wert = wert - 256
'//////////////////////////////////
'viertes Byte auffüllen
if wert > 128 then fourtbyte = fourtbyte + 128 : wert = wert -128
if wert > 64 then fourtbyte = fourtbyte + 64 : wert = wert - 64
if wert > 32 then fourtbyte = fourtbyte + 32 : wert = wert - 32
if wert > 16 then fourtbyte = fourtbyte + 16 : wert = wert - 16
if wert > 8 then fourtbyte = fourtbyte + 8 : wert = wert - 8
if wert > 4 then fourtbyte = fourtbyte + 4 : wert = wert - 4
if wert > 2 then fourtbyte = fourtbyte + 2 : wert = wert - 2
if wert > 1 then fourtbyte = fourtbyte + 1 : wert = wert - 1

So. Nun sind in firstbyte, secondbyte, thirdbyte und fourtbyte die
entsprechenden Werte als Dezimalzahl gespeichert.



MFG NIK

P.S. In Fourthbyte ist das niederwertigste Byte gespeichert(mit werten
bis zu 255)

von Matthias (Gast)


Lesenswert?

Hi

@Nik

du erhälst heute den "viel Text, wenig Sinn" Award :-)
Was du da machst ist im Prinzip die fortgesetzte Division durch zwei.
Wenn man das schon so machen will (will man aber nicht) dann in einer
Schleife.

Matthias

von Nik Bamert (Gast)


Lesenswert?

Hi

@Matthias

Sorry, hab von C echt überhaupt keeeeine Ahnung, desshalb wusste ich
auch überhaupt nicht was du da in deinem Code geschrieben hast ;-)

MFG Nik

von Stefan Peter (Gast)


Lesenswert?

Hallo!

Will hier auch mal meinen Senf dazugeben:
Man könnte nach rechts shiften (lsl) und wenn eine 1 rechts
herausfällt, dann sollte ein Flag gesetzt werden (glaube es ist das
Carry-Bit, bin aber gar nicht sicher...). In diesem Fall ist kann man
dan das entsprechende Bit im Byte auf eins setzen und das macht man 32
Mal...

von Stefan (Gast)


Lesenswert?

Hallo Nik, Hallo tobias,

bevor Ihr loprogrammiert, solltet Ihr Euch erstmal überlegen, wie es
denn in Eurem MC aussieht. Die 32Bit kann Euer MC ja nicht am Stück
speichern ich nehme an, Ihr arbeitet auf Atmel). Wie macht er es dann?
Richtig, er speichert es in 4 Bytes ab ...

Im Prinzip liegt also irgendwo im MC Euer Ergebnis schon fix und fertig
drin, wenn Ihr es schafft, auf diese 4 Byte Eures Long einzeln
zuzugreifen, dann habt Ihr schon gewonnen - ohne eine einzige
Berechnung auszuführen.

Die "schönste" Lösung ist dabei meiner Meinung die Union.
Aber was ist das?
Ihr erklärt Eurem Compiler, dass Er auf Eure Long nicht nur als Long,
sondern auch anders, nämlich als 4 Bytes, zugreifen kann. Im Programm
könnt Ihr dann entweder auf die Long oder auf eins der 4 Bytes
zugreifen, je nachdem, welchen Namen Ihr hinschreibt.

Ihr werded am Anfang zwar etwas mehr Verständnis-Zeit brauchen, aber
die lohnt sich, glaubts mir!

Stefan

P.S.:
Die Lösung von Matthias hat sicher auch ihre Berehtigung, ich denke
aber nicht, dass Ihr Euch in naher Zukunft mit Portierungsfragen
rumärgern müsst ...

von tobias hofer (Gast)


Lesenswert?

hallo stefan

die lösung mit einer union wäre das idealle. ich habe jedoch noch nie
etwas mit einer union gemacht. ich habe auch nach dem alten tread
gesucht der oben erwähnt wird. habe jedoch das beispiel 32bit zu
4x 8byte nicht gefunden. vieleicht kannst du mir
ja noch einen tip geben.

danke
tobias

von Stefan (Gast)


Lesenswert?

typedef union {
  unsigned char b[4];
  unsigned long l;
} typ_mixed;

int main(void){
  typ_mixed mylong;
  volatile unsigned long ergebnis;

  mylong.b[0] = 0;  /* unteres Byte = 0 */
  mylong.b[1] = 1;  /* zweites Byte = 1 */
  mylong.b[2] = 2;  /* drittes Byte = 2 */
  mylong.b[3] = 3;  /* oberes  Byte = 3 */

  /************************************
  mylong als Long gesehen ist jetzt:
     0 +
     1 * 256 +
     2  256  256 +
     3  256  256 * 256
  *************************************/

  ergebnis = mylong.l;

  return(0);
}

von Jörg Maaßen (Gast)


Lesenswert?

Hallo zusammen,

ich versuche mich gerade in der Assembler-Programmierung eines AVR.
Dabei würde ich gerne bis zu 24 Stunden lang per
Timer-Overflow-Interrupt Millisekunden zählen. Dazu brauche ich auch
einen 32bit-Wert. Für die Erzeugung des 1ms Taktes habe ich den Timer 0
und besagten Interrupt verwendet (klappt auch).

Wie lege ich in Assembler eine 32bit-Variable an? oder muss ich 4
Variable definieren und diese auf Überlauf überwachen um dann die
nächst zu erhöhen?

Gruß Jörg

von miwitt001 (Gast)


Lesenswert?

Es gibt noch so eine ähnlich Lösung wie die Unions. Weiß nicht ob das
auf nem ATMEL geht, aber unter Windows-C++ hab ichs mal gemacht.

long l;
long * pl = &l;

wenn man jetzt auf das erste byte zugreifen will einfach so:

(byte*)pl;

für das zweite
((byte*)pl) + 1;  usw...
so hat man dann die Adressen der einzelnen Byte Variablen, mit denen
man arbeiten kann.

mfg Michael

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.