Forum: Mikrocontroller und Digitale Elektronik Bit's sind vertauscht


von Siegfried S. (dieleena)


Lesenswert?

Hallo,
Habe ein kleines Problem. Das Programm arbeitet einwandfrei, nur im 
Array(BusOutput) werden die Bit's seitenverkehrt angesprochen. z.B. Bit 
7 = Bit 0 bzw. Bit 0 = Bit 7.
Versuche mal in kurzform meine Zeilen dazustellen.

*****************
union BusOutput
{
  struct
  {
    unsigned Bit7:1;    //  Bit  7
    unsigned Bit6:1;    //  Bit  6
    unsigned Bit5:1;    //  Bit  5
    unsigned Bit4:1;    //  Bit  4
    unsigned Bit3:1;    //  Bit  3
    unsigned Bit2:1;    //  Bit  2
    unsigned Bit1:1;    //  Bit  1
    unsigned Bit0:1;    //  Bit  0
  };
  unsigned char Byte;
};

BusTransfer union BusOutput BusSpiOutput[MaxBusSpiInOut];
BusTransfer union BusOutput *OutputPointer;
****************
Prozess unsigned int *FifoAdresse[MaxFifoAdresse];
Prozess unsigned char FifoByte[MaxFifoAdresse];
****************
unsigned char BitVariable[8] =
{
  0b00000001,
  0b00000010,
  0b00000100,
  0b00001000,
  0b00010000,
  0b00100000,
  0b01000000,
  0b10000000
};
****************
#define WeSbh_01g() { FifoZeiger = (unsigned 
int*)(void*)&BusSpiOutput[0]; FifoBit = 0; }
****************

//
//  ---->>>>  in Fifo Buffer laden
WeSbh_01g();
FifoAdresse[FifoCount] = FifoZeiger;
FifoByte[FifoCount++] = FifoBit;
//
//  ---->>>>  auslesen und bearbeiten
FifoZeiger = FifoAdresse[ProzessCount];
FifoBit = FifoByte[ProzessCount];
*FifoZeiger = SET_BIT BitVariable[FifoBit];
oder
*FifoZeiger |= 1 << FifoBit;

Gruß Siegfried

von Roland Praml (Gast)


Lesenswert?

Hmm, und was ist deine Frage?

von Siegfried S. (dieleena)


Lesenswert?

Hallo,
versuche es mal einfach zu beschreiben.
hier definiere ich die zu bearbeite Adresse und dessen Bit fest.
hier das Array "BusSpiOutput[0]"
und hier die Bitnummer "FifoBit = 0"
#define WeSbh_01g() { FifoZeiger = (unsigned 
int*)(void*)&BusSpiOutput[0]; FifoBit = 0; }
Die Adresse von "BusSpiOutput[0]" sowie die Bitnummer wird zwischen 
gespeichert.

hiermit lese ich aus dem Array "FifoAdresse / FifoBit" die Adresse und 
die Bytenummer aus.
FifoZeiger = FifoAdresse[ProzessCount];
FifoBit = FifoByte[ProzessCount];

Bis hier funktioniert alles einwandfrei.

Wenn ich nachher auf diese Speicherzelle zugreife,
so
*FifoZeiger = SET_BIT BitVariable[FifoBit];
oder
*FifoZeiger |= 1 << FifoBit;

z.B. Wenn im FifoBit der wert 0 enthalten ist, wird statt Bit 0 Bit 7 
bearbeitet.

Bit
0 = 7
1 = 6
2 = 5
3 = 4
4 = 3
5 = 2
6 = 1
7 = 0

Gruß Siegfried

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Siegfried hat herausgefunden, daß die Anordnung von Bits in einem 
Bitfeld implementierungsabhängig ist.

Ein virtuelles Bier!

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Dreh doch mal die Definition in der unsäglichen Union herum.
So etwa:
1
union BusOutput
2
{
3
  struct
4
  {
5
    unsigned Bit0:1;    //  Bit  0
6
    unsigned Bit1:1;    //  Bit  1
7
    unsigned Bit2:1;    //  Bit  2
8
    unsigned Bit3:1;    //  Bit  3
9
    unsigned Bit4:1;    //  Bit  4
10
    unsigned Bit5:1;    //  Bit  5
11
    unsigned Bit6:1;    //  Bit  6
12
    unsigned Bit7:1;    //  Bit  7
13
  };
14
  unsigned char Byte;
15
};

Ich hasse diese Unions besonders, wenns auf die Bitebene heruntergeht...

von Simon K. (simon) Benutzerseite


Lesenswert?

