mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Inkrementieren von Bits in Bitfeldern


Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo uC-Gemeinde,

ich habe ein Problem mit dem Inkrementieren eines oder mehrerer Bits in 
einem Bitfeld.

Folgender Code inkrementiert alle Member des Bitfelds:

static volatile struct{
    unsigned a:3;
    unsigned b:3;
    unsigned c:2;
  }status;

status.a++;


status.a += 1; funktioniert auch nicht.

Die direkte Zuweisung eines Wertes hingegen funktioniert.

Kann mir jemand sagen warum?

Vielen Dank im Voraus.

Gruß,
Hans.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das wäre ein Fehler des Compilers. Welcher Compiler? Einfaches 
compilierbares Beispiel?

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo A.K.,

der Compiler ist der gcc. Ich glaube nicht, dass der Fehler hier liegt.
Hier dein kompilerbares Beispiel.

Hab leider keine echte Hardware da, aber kann es sein, dass der 
Simulator des AVR-Studios einen Bug hat?
static volatile struct{
      unsigned char a:3;
      unsigned char b:3;
      unsigned char c:2;
    }status;

int main(void){
  

    status.a = 0;
    status.b = 0;
    status.c = 0;
    status.a++;
}

Gruß,
Hans.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Woran erkennst du in diesem Beispiel, dass das ganze Byte inkrementiert 
wird? Es wird so oder so 1 rauskommen.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Debugger im Studio wird vermutlich mit Bitfeldern einfach nichts 
anzufangen wissen. Deshalb wird er dir für alle drei (a, b und c) den 
Wert des kompletten Bytes als Inhalt präsentieren.

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Woran erkennst du in diesem Beispiel, dass das ganze Byte inkrementiert
> wird? Es wird so oder so 1 rauskommen.

Ich schau mir die einzelnen Member im AVR-Simulator an.
"Es wird so oder so 1 rauskommen" -> Versteh grad nicht, was genau du 
mit dieser Aussage meinst...

@Stefan:
Mit der Aussage könnte ich schon mehr anfangen. ;-)

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hans schrieb:

> "Es wird so oder so 1 rauskommen" -> Versteh grad nicht, was genau du
> mit dieser Aussage meinst...

Vorher:
  a = 0, b = 0, c = 0. Byte = 0.
Nachher:
  a = 1, b = 0, c = 0. Byte = 1.

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Hans schrieb:
>
>> "Es wird so oder so 1 rauskommen" -> Versteh grad nicht, was genau du
>> mit dieser Aussage meinst...
>
> Vorher:
>   a = 0, b = 0, c = 0. Byte = 0.
> Nachher:
>   a = 1, b = 0, c = 0. Byte = 1.

Ok, das wäre das, was ich erwartet hätte. Der AVR-Simulator sagt aber 
folgendes:

Vorher:
   a = 0, b = 0, c = 0.
Nachher:
   a = 1, b = 1, c = 1.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, weil:

Stefan Ernst schrieb:
> Der Debugger im Studio wird vermutlich mit Bitfeldern einfach nichts
> anzufangen wissen. Deshalb wird er dir für alle drei (a, b und c) den
> Wert des kompletten Bytes als Inhalt präsentieren.

Autor: mizch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Inkrementiere mal b.  Wenn dann 8 angezeigt wird, siehst Du das ganze 
Byte, nicht das Bitfeld.

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stimmt, das wars.
Danke.

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich nochmal.
Ich habs es gerade nochmal auf der echten Hardware ausprobiert.
Da ist es genauso.
Der Fehler muss also doch woanders liegen...
Hat jemand ne Idee?

Gruß,
Hans

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hä? Was ist da genau so? Natürlich werden die 3 Bitfeldvariablen in 
einem Byte gespeichert, wieso sollte das auch anders sein?

Es funktioniert alles wie du willst.

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

Bewertung
0 lesenswert
nicht lesenswert
Welcher Compilerversion?

Habs hier mit der WinAvr-20090313 ausprobiert.
Der Assemblercode sieht gut aus
int main(void){
  

    status.a = 0;
  7c:  80 91 60 00   lds  r24, 0x0060
  80:  88 7f         andi  r24, 0xF8  ; 248
  82:  80 93 60 00   sts  0x0060, r24
    status.b = 0;
  86:  80 91 60 00   lds  r24, 0x0060
  8a:  87 7c         andi  r24, 0xC7  ; 199
  8c:  80 93 60 00   sts  0x0060, r24
    status.c = 0;
  90:  80 91 60 00   lds  r24, 0x0060
  94:  8f 73         andi  r24, 0x3F  ; 63
  96:  80 93 60 00   sts  0x0060, r24
    status.a++;
  9a:  90 91 60 00   lds  r25, 0x0060
  9e:  9f 5f         subi  r25, 0xFF  ; 255
  a0:  97 70         andi  r25, 0x07  ; 7
  a2:  80 91 60 00   lds  r24, 0x0060
  a6:  88 7f         andi  r24, 0xF8  ; 248
  a8:  89 2b         or  r24, r25
  aa:  80 93 60 00   sts  0x0060, r24
}
  ae:  80 e0         ldi  r24, 0x00  ; 0
  b0:  90 e0         ldi  r25, 0x00  ; 0
  b2:  08 95         ret

Lass dir mal ein List-File erzeugen und sieh nach, was der Compiler 
daraus gemacht hat

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Hans: Vermutlich hast du den gleichen defekten Debugger diesmal auf die 
echte Hardware gehetzt. Naturgemäss mit dem gleichen Ergebnis. Nicht die 
Simulator-Engine ist das Problem, sondern der entweder darauf oder auf 
der echten Hardware aufsitzende Debugger.

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, jetzt hab glaube ich verstanden zu haben, was da vor sich geht.
static volatile struct{
    unsigned a:3;
    unsigned b:3;
    unsigned c:2;
  }status;
Für das Struct werden im Speicher 8Bit reserviert. (Erkennbar an den 
daraufolgenden Speicheradressen)

Komischerweise, liest das AVR-Studio 16 Bit ein.
Ich habe aber 2 dieser Structs nebeneinander im Speicher, daher liest er 
wenn Struct1 und Struct2 ist 257 als Wert für Struct1 ein.

Der Fehler ist nicht nur im Simulator, sondern auf dem Atmel läuft der 
Zugriff auch falsch ab, weil Abfragen auf Struct1 == 1 dann falsch 
ausgewertet werden.

Mit
static volatile struct{
    unsigned char a:3;
    unsigned char b:3;
    unsigned char c:2;
  }status;
funktioniert das Ganze.

Was sagt ihr dazu?

Gruß,
Hans.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bis zum Beweis des Gegenteils glaube ich dem Compiler und misstraue der 
Variablenanzeige des Debuggers. Probier mal mit der ursprünglichen 
Version
   volatile unsigned temp;
   ...
   status.a++;
   temp = status.b;
und schau danach rein, was in temp steht. Vermutlich der korrekte Wert.

M.a.W: Du kämpfst grad gegen Gepenster. Weder Compiler noch Simulator 
noch Hardware machen etwas falsch, sondern die Anzeige der Daten ist 
falsch. Hast du wohlmöglich den Optimizer eingeschaltet?

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

Bewertung
0 lesenswert
nicht lesenswert
Hans schrieb:

> Was sagt ihr dazu?

All das was A.K. auch schon gesagt hat.
Plus: Bitfelder werden sowieso überbewertet

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.