mikrocontroller.net

Forum: Compiler & IDEs Struktur Bitfeld in Variable kopieren


Autor: bernd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Tag

Ich schlag mich so ein bisschen mit Strukturen herum und bin etwas 
genervt.
Genaugenommen geht es im Bitfeldern die ich so definiert habe.

int main()
  {
    struct
    {
      unsigned char status:1; // 1 Bit für bStatus_1
      unsigned char status1:1; // 1 Bit für bStatus_1
      unsigned char status2:1; // 1 Bit für bStatus_1
      unsigned char status3:1; // 1 Bit für bStatus_1
      unsigned char status4:1; // 1 Bit für bStatus_1

    } byte;


  while(1)
    {
    }
  }

Das funktioniert aus soweit ganz gut, mit bit.status1 u.s.w kann ich 
alles mit den bits machen.

Jetzt dachte ich ich könnte die so veränderten bits nun in den Porta 
schreiben.
Also PORTA = byte; // Der Inhalt von byte wird in den PORTA kopiert

geht aber nicht?? Warum, oder wie geht das kopieren.

Danke

Autor: Werner B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PORTA = *((unsigned char *)&byte);

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oder mit einer union... Man muss sich aber bei beiden Varianten klar 
darüber sein, dass der C-Standard nicht definiert, in welcher 
Reihenfolge die Bits in einem Bitfeld abgelegt werden. Ausprobieren...

Autor: OliverSo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die union-Variante geht dann z.B. so:
  union
  {
  struct
    {
      unsigned char  status:1;
      unsigned char  status1:1;
      unsigned char  status2:1;
      unsigned char  status3:1;
      unsigned char  status4:1;
    };
    unsigned char byte;
  } bit_byte;

 bit_byte.status = 1;
 PORTA = bit_byte.byte;

Oliver

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OliverSo wrote:
> Die union-Variante geht dann z.B. so:
> [...]
Exakt. Der AVR-GCC legt übrigens afaik die einzelnen Bitfeld-Elemente 
"von hinten" ab, also das erste Element des Bitfeldes (im Beispiel 
status ) am niederwertigen Ende des Bytes (also im Bit Nummer 0).

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die genannte Variante ist IMHO nicht portabel, sondern eine GCC-
Erweiterung.  Die portable Variante müsste der bitfield-struct
noch einen Namen geben:
union
{
struct
  {
    unsigned char  status:1;
    unsigned char  status1:1;
    unsigned char  status2:1;
    unsigned char  status3:1;
    unsigned char  status4:1;
  } bits;
  unsigned char byte;
} bit_byte;

 bit_byte.bits.status = 1;
 PORTA = bit_byte.byte;

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörg Wunsch wrote:
> Die genannte Variante ist IMHO nicht portabel, sondern eine GCC-
> Erweiterung.  Die portable Variante müsste der bitfield-struct
> noch einen Namen geben:
Stimmt natürlich. Das hatte ich übersehen. Funktioniert das ohne Namen 
im GCC tatsächlich?

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johannes M. wrote:

> Funktioniert das ohne Namen
> im GCC tatsächlich?

Ja. ;-)

http://gcc.gnu.org/onlinedocs/gcc-4.2.3/gcc/Unname...

Autor: bernd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, schon mal danke, ich werde die Sachen mal ausprobieren. Ich finde 
es ein bisschen Schade das gcc von Standarts abweicht die sich bei 
(teuren) Compilern so eingebürgert haben. Z.B. macht Keil das mit " 
#byte " und " #bit ". Das ist sehr einfach und spart Programmierarbeit. 
Habe bisher die Assembler Technik genutzt und Bits numeriert um sie 
später mit einem Byte zu maskieren. Aber mit "if(Byte & (1<<Bit)) u.s.w" 
bricht man sich die Finger.

unsigned int abzukürzen ist ja ganz toll, aber uint16_t ist auch nicht 
der Hit, wenn man nicht blind zehn Finger schreiben kann.

Zugegeben haben Strukturen mehr Möglichkeiten, aber bits zu setzen finde 
ich so wichtig das man den Elektrotechniker und Nichtinformatiker ein 
bisschen unterstützen sollte.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
bernd wrote:
> Hallo, schon mal danke, ich werde die Sachen mal ausprobieren. Ich finde
> es ein bisschen Schade das gcc von Standarts abweicht die sich bei
> (teuren) Compilern so eingebürgert haben.
Falsch ! Das sind eben keine Standards, sondern willkürliche 
Erweiterungen einiger kommerzieller Embedded-C-Compiler, die nicht vom 
ANSI-Standard abgedeckt sind. Außerdem kocht da praktisch jeder Anbieter 
sein eigenes Süppchen, weshalb die Sachen auch bei einer Plattform 
i.d.R. nicht portierbar sind.

