byte buffer in long konvertieren

OP #3298961
Lesenswert?

Hallo Mädels,
ich habe die SuFu genutzt und nichts passendes gefunden.
Ich möchte ein byte array in eine Longvariable konvertieren.
Jetzt sind es aber nicht 4 bytes sondern 24.
In jedem Byte steht nur eine 0 oder 1.
Im Byte[0] ist das höchstwertige Bit untergebracht.
Im Byte[23] ist das niederwertigste Bit untergebracht.

Jetzt sollen aus den 23 Bit eine ganze Zahl werden. Wie stelle ich das 
am besten an?

Viele Grüße,
afo
OP #3298978
Lesenswert?

So scheint es zu funktionieren...
Mit 24 war es um eins verschoben.

1
   k = (unsigned long) buffer_FPGA[0] << 23 |
2
                  (unsigned long) buffer_FPGA[1] << 22 |
3
                  (unsigned long) buffer_FPGA[2] << 21 |
4
                  (unsigned long) buffer_FPGA[3] << 20 |
5
                  (unsigned long) buffer_FPGA[4] << 19 |
6
                  (unsigned long) buffer_FPGA[5] << 18 |
7
                  (unsigned long) buffer_FPGA[6] << 17 |
8
                  (unsigned long) buffer_FPGA[7] << 16 |
9
                  (unsigned long) buffer_FPGA[8] << 15 |
10
                  (unsigned long) buffer_FPGA[9] << 14 |
11
                  (unsigned long) buffer_FPGA[10] << 13 |
12
                  (unsigned long) buffer_FPGA[11] << 12 |
13
                  (unsigned long) buffer_FPGA[12] << 11 |
14
                  (unsigned long) buffer_FPGA[13] << 10 |
15
                  (unsigned long) buffer_FPGA[14] << 9 |
16
                  (unsigned long) buffer_FPGA[15] << 8 |
17
                  (unsigned long) buffer_FPGA[16] << 7 |
18
                  (unsigned long) buffer_FPGA[17] << 6 |
19
                  (unsigned long) buffer_FPGA[18] << 5 |
20
                  (unsigned long) buffer_FPGA[19] << 4 |
21
                  (unsigned long) buffer_FPGA[20] << 3 |
22
                  (unsigned long) buffer_FPGA[21] << 2 |
23
                  (unsigned long) buffer_FPGA[22] << 1 |
24
                  buffer_FPGA[23];
OP #3299754
Lesenswert?

Vielen Dank für die hilfreichen Antworten.

Bisher sieht die Lösung jetzt so aus:
1
int j;          
2
unsigned long counter = 0;
3
for(j = 0; j < 24; j++){
4
if(buffer_FPGA[23-j]== 1){
5
counter |= (unsigned int)(1<<(23-j));
6
}
7
}

Allerdings fängt er irgendwie erst ab Bit 16 an zu shiften und wirklich 
Werte in counter zu schreiben. Zuvor wird die if schleife normal 
durchlaufen, aber es bleibt eine 0 stehen.
Kann sich das jemadn erklären?
Gast #3299760
Lesenswert?

Jan R. schrieb:
> Kann sich das jemadn erklären?

ja

(unsigned int)(1<<(23-j));


das cast ist falsch. denn die 1 die geschiftet wird ist nur ein int.

wenn dann so

((unsigned int)1<<(23-j));


ja noch CPU die die schleife viel langsamer sein. aus dem Grunde hatte 
ich es ohne schleife gemacht.
OP #3299771
Lesenswert?

Auch mit der Änderung des Casts tritt der gleiche Fehler auf.
Bei deiner Lösung, also ohne Schleife (siehe oben), war es prinzipiell 
ganz gut. Nur es kamen die ganz richtige Ergebnisse raus.
Das Bytearray hat sicher die richtigen Werte. Ich konvertire den Wert 
mit dem Windows Rechner und es kommt 900000 raus. Dann mache ich es mit 
der Variante und es kommt 898880 raus.
Wie kann das sein?
Gast #3299774
Lesenswert?

898880 = 0b11011011011101000000
900000 = 0b11011011101110100000

0b110110_11011101000000
0b11011011101110100000


das kann wirklihc nicht am cast liegen. Sicher das immer die gleichen 
werte reinkommen? Dann hier es es fehlet einfach 1 bit.
OP #3299785
Lesenswert?

