12bit Integer aus 8bit Array lesen

Gast #2263344
Lesenswert?

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
#2263371
Lesenswert?

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);
Gast #2263425
Lesenswert?

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!
Gast #2264247
Lesenswert?

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'.
Gast #2264313
Lesenswert?

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 :-(
#2264335
Lesenswert?

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.
Gast #2264346
Lesenswert?

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.
#2264356
Lesenswert?

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.
#2264960
Lesenswert?

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.
#2264981
Lesenswert?

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
#2265050
Lesenswert?

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^^.
#2265127
Lesenswert?

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.

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