Forum: Mikrocontroller und Digitale Elektronik byte buffer in long konvertieren


von Peter M. (allforone)


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

von Peter II (Gast)


Lesenswert?

Jan R. schrieb:
> Jetzt sollen aus den 23 Bit eine ganze Zahl werden. Wie stelle ich das
> am besten an?

welche Sprache?

Wenn es zufällig C ist.

Long l = ((Long)Byte[0])<<24 | ((Long)Byte[1])<<23 | ((Long)Byte[2])<<22 
| ...

von Peter M. (allforone)


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];

von Timmo H. (masterfx)


Lesenswert?

Je nach byte-order. Im einfachsten Fall so
1
int i;
2
long foo = 0;
3
for(i = 0; i < 24; i++){
4
  if(byte[i]){
5
    foo |= (1<<(23-i));
6
  }
7
}

von Yalu X. (yalu) (Moderator)


Lesenswert?

So
1
buf2num = foldl (\n b -> 2*n+b) 0

oder so
1
uint32_t buf2num(uint8_t buffer[]) {
2
  uint32_t num = 0;
3
  uint8_t  i;
4
5
  for(i=0; i<24; i++)
6
    num = 2 * num + buffer[i];
7
8
  return num;
9
}

je nach Geschmack.

von Peter M. (allforone)


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?

von Peter II (Gast)


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.

von Peter M. (allforone)


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?

von Peter II (Gast)


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.

von Peter M. (allforone)


Lesenswert?

Der Wert kommt rein und ich stoppe das Programm. Schau mir parallel den 
das bytearray an konvertiere es mit dem Windows Rechner und lasse dann 
das Programm weiterlaufen. Es sind sicher die gleichen und es sollen 
auch 900.000 rauskommen.

von Peter II (Gast)


Lesenswert?

Jan R. schrieb:
> Es sind sicher die gleichen und es sollen
> auch 900.000 rauskommen.

glaube ich nicht. Der Versatz ist zeigt es recht deutlich

von Yalu X. (yalu) (Moderator)


Lesenswert?

Nicht so:
1
(unsigned int)(1<<(23-j))

und auch nicht so:
1
((unsigned int)1<<(23-j));

sondern so:
1
((unsigned long)1<<(23-j));

oder einfach so:
1
(1UL<<(23-j));

counter ist ja schließlich (wahrscheinlich aus gutem Grund) auch 
unsigned long.

von Peter M. (allforone)


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.

von Peter II (Gast)


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.

von Peter M. (allforone)


Lesenswert?

Ich trösel die einzelnen Shitfs jetzt mal auf, um es besser anschauen zu 
können.

von Peter II (Gast)


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 )

von Peter M. (allforone)


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...

von Yalu X. (yalu) (Moderator)


Lesenswert?

Peter II schrieb:
> er testet eh auf einen windows PC.

Ich habe das so verstanden, dass er den PC nur zur Kontrolle des 
Eregbnisses benutzt, kann mich aber täuschen.

von Peter M. (allforone)


Lesenswert?

Ja ich flashe erst, kann aber über den PC Breakpoints setzen und 
überwachen.

von Yalu X. (yalu) (Moderator)


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?

von Yalu X. (yalu) (Moderator)


Lesenswert?

Jan R. schrieb:
> counter |= (unsigned long) buffer_FPGA[0] << 23;

Wieso ist da jetzt ein '|=' drin? Das bedeutet ja, dass die 24 Bits auf 
buffer_FPGA mit dem Inhalt verodert wird, den counter 
zufälligerweise vorher schon hatte. Oder wird counter vorher auf 0 
gesetzt?

von Peter M. (allforone)


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.

von Yalu X. (yalu) (Moderator)


Lesenswert?

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

Kannst du mal posten, welcher Wert in counter vor Ausführung dieser 
Zeile steht und welcher danach?

von Peter II (Gast)


Lesenswert?

Yalu X. schrieb:
> Kannst du mal posten, welcher Wert in counter vor Ausführung dieser
> Zeile steht und welcher danach?

und noch wichtiger was in buffer_FPGA[12] steht, nicht das mal was 
anderes als 0 oder 1 drin steht.

von Peter M. (allforone)


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...

von Yalu X. (yalu) (Moderator)


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.

von Peter M. (allforone)


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.

von Yalu X. (yalu) (Moderator)


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.

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.