1
counter = (unsigned long) buffer_FPGA[0] << 23 |
2
                  (unsigned long) buffer_FPGA[1] << 22 |
3
                  (unsigned long) buffer_FPGA[2] << 21 |
4
                  (unsigned long) buffer_FPGA[3] << 20 |
5
                  (unsigned long) buffer_FPGA[4] << 19 |
6
                  (unsigned long) buffer_FPGA[5] << 18 |
7
                  (unsigned long) buffer_FPGA[6] << 17 |
8
                  (unsigned long) buffer_FPGA[7] << 16 |
9
                  (unsigned long) buffer_FPGA[8] << 15 |
10
                  (unsigned long) buffer_FPGA[9] << 14 |
11
                  (unsigned long) buffer_FPGA[10] << 13 |
12
                  (unsigned long) buffer_FPGA[11] << 12 |
13
                  (unsigned long) buffer_FPGA[12] << 11 |
14
                  (unsigned long) buffer_FPGA[13] << 10 |
15
                  (unsigned long) buffer_FPGA[14] << 9 |
16
                  (unsigned long) buffer_FPGA[15] << 8 |
17
                  (unsigned long) buffer_FPGA[16] << 7 |
18
                  (unsigned long) buffer_FPGA[17] << 6 |
19
                  (unsigned long) buffer_FPGA[18] << 5 |
20
                  (unsigned long) buffer_FPGA[19] << 4 |
21
                  (unsigned long) buffer_FPGA[20] << 3 |
22
                  (unsigned long) buffer_FPGA[21] << 2 |
23
                  (unsigned long) buffer_FPGA[22] << 1 |
24
                  buffer_FPGA[23];

Vielleicht ist hier noch irgendwo ein Fehler...
Ich nehme den Wert wirklich zur Laufzeit aus dem Programm.
Gast #3299786
Lesenswert?

Yalu X. schrieb:
> Nicht so:
> (unsigned int)(1<<(23-j))
>
> und auch nicht so:
> ((unsigned int)1<<(23-j));
>
> sonder so:
> ((unsigned long)1<<(23-j));
>
> oder einfach so:
> (1UL<<(23-j));

er testet eh auf einen windows PC. Dort ist denke ich mal alles 32bit. 
Damit spielt es überhaupt keine Rolle.
Gast #3299792
Lesenswert?

Jan R. schrieb:
> counter = (unsigned long) buffer_FPGA[0] << 23 |
>                   (unsigned long) buffer_FPGA[1] << 22 |
>                   (unsigned long) buffer_FPGA[2] << 21 |
>                   (unsigned long) buffer_FPGA[3] << 20 |
>                   (unsigned long) buffer_FPGA[4] << 19 |
>                   (unsigned long) buffer_FPGA[5] << 18 |
>                   (unsigned long) buffer_FPGA[6] << 17 |
>                   (unsigned long) buffer_FPGA[7] << 16 |
>                   (unsigned long) buffer_FPGA[8] << 15 |
>                   (unsigned long) buffer_FPGA[9] << 14 |
>                   (unsigned long) buffer_FPGA[10] << 13 |
>                   (unsigned long) buffer_FPGA[11] << 12 |
>                   (unsigned long) buffer_FPGA[12] << 11 |
>                   (unsigned long) buffer_FPGA[13] << 10 |
>                   (unsigned long) buffer_FPGA[14] << 9 |
>                   (unsigned long) buffer_FPGA[15] << 8 |
>                   (unsigned long) buffer_FPGA[16] << 7 |
>                   (unsigned long) buffer_FPGA[17] << 6 |
>                   (unsigned long) buffer_FPGA[18] << 5 |
>                   (unsigned long) buffer_FPGA[19] << 4 |
>                   (unsigned long) buffer_FPGA[20] << 3 |
>                   (unsigned long) buffer_FPGA[21] << 2 |
>                   (unsigned long) buffer_FPGA[22] << 1 |
>                   buffer_FPGA[23];
>
> Vielleicht ist hier noch irgendwo ein Fehler...


ja ist er.

buffer_FPGA[0] << 23 |
...
buffer_FPGA[22] << 1

das 0.bit wird nie gesetzt.  es fehlet irgendwie die zeile ohne ein 
schift. (also ein << 0 )
OP #3299815
Lesenswert?