Genauer: Die Reihenfolge der Bits hängt von der Endianess des Prozessors 
ab. Zumindest auf Compilerebene.

von Siegfried S. (dieleena)


Lesenswert?

Hallo,
schade, habe noch keinen Zapfhahn am Rechner.
Die Zeile "SET_BIT BitVariable[0 .. 7];" nutze ich mehrmals im Programm 
ohne Probleme.
Sollte es hieran liegen, Reihenfolge ?
union BusOutput
{
  struct
  {
    unsigned Bit7:1;    //  Bit  7
    unsigned Bit6:1;    //  Bit  6
    unsigned Bit5:1;    //  Bit  5
    unsigned Bit4:1;    //  Bit  4
    unsigned Bit3:1;    //  Bit  3
    unsigned Bit2:1;    //  Bit  2
    unsigned Bit1:1;    //  Bit  1
    unsigned Bit0:1;    //  Bit  0
  };
  unsigned char Byte;
};

Reihenfolge darf sich nicht ändern, da mein Programm die Byte komlett 
bearbeitet.

Gruß Siegfried

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> ...Anordnung von Bits in einem Bitfeld implementierungsabhängig ist.
> Ein virtuelles Bier!
Was heißt da eines? Da brauche ich viele, viele Biere,
um den Schmerz nicht so deutlich zu spüren.

Leute, tut euch und der Nachwelt einen Gefallen und verwendet keine 
Unions mit Bits. Der Code ist für Aussenstehende absolut unerklärlich. 
Und ob jeder Compiler das so gut packt, wage ich zu bezweifeln.
Darüber hinaus sind Unions keine impliziten Casts für die Umwandlung 
von einem Format in das Andere (z.B. Bit->Byte, Byte->Long, usw. usf.).

Eine Union wird Zielsystemabhängig implementiert.

von Der M. (steinadler)


Lesenswert?

Ihr macht den Siegfried klug und weise,
denn Bits in Unions, die sind schei..,
doch da er jetzt weiß, wie mans macht,
wird er auch nicht mehr ausgelacht.

von Olli R. (xenusion)


Lesenswert?

Und es heisst verdammt noch mal Bits und nicht Bit's.

von Siegfried S. (dieleena)


Lesenswert?

Hallo,
@Lothar Miller
erklär mir bitte, wie ich dieses ohne "union" machen kann. Ich habe es 
nicht so drauf.
Gruß Siegfried

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> Reihenfolge darf sich nicht ändern,
> da mein Programm die Byte komlett bearbeitet.
Tja, wenn die Karre schon im Dreck fstsitzt
hilft nur noch:
1
#define 0 7
2
#define 1 6
3
#define 2 5
4
#define 3 4
5
#define 4 3
6
#define 5 2
7
#define 6 1
8
#define 7 0
  ;-)

von Der M. (steinadler)


Lesenswert?

Bits kannst du so abfragen:
1
if((byteval & 1<<[Bit-Nummer]) != 0)
2
{
3
}

also eine UND-Verknüpfung.

von Benedikt K. (benedikt)


Lesenswert?

Lothar Miller wrote:

> Leute, tut euch und der Nachwelt einen Gefallen und verwendet keine
> Unions mit Bits. Der Code ist für Aussenstehende absolut unerklärlich.
> Und ob jeder Compiler das so gut packt, wage ich zu bezweifeln.

So pauschal würde ich das nicht sagen.
Nahezu bei jedem Compiler den ich kenne, wird sowas für die IO Register 
gemacht, um einzelne Portpins usw. ansprechen zu können.
Dies hat den Vorteil, dass man z.B.
#define LED PORTD.0
machen kann und dann später im Code
LED=1;
und
LED=0;
schreiben kann, was meiner Meinung nach den Code sehr viel besser lesbar 
(und vor allem wartbar) macht, als
PORD|=(1<<LED);
und
PORD&=~(1<<LED);

Ein weiterer Vorteil davon ist, dass die Unions von den meisten 
Compilern direkt in Bitoperationen übersetzt werden (falls es sowas in 
der Harware gibt), während PORTD|=(1<<LED) oft so übersetzt wird, wie es 
dasteht, nämlich in eine Lese, oder und Schreib Operation, was etwas 
langsamer ist.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

> erklär mir bitte, wie ich dieses ohne "union" machen kann.

Das habe ich doch gestern schon hier 
Beitrag "Re: Zeiger auf Array" gemacht.

von (prx) A. K. (prx)


Lesenswert?

Benedikt K. wrote:

> #define LED PORTD.0