Der AVR-GCC ist im Großen und Ganzen ein ANSI-C-Compiler, der zwar 
mittlerweile auch einige µC-spezifische Erweiterungen bietet, die für 
notwendig bzw. wirklich sinnvoll erachtet wurden (z.B. Eingabe von 
Binärzahlen mit 0bxxxx), die aber vom ANSI-Standard nicht abgedeckt 
werden. Ansonsten kommt man gar nicht erst in Versuchung, Code zu 
schreiben, den andere C-Compiler nicht verstehen. Hier im Forum tauchen 
des öfteren Anfragen auf nach dem Motto "Hilfe! Habe Programm für 
Compiler XYZ geschrieben und es lässt sich mit Compiler ZYX nicht 
compilieren...". Die Standard-konformen Schreibweisen versteht jeder 
C-Compiler, der den Namen zu Recht trägt. Einzige Ausnahme bilden dann 
allerdings trotz allem die µC-spezifischen Bibliotheksfunktionen.

Die meisten "Vereinfachungen" der kommerziellen Compiler täuschen auch 
darüber hinweg, was im Hintergrund abläuft. Und das kann gerade bei 
Hardware-nahen Anwendungen schonmal zu langen Fehlersuchen führen, wenn 
man als Programmierer nicht mal weiß, was da eigentlich passiert.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
bernd wrote:

> später mit einem Byte zu maskieren. Aber mit "if(Byte & (1<<Bit)) u.s.w"
> bricht man sich die Finger.
....
> Zugegeben haben Strukturen mehr Möglichkeiten, aber bits zu setzen finde
> ich so wichtig das man den Elektrotechniker und Nichtinformatiker ein
> bisschen unterstützen sollte.

Was hindert dich daran, dir selbst mit Standard-C ein paar
Hilfsfunktionen bzw. Makros zu schreiben, so dass du dir nicht
mehr die Finger brichst?

Im Übrigen wird die reine Tipparbeit überschätzt. Das Problem
beim Programmieren ist ja nicht das Drücken von Tasten sondern
die Logik die es umzusetzen gilt.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
bernd wrote:

> Aber mit "if(Byte & (1<<Bit)) u.s.w"
> bricht man sich die Finger.

Das eigentliche Übel ist, dass die Bitkonstanten nicht gleich als
Masken definiert worden sind, sondern als Bitnummern.  Das wiederum
hat seine Ursache darin, dass die entsprechenden Bitnamen auch in
Assemblercode verwendbar sein sollten, und dass dort Befehle wie
CBI oder SBI eine Bitnummer brauchen.  Von einer Nummer auf eine
Maske ,,rechnen'' ist trivial, eine Maske in eine Nummer zurückzu-
rechnen leider nicht.

Du kannst dir das 1<< ja in einem Makro vereinfachen.  avr-libc bietet
dir dafür den Makro _BV() bereits vorgefertigt an.

> unsigned int abzukürzen ist ja ganz toll, aber uint16_t ist auch nicht
> der Hit, wenn man nicht blind zehn Finger schreiben kann.

Das ist aber C99-Standard.  Es hat nichts mit ,,abkürzen'' zu tun,
sondern besagt, dass der entsprechende Datentyp unabhängig von der
verwendeten Umgebung eben genau 16 bits breit (und vorzeichenlos)
ist.  Das ist für "unsigned int" nicht gegeben, das kann durchaus auch
32 bits breit sein.

Autor: bernd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK OK OK
mit Standarts meinte ich jetzt nicht das es quasi genormt ist, sondern 
wie ja schon gesagt wurde sich um -> sinnvolle <- Erweiterungen handelt, 
die aber bei jeden teuern Compiler eben vorhanden sind.

Ich habe das mal ausprobiert und die Strukturen lassen sich nicht 
vernümftig watchen. Es wird bei jedem Bit der Byte Wert angezeigt.
Zum Debuggen mist, da sich die Bits auch nicht immer mit den Werten 
setzen lassen (1,2,4,8 u.s.w).
Ach ja, ich nutze AVR Studio mit gcc.

Werde wohl doch wieder maskieren. Son shit. Habe mal einem Informatiker 
über die Finger geschaut, da bekommt man ja Augenkrebs. Die nehmen auch 
für alles Bytes, ist ja auch egal.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Pssss bernd