Der allerletze Befehl buffer_FPGA[23]; wird nicht geshiftet.
Jetzt habe ich gemerkt nachdem ich es einzeln aufgetröselt habe:
1
counter |= (unsigned long) buffer_FPGA[0] << 23;
2
                  counter |= (unsigned long) buffer_FPGA[1] << 22; 
3
                  counter |= (unsigned long) buffer_FPGA[2] << 21;
4
                  counter |= (unsigned long) buffer_FPGA[3] << 20; 
5
                  counter |= (unsigned long) buffer_FPGA[4] << 19; 
6
                  counter |= (unsigned long) buffer_FPGA[5] << 18; 
7
                  counter |= (unsigned long) buffer_FPGA[6] << 17; 
8
                  counter |= (unsigned long) buffer_FPGA[7] << 16; 
9
                  counter |= (unsigned long) buffer_FPGA[8] << 15; 
10
                  counter |= (unsigned long) buffer_FPGA[9] << 14; 
11
                  counter |= (unsigned long) buffer_FPGA[10] << 13; 
12
                  counter |= (unsigned long) buffer_FPGA[11] << 12; 
13
                  counter |= (unsigned long) buffer_FPGA[12] << 11; 
14
                  counter |= (unsigned long) buffer_FPGA[13] << 10; 
15
                  counter |= (unsigned long) buffer_FPGA[14] << 9; 
16
                  counter |= (unsigned long) buffer_FPGA[15] << 8;
17
                  counter |= (unsigned long) buffer_FPGA[16] << 7; 
18
                  counter |= (unsigned long) buffer_FPGA[17] << 6; 
19
                  counter |= (unsigned long) buffer_FPGA[18] << 5; 
20
                  counter |= (unsigned long) buffer_FPGA[19] << 4; 
21
                  counter |= (unsigned long) buffer_FPGA[20] << 3; 
22
                  counter |= (unsigned long) buffer_FPGA[21] << 2; 
23
                  counter |= (unsigned long) buffer_FPGA[22] << 1; 
24
                  counter |= buffer_FPGA[23];

Das während dieses Vorgangs bei buffer_FPGA[12] das Array von unten 
überschrieben wird ?!
So einen Fehler hatte ich noch nie...
Moderator #3299833
Lesenswert?

Auf welchem Prozessor läuft der Code? Ich nehme an, es ist irgendein 
8-Bit- oder 16-Bit-Controller.

Was genau steht bei deinem Test in dem Byte-Puffer?

Sind die 0en und 1en im Byte-Puffer Integer-Werte (also 0x00 bzw 0x01) 
oder ASCII-Zeichen (also 0x30 und 0x31)?

Jan R. schrieb:

> Ich konvertire den Wert
> mit dem Windows Rechner und es kommt 900000 raus. Dann mache ich es mit
> der Variante und es kommt 898880 raus.

Sind die diese Zahlen 900000 und 898880 im Dezimal- oder 
Hexadezimalformat?
OP #3299844
Lesenswert?

So vielen Dank für deine Hilfe.
Deklaration:
byte buffer_FPGA [24];

Es ist ein 8 Bit Controller (MC9S08AW60)
http://cache.freescale.com/files/microcontrollers/doc/data_sheet/MC9S08AW60.pdf?fpsp=1&WT_TYPE=Data%20Sheets&WT_VENDOR=FREESCALE&WT_FILE_FORMAT=pdf&WT_ASSET=Documentation

Im Array steht in jedem Byte eine 0 oder 1 als Integer Wert, also 
0b00000000 oder 0b00000001.
Die 900000 bzw. 898880 sind im Dezimalformat.

Ab der zeile geht es mit dem überschreiben los:
 counter |= (unsigned long) buffer_FPGA[12] << 11;


Ich habe kein Timer und keine Interrupts aktiv.
OP #3299883
Lesenswert?

1
buffer_FPGA    
2
[0]  0
3
[1]  0
4
[2]  0
5
[3]  0
6
[4]  1
7
[5]  1
8
[6]  0
9
[7]  1
10
[8]  1
11
[9]  0
12
[10]  1
13
[11]  1
14
[12]  1
15
[13]  0
16
[14]  1
17
[15]  1
18
[16]  1
19
[17]  0
20
[18]  0
21
[19]  1
22
[20]  1
23
[21]  1
24
[22]  1
25
[23]  1
26

