www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Bit's sind vertauscht


Autor: Siegfried Saueressig (dieleena)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Praml (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmm, und was ist deine Frage?

Autor: Siegfried Saueressig (dieleena)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

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

Ein virtuelles Bier!

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dreh doch mal die Definition in der unsäglichen Union herum.
So etwa:
union BusOutput
{
  struct
  {
    unsigned Bit0:1;    //  Bit  0
    unsigned Bit1:1;    //  Bit  1
    unsigned Bit2:1;    //  Bit  2
    unsigned Bit3:1;    //  Bit  3
    unsigned Bit4:1;    //  Bit  4
    unsigned Bit5:1;    //  Bit  5
    unsigned Bit6:1;    //  Bit  6
    unsigned Bit7:1;    //  Bit  7
  };
  unsigned char Byte;
};

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

Autor: Simon K. (simon) Benutzerseite
Datum:

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

Autor: Siegfried Saueressig (dieleena)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Der Micha (steinadler)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Olli R. (xenusion)
Datum:

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

Autor: Siegfried Saueressig (dieleena)
Datum:

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

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

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

Autor: Der Micha (steinadler)
Datum:

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

also eine UND-Verknüpfung.

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Siegfried Saueressig (dieleena)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.