Hallo, ich habe ein 2 Dimensionales Array gsDataBuffer[][] aus 8bit Integer Zahlen. An einer Stelle, die zb. so aussieht: ... 0_ _0_ _0_ _0_ _1_ _1_ _1_ _1 ; 1_ _1_ _1_ _1_ _1_ _1_ _1_ _1 ; ... möchte ich nun 12 Stellen (die mit den 1ern) zu einer 12bit langen Zahl verknüpfen und in einer 16bit Variablen speichern. Als Wert (value) sollte dieser herauskommen 2^12 -1 = 4095 (entspricht 12bit) Dazu folgender Code: Die 2. Dimension (column) ist hier konstant ########################################### ... uint16_t value; uint16_t data_low, data_high; uint8_t position = numChannels - 1 - ((row*3)+color); uint8_t posarray = position*3/2; ... data_high = (((uint16_t)gsDataBuffer[posarray][column])&(15UL)); //liest die ersten 4bit der "oberen" 8bit Zahl ein. posarray++; data_low = ((uint16_t) gsDataBuffer[posarray][column]); //liest alle 8bit der "unteren" 8bit Zahl ein. value = (data_high<<8) + data_low; //Addieren return(value); ########################################### Leider erhalte ich als Ergebnis immer nur das "Low Byte" mit 0b11111111. Wo kann hier der Fehler liegen? Vielen Dank schonmal
Wenn man in C von einem Element im Feld zum direkt darauffolgenden im Speicher kommen will, muß man den letzten Index erhöhen, nicht den ersten.
Außerdem liest du doch die oberen Bit aus einer niedrigeren Adresse; in deiner Skizze ist es aber anders gezeichnet.
Außerdem: woher kommt dein 00001111? Ist das vielleicht versehentlich als 11110000 im Speicher?
Gerade ging es in einem anderen Thread um ein ähnliches Problem. Mit Hilfe einer union sollte sich das ganze ohne Rechnerei erledigen lassen.
1 | union { uint16_t u16; |
2 | uint8_t u8[2];} value; |
3 | |
4 | value.u8[0] = gsDataBuffer[posarray][column]; |
5 | value.u8[1] = gsDataBuffer[posarray][column+1]; |
6 | |
7 | return(value.u16); |
PS: Die Namen der Indexvariablen sollten natürlich passender gewählt werden.
In dieser Skizze, ist die Dimension "column" konstant,
es sind 2 "aufeinanderfolgende" 8bit Zahlen der Dimension "posarray" zu
sehen
...
0_ 0_ _0_ _0_ _1_ _1_ _1 _1 ; // 1
1_ 1_ _1_ _1_ _1_ _1_ _1 _1 ; // 2
...
Die niederwertigen 4Bit der 1. 8bit Zahl sollen die höchstwertigen der
12bit Zahl werden.
Die 8bit der 2. 8bit Zahl sollen die niederen 8bit der 12bit Zahl
werden.
Ausprobiert habe ich folgendes:
union { uint16_t u16;
uint8_t u8[2];} value;
value.u8[1] = (gsDataBuffer[posarray][column]&15);
posarray++;
value.u8[0] = gsDataBuffer[posarray][column];
return(value.u16);
Das Ergebnis bleibt leider immernoch das Selbe?
Vielen Dank euch schonmal für die Hilfe!
Tobi M. schrieb: > Die niederwertigen 4Bit der 1. 8bit Zahl sollen die höchstwertigen der > 12bit Zahl werden. > Die 8bit der 2. 8bit Zahl sollen die niederen 8bit der 12bit Zahl > werden. Dann geht das mit der 'union' nicht, würde ich mal sagen. Da muss die Byteorder stimmen (im Speicher sortiert von niedrigem zu hohem Byte). Probiere mal: 1. ein kurzes Programm, wo nichts anderes gemacht wird, als 'Werte umzuwandeln'. Kannste ja mal hier reinstellen. Ich glaube der Fehler liegt wo anders. Tobi M. schrieb: > uint8_t position = numChannels - 1 - ((row*3)+color); > uint8_t posarray = position*3/2; ... sieht mir nicht so gelungen aus: 'posarray' ergibt sich nicht aus einer Berechnung ohne Rest. (Kann aber gewollt sein, der Rest ist dann ein Offset, oder so) 2. wenn's geht: Die Anordnung der Daten ändern. Jede Zelle ist dann vom Typ 'union xxx'.
Ralf schrieb: > Dann geht das mit der 'union' nicht, würde ich mal sagen. Da muss die > Byteorder stimmen (im Speicher sortiert von niedrigem zu hohem Byte). Ganz im Gegenteil, mit Hilfe einer union kann man doch die Speicherreihenfolge von HByte und LByte an die benötigte Byteorder anpassen.
J.-u. G. schrieb: > Ralf schrieb: >> Dann geht das mit der 'union' nicht, würde ich mal sagen. Da muss die >> Byteorder stimmen (im Speicher sortiert von niedrigem zu hohem Byte). > > Ganz im Gegenteil, mit Hilfe einer union kann man doch die > Speicherreihenfolge von HByte und LByte an die benötigte Byteorder > anpassen. Vielleicht meinen wir was Verschiedenes:
1 | union
|
2 | {
|
3 | uint16_t W; |
4 | struct
|
5 | {
|
6 | uint8_t L,H; |
7 | }
|
8 | }
|
Im Speicher stehen jetzt L und H hintereinander, was ja automatisch W ergibt. Ablauf: Daten aus dem Array nach L und H übernehmen. W lesen. Das geht. Ich hätte jetzt versucht die Originaldaten für die 'union' schon zurechtzumachen (also Low- und High-Byte vertauschen), dann muss man nur noch lesen. Außer, ich habe mal wieder einen Denkfehler drin :-(
Ralf schrieb: > Vielleicht meinen wir was Verschiedenes: Offensichtlich. Ich meine das, was ich bereits hier Beitrag "Re: 12bit Integer aus 8bit Array lesen" beschrieben habe.
1 | union { uint16_t u16; |
2 | uint8_t u8[2];} value; |
3 | |
4 | value.u8[0] = DatenByte1; |
5 | value.u8[1] = DatenByte2; |
Je nachdem ob DatenByte1 oder DatenByte2 das höherwertige ist, muss die Zuordung zu value.u8[0] bzw. value.u8[1] erfolgen.
J.-u. G. schrieb: > Je nachdem ob DatenByte1 oder DatenByte2 das höherwertige ist, muss die > Zuordung zu value.u8[0] bzw. value.u8[1] erfolgen. Genau. Dann kann man sich den Umweg über die Union allerdings sparen und den 16Bit-Wert mit Shift und Or gleich zusammensetzen. Da allerdings dort offensichtlich was nicht funktioniert, vermute ich, liegt der Fehler in der Indizierung des Arrays.
Ralf schrieb: > Genau. Dann kann man sich den Umweg über die Union allerdings sparen und > den 16Bit-Wert mit Shift und Or gleich zusammensetzen Ja, meistens gibt es mehrere Wege zum selben Ziel und jeder kann einen für sich passenden aussuchen. Ich arbeite in Fällen wie hier lieber mit der union, weil man meist ohne Operationen, sondern nur mit Zuweisungen auskommt. Ich sehe darin auch keinen Umweg. Ralf schrieb: > Da allerdings > dort offensichtlich was nicht funktioniert, vermute ich, liegt der > Fehler in der Indizierung des Arrays. Das vermute ich auch.
1 | for(i=0;i<=7;i++) { |
2 | result = result + (myValue[0][x]<<i); |
3 | x--; |
4 | }
|
5 | |
6 | x=7; |
7 | |
8 | for(i=0;i<=7;i++) { |
9 | High = High + (myValue[1][x]<<i); |
10 | x--; |
11 | }
|
12 | |
13 | result = result + (High<<8); |
Zu kompliziert? Ich weiß^^.
Julian Schild schrieb: > for(i=0;i<=7;i++) { > result = result + (myValue[0][x]<<i); > x--; > } > > x=7; > > for(i=0;i<=7;i++) { > High = High + (myValue[1][x]<<i); > x--; > } > > result = result + (High<<8); > Zu kompliziert? Der TO möchte sein Ergebnis aus 2 Werten des Arrays zusammenbasteln, nicht aus 16. Die beiden Werte sind im Array so gespeichert, dass der zweite Index (bei Dir x) für beide gleich ist.
Tobi M. schrieb: > Das Ergebnis bleibt leider immernoch das Selbe? Hm, der Code sieht eigentlich OK aus. Aber vielleicht steht ja nicht das richtige im Array ? Hast du mal data_high und data_low direkt ausgegeben ? Das einzige was ich im original-Code seltsam fand ist die Konstante "15UL", also unsigned long. Vermutlich ist long mindestens 32 bit, aber es wird nur mit 16 bit Werten hantiert => ? Ich wurde einfach 15U schreiben (obwohl der Compiler eventuell das ganze durchschaut und den selben Code generiert ?) ZigZeg
J.-u. G. schrieb: > Der TO möchte sein Ergebnis aus 2 Werten des Arrays zusammenbasteln, > nicht aus 16. Verstehe ich das richtig. Er will einfach nur zwei 8 Bit Zahlen in einer 16 Bit Zahl vereinen? Lol. Wo ist das Problem?
1 | uint8_t Var1 = 0, Var2 = 0; |
2 | uint16_t Result = 0; |
3 | |
4 | Result = Var1 + (Var2<<8); |
Voila. :P Whs hab ich es schon wieder falsch verstanden^^.
Julian Schild schrieb: > Verstehe ich das richtig. Er will einfach nur zwei 8 Bit Zahlen in einer > 16 Bit Zahl vereinen? So habe ich es auch verstanden. Julian Schild schrieb: > uint8_t Var1 = 0, Var2 = 0; > uint16_t Result = 0; > > Result = Var1 + (Var2<<8); Das wäre eine Möglichkeit und so hat es der TO auch versucht. Julian Schild schrieb: > Wo ist das Problem? Um das Problem einzugrenzen benötigen wir noch weitere Informationen des TO. Es könnte an dem 2D-Array liegen, in dem die beiden 8-Bit-Zahlen gespeichert sind.
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.