Dann bitte wenigstens PORTD.bit0 oder so.

Besonders effektiv macht das Microchip. Da steht dann nämlich sowas 
ähnliches wie PortDbits.PortDbit0. Wenn man bei solchen Definitionen 
global die Modulkonfiguration einstellen will, wie in
   #define LED_PORT  D
   #define LED_E_BIT 4
und dies mit entsprechenden Präprozessor-Makros wie 
PORTBIT(LED_PORT,LED_E) dann in PORTDbits.PORTDbit4 unwandeln will, dann 
lernt man ziemlich viel über die Vor- und vor allen die Nachteile der 
Arbeitsweise des C-Präprozessors.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> Nahezu bei jedem Compiler den ich kenne, wird sowas für die IO Register
> gemacht, um einzelne Portpins usw. ansprechen zu können.

Richtig, aber genau dieser Teil eines Programms (IO) ist sowieso am 
schlechtesten zu portieren. Diese Stelle ist Hardware- und 
Compilerabhängig.
Denn der eine Prozessor hat einen PORTA, beim anderen ist das Port0 usw.
Zudem heißt es beim einen Compiler PORT_A, beim anderen PORTA...
D.h. genau an dieser Stelle muss ich sowieso was tun.

Wo es mich dann vollkommen unerwartet aus der Kurve wirft, ist wenn im 
'normalen' Programmablauf Datenkonvertierungen über Unions gemacht 
werden.

von Siegfried S. (dieleena)


Lesenswert?

Hallo,
habe festgestellt, das es keine Rolle spielt, wie man dieses schreibt.
union BusOutput
{
  struct
  {
    unsigned Bit7:1;    //  Bit  7
 ....
    unsigned Bit0:1;    //  Bit  0
  };
  unsigned char Byte;
};
oder
union BusOutput
{
  struct
  {
    unsigned Bit0:1;    //  Bit  0
 ....
    unsigned Bit7:1;    //  Bit  7
  };
  unsigned char Byte;
};

Der Compiler erkennt die erste Zeile als Bit 0 und die achte als Bit 7.
Übernehme wegen der besseren Übersicht das zweite Beispiel.

Hier kann ich die von Benedikt K. geschriebene Zeilen begrüßen.
Dies hat den Vorteil, dass man z.B.
#define LED PORTD.0
machen kann und dann später im Code
LED=1;
und
LED=0;

damit "#define WeSbh_01g() { FifoZeiger = (unsigned 
int*)(void*)&BusSpiOutput[0]; FifoBit = 0; }" habe ich mich einige Zeit 
beschäftigt, um den Ein- oder Ausgang Pin im Klartext ansprechen zu 
können.


@Lothar Miller
nicht für ungut. Wie soll ich mit "PORD|=(1<<LED);" die übersicht über 
in der ersten Ausbaustufe mit 320 Ein- oder Ausgang PIN behalten.

Gruß Siegfried

von Benedikt K. (benedikt)


Lesenswert?

Lothar Miller wrote:

> Richtig, aber genau dieser Teil eines Programms (IO) ist sowieso am
> schlechtesten zu portieren. Diese Stelle ist Hardware- _und_
> Compilerabhängig.

Gut, dann sind wir einer Meinung. Ich habe mir nämlich für den AVR auch 
solche Bitmakros für die Pins gebaut, denn nahezu jeder andere Compiler 
hat das schon integriert und da ist es etwas nervig beim Portieren, wenn 
man es ausgerechnet beim AVR anders machen muss.

von Simon K. (simon) Benutzerseite


Lesenswert?

Siegfried Saueressig wrote:
> Der Compiler erkennt die erste Zeile als Bit 0 und die achte als Bit 7.
> Übernehme wegen der besseren Übersicht das zweite Beispiel.
Oh mann, der Compiler erkennt gar nichts. Nur werden Bitfelder, je nach 
Endianess, entweder in die eine Richtung, oder in die andere abgebildet.

> @Lothar Miller
> nicht für ungut. Wie soll ich mit "PORD|=(1<<LED);" die übersicht über
> in der ersten Ausbaustufe mit 320 Ein- oder Ausgang PIN behalten.
Wo ist das Problem? Es ist auf jeden Fall "sauberer" (im Sinne von mehr 
standardkonform) Code.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

>  Wie soll ich mit "PORD|=(1<<LED);" die übersicht über
> in der ersten Ausbaustufe mit 320 Ein- oder Ausgang PIN behalten.

Meinst Du allen Ernstes, daß das übersichtlicher wird, wenn Du den 
Dingern 320 verschiedene Namen gibst?

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.