Forum: Mikrocontroller und Digitale Elektronik Bitumwandlung


von Jack (Gast)


Lesenswert?

Hallo,
ich bekomme 16 bit durch 2 x 8 bit Werte parallel eingelesen. Das mache 
ich über den PortC. Allerdings sollen meine 16 bit, nach dem kombinieren 
von den beiden 8 bit, dann auch direkt im 2er Komplement umgewandelt 
werden.
Oder anders gesagt, die beiden 8 bit sind unsigned und die möchte ich in 
eine 16 bit signed umwandeln

Mein Code:
1
  uint8_t VarPortCHigh = 0;
2
  uint8_t VarPortCLow = 0;
3
  int16_t VarC = 0;  
4
5
  VarPortCHigh = PINC;     //High Byte speichern
6
        
7
  //umschalten auf low
8
9
  VarPortCLow = PINC;     //Low Byte speichern
10
11
  VarC = VarPortCHigh * 256 + VarPortCLow;

Kurze Frage:
Ist das so korrekt? Bekomme ich so meine Werte zwischen -32768 und 
+32767 für VarC?

Danke

von Ralf (Gast)


Lesenswert?

Einfach mal durch den Simulator schicken.

von Random .. (thorstendb) Benutzerseite


Lesenswert?

LOL :-)

256 + 256 = ??? **grins*

val16 = (val8_high << 8) | val8_low;

von Random .. (thorstendb) Benutzerseite


Lesenswert?

TheMagicStruct (TM):
1
typedef struct {
2
  union {
3
    uint32_t val16;
4
5
    struct {
6
      char val8_l;
7
      char val8_h;
8
    }
9
  }
10
} CONVERT;
11
12
CONVERT val;
13
14
val.val8_l = 0x55;
15
val.val8_h = 0xaa;
16
17
if(val16 == 0xaa55) {
18
  ...
19
}

Hoffe, ich hab mich auf die schnelle jetzt nicht vertippt :-)

---
Edit:
VarC = VarPortCHigh * 256 + VarPortCLow;

da hab ich mich doch glatt was überverlesen :-)

von Klaus W. (mfgkw)


Lesenswert?

Random ... schrieb:
> if(val16 == 0xaa55) {

besser: if(val.val16 == 0xaa55) {

von Random .. (thorstendb) Benutzerseite


Lesenswert?

**autsch** :-)

Für (signed int) musst du das ganze noch mit -32k umrechnen.

von J.-u. G. (juwe)


Lesenswert?

@Random...
Warum eine derartige Verschachtelung von struct und union?
1
union { int16_t i16;
2
        char    u8[2];} val;
3
4
val.u8[0] = 0x55;
5
val.u8[1] = 0xaa;
6
7
if(val.i16 == 0xaa55) {
8
  ...
9
}

von Random .. (thorstendb) Benutzerseite


Lesenswert?

... weil man es dann mit Intellisense schöner sieht :-)

ka ... viele Wege führen nach ROM.

Aber ... wie machst du aus 2 * U8 einen I16? Magic Smoke? **grins**

von Jack (Gast)


Lesenswert?

danke erstmal...

ich möchte es gerne möglichst einfach haben und den structs und anderen 
aus dem weg gehen

1. Zuerst, ist mein Code nun falsch oder nicht?

2.
Ist das
VarC = VarPortCHigh * 256 + VarPortCLow;
nicht gleich dem
val16 = (val8_high << 8) | val8_low;

3.
Random ... schrieb:
> Für (signed int) musst du das ganze noch mit -32k umrechnen.

Was meinst du damit?


Danke

von J.-u. G. (juwe)


Lesenswert?

Random ... schrieb:
> Aber ... wie machst du aus 2 * U8 einen I16? Magic Smoke? **grins**

Leider hat der OT nicht angegeben woher seine U8 kommen. Für mein 
Beispiel ging ich deshalb davon aus, das irgendwo ein i16 erzeugt wird 
(Sensor) und dann HByte und LByte getrennt übertragen werden und wieder 
zusammengebastelt werden sollen.

von Ralf (Gast)


Lesenswert?

J.-u. G. schrieb:

> union { int16_t i16;
> char    u8[2];} val;

Das ist das Einfachste!

von Onkel Willi (Gast)


Lesenswert?

Jack schrieb:
> ich möchte es gerne möglichst einfach haben und den structs und anderen
> aus dem weg gehen

Warum fragst du dann überhaupt nach einer Lösung, wenn Lernresistenz 
dein Grundprinzip ist?

von Michael (Gast)


Lesenswert?

Jack schrieb:
> 2.
> Ist das
> VarC = VarPortCHigh * 256 + VarPortCLow;
> nicht gleich dem
> val16 = (val8_high << 8) | val8_low;
´
Vom Ergebnis sollte bei "*256" VarC=VarPortCLow rauskommen. Bei "<< 8" 
kommt es drauf an, wie du die Variablen deklariert hast.
Und wenn Code dann erstmal so ist, wie du es meinst, dann hängt es vom 
Compiler und den Oprimierungseinstellungen ab, ob beide Versionen für 
den Prozessor den gleichen Rechenaufwand bedeuten.
MfG

von Jack (Gast)


Lesenswert?

Alelrdings habe ich noch ein Problem, vielleicht habe ich mich durch 2er 
Komplement falsch ausgedrückt. Jedenfalls möchte ich folgendes 
erreichen:

8bit low= 0b00000000
8bit high=0b00000000
zusammen 16 bit signed = 0   //Stimmt, bei mir 0

8bit low= 0b01111111
8bit high=0b11111111
zusammen 16 bit signed = 32767  //Stimmt, bei mri 32767

8bit low= 0b11111111
8bit high=0b11111111
zusammen 16 bit signed = -32768   //Falsch, bei mir kommt -1

und das ist unabhänig von union oder val16 = (val8_high << 8) | 
val8_low;

ich will also die Minus-Skala gedreht haben
wie rechne ich das für mich richtig um?

Danke


Onkel Willi schrieb:
> Warum fragst du dann überhaupt nach einer Lösung, wenn Lernresistenz
> dein Grundprinzip ist?

Das hat damit überhaupt nichts zu tun, der Code soll auch noch anderen 
weiterhelfen und union ist nunmal unübersichtlich und erstmal nicht 
direkt durchschaubar (für das nicht so geübte Auge)
Ich musste auch erst nochmal wieder nachschauen.


Achja, bei dem Code oben fehlen noch zwei ; (Abschluss union und struct)

von Klaus W. (mfgkw)


Lesenswert?

Jack schrieb:
> 8bit low= 0b11111111
> 8bit high=0b11111111
> zusammen 16 bit signed = -32768   //Falsch, bei mir kommt -1

Lauter gesetzte Bit sind bei 2er-Komplement immer -1, nicht -32768

-32768 wäre 0b1000000000000000

von Jack (Gast)


Lesenswert?

ich weiß, deswegen habe ich ja oben geschrieben

Jack schrieb:
> vielleicht habe ich mich durch 2er
> Komplement falsch ausgedrückt

kennt trotzdem jemand eine gescheite Umwandlung für mein Vorhaben?

von Karl (Gast)


Lesenswert?

Wenn das oberste bit bei dem 16bit unsigned Wert gesetzt ist, musst du 
von diesem Wert noch 32768 abziehen um auf 16bit signed zu wandeln.

von Karl (Gast)


Lesenswert?

1
val16 = ((val8_high&0x7f) << 8) | val8_low;
2
if ( val8_high & 0x80 )
3
    val16 = -val16;

von Jack (Gast)


Lesenswert?

Sauber, genau so soll es sein

Danke

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.