Forum: Mikrocontroller und Digitale Elektronik 12bit Integer aus 8bit Array lesen


von Tobi M. (Gast)


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

von Tobi M. (Gast)


Lesenswert?

PS: Controller ist ein Atmega644p , programmiert mit AVR Studio (Avr 
gcc)

von Klaus W. (mfgkw)


Lesenswert?

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.

von Klaus W. (mfgkw)


Lesenswert?

Außerdem liest du doch die oberen Bit aus einer niedrigeren Adresse; in 
deiner Skizze ist es aber anders gezeichnet.

von Klaus W. (mfgkw)


Lesenswert?

Außerdem: woher kommt dein 00001111? Ist das vielleicht versehentlich 
als 11110000 im Speicher?

von Michael (Gast)


Lesenswert?

Ohne zu rechne, ließe sich das evtl. geschickt mit einer
1
union
 lösen
Beitrag "Re: Bitumwandlung"

von J.-u. G. (juwe)


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

von J.-u. G. (juwe)


Lesenswert?

@Michael

Den Thread meinte ich.

von J.-u. G. (juwe)


Lesenswert?

PS:
Die Namen der Indexvariablen sollten natürlich passender gewählt werden.

von Tobi M. (Gast)


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!

von Ralf (Gast)


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

von J.-u. G. (juwe)


Lesenswert?

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.

von Ralf (Gast)


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 :-(

von J.-u. G. (juwe)


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.

von Ralf (Gast)


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.

von J.-u. G. (juwe)


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.

von Nn N. (jaytharevo)


Lesenswert?

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

von J.-u. G. (juwe)


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.

von Kai S. (zigzeg)


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

von Nn N. (jaytharevo)


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

von J.-u. G. (juwe)


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.

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.