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
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 | ...
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]; |
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 | }
|
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.
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?
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.
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?
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.
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.
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
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.
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.
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.
Ich trösel die einzelnen Shitfs jetzt mal auf, um es besser anschauen zu können.
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 )
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...
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.
Ja ich flashe erst, kann aber über den PC Breakpoints setzen und überwachen.
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?
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?
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.
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?
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.
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...
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.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.