27

28
Nach counter |= (unsigned long) buffer_FPGA[13] << 10;
29

30

31
counter= 11011011100000000000
32

33
buffer_FPGA    
34
[0]  0
35
[1]  0
36
[2]  0
37
[3]  0
38
[4]  1
39
[5]  1
40
[6]  0
41
[7]  1
42
[8]  1
43
[9]  0
44
[10]  1
45
[11]  1
46
[12]  1
47
[13]  0
48
[14]  1
49
[15]  1
50
[16]  1
51
[17]  0
52
[18]  0
53
[19]  1
54
[20]  1
55
[21]  33
56
[22]  78
57
[23]  0
]


Dann wird der buffer_FPGA immer weiter mit komischen Werten 
überschrieben und das beeinflusst so die Konvertierung natürlich stark.
Ich habe ein Watchpoint auf die den Buffer gelegt und gemerkt, dann bin 
ich in einer Assemblerfunktion gelandet, jeder Befehl dieser Funktion 
wurde dann n den Buffer geschrieben...
Moderator #3299958
Lesenswert?

Jan R. schrieb:
> [19]  1
> [20]  1
> [21]  33
> [22]  78
> [23]  0

Ja, irgendetwas spuckt da in deine Daten.

78*256+33 ist überigens 20001. Zufall?

Oder wird in dem Programm tatsächlich irgendwo mit Zahlen um die 20000 
gerechnet. Wenn ja, hast du ja schon einen Anhaltspunkt, wo der Fehler 
liegen könnte.

An der Konvertierungsroutine brauchst du jedenfalls nicht 
weiterzumachen, bis du den Fehler gefunden hast.



Nur noch ein kleiner Hinweis für später:

Der HCS08 hat keinen Barrel-Shifter und schon gar keinen für 32 Bit. Er 
muss deswegen Shifts um mehr als 1 Bit aus recht vielen 
Einzeloperationen zusammensetzen, u.U. sogar unter Verwendung von 
Schleifen. Deswegen sollte man, wenn möglich, Algorithmen so 
umkonstruieren, dass sie mit Shifts um 1 Bit auskommen. Das 
Code-Beispiel, das ich weiter oben gepostet habe, geht in diese 
Richtung, da eine Multiplikation mit einem Links-Shift um 1 Bit 
entspricht.

Je nach Optimierungsfähigkeit des Compilers liefert dieser evtl. bei 
folgender Variante (wichtig ist vor allem das '|' anstelle des '+') 
besseren Code:
1
unsigned long buf2num(unsigned char buffer[]) {
2
  unsigned long num = 0;
3
  unsigned char i;
4

5
  for(i=0; i<24; i++)
6
    num = num<<1 | buffer[i];
7

8
  return num;
9
}

Auf einem AVR mit GCC 4.8.1 benötigt damit ein Schleifendurchlauf nur 11 
Taktzyklen. Besser bekommt es auch ein Assemblerprogrammierer kaum hin.

Ich schätze, dass das auf einem HCS08 ganz ähnlich aussieht.
OP #3299993
Lesenswert?

Hallo,
1
 counter = (counter<<1) | PTED_PTED1;

Problem ist gelöst bzw. eine Alternative wurde gefunden.
So mache ich das ohne Array und es funktioniert.
Auf dem Stack ist noch ewig viel Platz und eine 20000 verwende ich 
nirgends.

Das war einfach eine komische Angelegenheit....
Ich versuche nachher das Problem auch mit der Array zu lösen, rein aus 
Neugier.
Moderator #3300036
Lesenswert?

Jan R. schrieb:
> Ich versuche nachher das Problem auch mit der Array zu lösen, rein aus
> Neugier.

Du solltest das nicht nur aus Neugier machen. Wenn tatsächlich irgendein 
fehlerhafter Programmteil das Array überschrieben hat, überschreibt er 
nach Beseitigung des Arrays eben irgendetwas anderes, was dir vielleicht 
nur noch nicht aufgefallen ist. Nur wenn du weißt, wo genau der Fehler 
lag, kannst du auch wissen, ob er immer noch existiert und ggf. behoben 
werden muss.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren