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
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
Siegfried hat herausgefunden, daß die Anordnung von Bits in einem Bitfeld implementierungsabhängig ist. Ein virtuelles Bier!
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...
Genauer: Die Reihenfolge der Bits hängt von der Endianess des Prozessors ab. Zumindest auf Compilerebene.
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
> ...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.
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.
Hallo, @Lothar Miller erklär mir bitte, wie ich dieses ohne "union" machen kann. Ich habe es nicht so drauf. Gruß Siegfried
> 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
|
;-)
Bits kannst du so abfragen:
1 | if((byteval & 1<<[Bit-Nummer]) != 0) |
2 | {
|
3 | }
|
also eine UND-Verknüpfung.
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.
> erklär mir bitte, wie ich dieses ohne "union" machen kann. Das habe ich doch gestern schon hier Beitrag "Re: Zeiger auf Array" gemacht.
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.
> 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.
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
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.
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.
> 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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.