Bit's sind vertauscht

OP #998950
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
OP #998991
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
Moderator (Firma: Titel) Persönliche Seite #998995
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...
OP #999003
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
Moderator (Firma: Titel) Persönliche Seite #999005
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.
#999044
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.
#999063
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.
Moderator (Firma: Titel) Persönliche Seite #999069
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.
OP #999073
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
#999076
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.
Persönliche Seite #999079
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.

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