Ist jetzt nicht wirklich wichtig, aber es heist Standard. Hinten
mit 'd'.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
bernd wrote:

> wie ja schon gesagt wurde sich um -> sinnvolle <- Erweiterungen handelt,
> die aber bei jeden teuern Compiler eben vorhanden sind.

Du kennst ,,jeden teuren'' Compiler?

Ich kenne zumindest einen, der zu den teuersten zählt (und vom
generierten Code her zu den besten), aber der hält sich mit allem
an den C-Standard und die durch den Standard vorgegebenen
Syntaxregeln der Sprache.  Das bedeutet nicht, dass er keine
Erweiterungen hätte (die hat wohl jeder Compiler), aber er bewegt
sich mit seinen Erweiterungen (genauso wie GCC) zumindest im durch
den Standard vorgegebenen Rahmen.

Autor: bernd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das in Foren immer sofort gestritten werden muss kann ich echt nicht 
nachvollziehen, und einige scheinen Deutschlehrer zu sein. Dabei braucht 
man nachgewiesener Maßen nur Anfangs und Endbuchstaben eines Wortes um 
den Satz lesbar zu machen. Da finde ich es schwierieger sinnlos 
herunterzuscrollen um eine richtige Antwort zu finden.

Wer sich noch fürs Thema interessiert:
Keil Compiler 8051 und MPLap für Pics z.B. besitzen die #Bit und #Byte 
Befehle. Standar(d) hin oder her, es zählt was sich durchsetzt und 
sinnvoll ist. Und das ist struct bei bitfelder in keinster Weise, 
zumindest nicht bei 8Bit Prozessoren. Ob das Kernigham und Ritchi so 
wollten ist denen wahrscheinlich ebenso egal wie mir.

Die Frage steht also noch im Raum ob es eventuell duch eine .h eine 
bessere Lösung gibt die auch in AVR Studio debugged werden kann. bools 
mit endsprechende .h benutzen ja auch immer 1Byte.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
bernd wrote:

> Keil Compiler 8051 und MPLap für Pics z.B. besitzen die #Bit und #Byte
> Befehle. Standar(d) hin oder her, es zählt was sich durchsetzt und
> sinnvoll ist.

Und wer definiert, was sich ,,durchgesetzt'' hat?  Irgendwelche
mittelprächtigen Compiler?

Keil hat mich vor knapp 20 Jahren mal über einen Arbeitstag gekostet
um rauszufinden, dass sie in ihrer OS-9-Version für den m68k nicht
in der Lage waren, mit Variablen in geschachtelten Blöcken ordentlich
umzugehen (der Platz wurde nicht während des gesamten Funktionslaufs,
sondern erst am Beginn des Blocks auf dem Stack eingeräumt, dann aber
nie wieder ausgeräumt).  Irgendjemand bestätigte mir kürzlich, dass
dieses Problem immer noch existiere...

Durchgesetzt?  Durchgesetzt hat sich wohl ganz eindeutig GCC, und
IAR sicher auch.  Für Keil kenne ich außer Peter Dannegger (und von
mir aus dir) kaum einen, der sich über dessen Qualitäten begeistert
geäußert hätte, dafür aber genügend, die mir gesagt haben, dass sie
froh sind, dieses Teil dank GCC (und Wechsel von MCS51 weg) nicht
mehr benutzen zu müssen.  IAR hat zumindest insgesamt eine sehr gute
Reputation (und einen extremen Preis), und das interessanterweise,
obwohl er mit Erweiterungen wohl eher sparsam umgeht.

Autor: bernd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe nie behauptet das ich die Programmer unheimlich toll finde. Es 
ist die eine Funktion.
Ich muss Beruflich Pics, AVRs und Fujitsus Programmieren und mich 
zwangsläufig auch mit den Compilern auseinandersetzen. Dafor hatte ich 
es eben mit Keil und diverser damaligen "Puplic Domain" Software zu tun.
Alle hatten Qualitäten und Nachteile.

Das es AVR Studio nicht auf die Reihe bekommt beim watchen auch eine Bit 
Anzeige zu machen ist ein weiteres Manko.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
bernd wrote:

> Ich habe nie behauptet das ich die Programmer unheimlich toll finde.

(Programmer?  Oder Compiler?)

...aber bescheinigst ihnen, dass sich da irgendeine ihrer Erweiterungen
,,durchgesetzt'' hätte...

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.