Forum: Compiler & IDEs Definition von 2 Bit in einem 8bit Register


von Julien M. (ljminti)


Lesenswert?

Hallo

Ich schreibe mir gerade eine Register und Bit definition für den 
PCA9635.

nun um 1 Bit zu definieren sage ich

#define test   1

Was mache ich aber wenn sich eine Variable über 2 bits ersterecken soll?

Beispiel:

Register XYZ

A3 [7:6]    /Bit 7 und 6
A2 [5:4]
A1 [3:2]
A0 [1:0]

und A1 kann die Zustände 00, 01, 10 und 11 annehmen

Im Quellcode möchte ich jetzt sagen können

A0 = 1 // A0 = 01
A2 = 3 // A2 = 11

XYZ |= (1<A1)|(1<A3)   // XYZ = 0b00110001

Ist dies irgendwie lösbar?

Gruß Julien





von j-x (Gast)


Lesenswert?

in c++ gehts so:

xyz = (a3<<6)+(a2<<4)+(a1<<2)+a0

von Julien M. (ljminti)


Lesenswert?

ja dann machst du ja ein Bit-Shift

Aber dadurch ist A1 etc. immer noch nicht definiert

von j-x (Gast)


Lesenswert?

auslesen wär dann so (zumindest in c++ gehts nicht anders)
int a1= (xyz&0b00001100)>>2; //ob man das & braucht weis ich nicht

von Ronny (Gast)


Lesenswert?

Zunächst ein Makro um aus einem gegebenem Bit die entsprechende Zahl zu 
machen:

#define BIT(x) (1<<x)

Nun kann man ein Bit SETZEN:

a |= BIT(y);    // setzt das Bit Nr y in der Variable a

und natürlich auch löschen:

a &= ~BIT(y);   // löscht das Bit Nr y in der Variable a


Hintergrund sind die Wahrheitstabellen der bitweisen Operationen,die 
sollte man sich mal näher anschauen.

x   y   x UND Y   x ODER y x XOR y
0 | 0 |    0    |    0   |   0
1 | 0 |    0    |    1   |   1
0 | 1 |    0    |    1   |   1
1 | 1 |    1    |    1   |   0

Zusammenfassend: Mit logisch ODER wird gesetzt,mit logisch UND wird 
gelöscht/maskiert und mit exklusiv-oder kann man Bits toggeln.

von Julien M. (ljminti)


Lesenswert?

@ Ronny:

Jaja die Wahrheitstabellen und setzten löschen ist mir ja alles klar :=
Ist ein alter Hut.

Jedoch ist mein Kernproblem nicht das Setzen oder löschen.

also XYZ |= variable a

Mein Problem ist ja dass ich eben diese Variable a definieren möchte.
und dies kann 4 Zustände annehmen. Diese zustände sind aber egal.

Siehe Oben:

A3 [7:6]    / A3 definiert Bit 7 und 6
A2 [5:4]
A1 [3:2]
A0 [1:0]

Ich will ja nahher nur noch sagen A3 ist ...
und dann

XYZ |= A3   // --> XYZ wird mit A3 oder verknüpft

Die Schwierigkeit liegt NUR dabei A3 zu definieren!!

Gruß

von Karl H. (kbuchegg)


Lesenswert?

Nachdem ich im 2.ten Anlauf immer noch nicht kapiert
habe, wo dein Problem liegt, rate ich einfach mal.

Du bist auf der Suche von Bitfeldern:

struct Irgendwas {
  unsigned char A0:2;
  unsigned char A1:2;
  unsigned char A2:2;
  unsigned char A3:2;
}

struct Irgendwas MyByte;

MyByte.A3 = 3;    // setzt die Bits 6 und 7 in MyByte

Allerdings: Bitfelder werden oft glorreich überschätzt.
Mit ein paar speziellen Makros ist man meist besser
bedient. Vor allem deswegen weil man sich bewusst macht,
dass zum setzen dieser Bits ein paar Bit-Operationen
notwendig sind, die einem bei einem Bitfeld der Compiler
'under the hood' macht.

von Julien M. (ljminti)


Lesenswert?

@Karl Heinz:

Vielen Dank, genau das hab ich gesucht. :)

In wie weit würde sich dies jetzt auch mit einem Makro lösen lassen?
Wenn es elegantere Methoden gibt bin ich auch für diese offen :)

Gruß Julien

von Karl H. (kbuchegg)


Lesenswert?

#define SET_A3(x,y)    ((x)&0b00111111)|(((y)&0b00000011)<<6))


  unsigned char a;
  SET_A3( a, 3);

setzt in a die A3 Bits auf 3

Wenn du die union Lösung nimmst, macht der Compiler auch
nichts anderes als dieses UND/ODER Monster da oben.

von Julien M. (ljminti)


Lesenswert?

Hallo ich habe mal versucht das an einem konkreten Beispiel umzusetzen.
Leider Ohne erfolg

LEDOUT0 ist ein register des PCA9635
1
#define LEDOUT0    0x14
2
3
struct leds0_3 {
4
  unsigned char LDR0:2;
5
  unsigned char LDR1:2;
6
  unsigned char LDR2:2;
7
  unsigned char LDR3:2;
8
} 
9
10
struct leds0_3 LEDOUT0;

vielleicht gibt es da noch einen Kniff den ich nicht kenne?
Geht das überhaupt wenn ich später folgednes ausführen möchte?

LEDOUT0.LDR2 = 2

wenn LEDOUT0 gar keinen Datentyp hat?

Gruß

von Karl H. (kbuchegg)


Lesenswert?

Wieso soll LEDOUT0 keinen Datentyp haben?
Es hat duch einen. Es ist vom Typ "struct leds0_3"

> LEDOUT0 ist ein register des PCA9635

Das kann dann allerdings so nichts werden. Denn irgendwie
muss ja noch die Verknüpfung zu diesem Register hergestellt
werden. Wenn das ein memory mapped Register ist, dann
kann man das so machen

struct leds0_3 * LEDOUT0 = 0xund_hier_die_Adresse_vom_Register;

*LEDOUT0.LDR2 = 2;

In allen anderen Fällen, wird das aber wohl nichts werden.

Ich sagte doch, dass dieses Bitgepfriemel über Bitfelder
überschätzt wird.

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.