Forum: Mikrocontroller und Digitale Elektronik Inkrementieren von Bits in Bitfeldern


von Hans (Gast)


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:
1
static volatile struct{
2
    unsigned a:3;
3
    unsigned b:3;
4
    unsigned c:2;
5
  }status;
6
7
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.

von (prx) A. K. (prx)


Lesenswert?

Das wäre ein Fehler des Compilers. Welcher Compiler? Einfaches 
compilierbares Beispiel?

von Hans (Gast)


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?
1
static volatile struct{
2
      unsigned char a:3;
3
      unsigned char b:3;
4
      unsigned char c:2;
5
    }status;
6
7
int main(void){
8
  
9
10
    status.a = 0;
11
    status.b = 0;
12
    status.c = 0;
13
    status.a++;
14
}

Gruß,
Hans.

von (prx) A. K. (prx)


Lesenswert?

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

von Stefan E. (sternst)


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.

von Hans (Gast)


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. ;-)

von (prx) A. K. (prx)


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.

von Hans (Gast)


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.

von Simon K. (simon) Benutzerseite


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.

von mizch (Gast)


Lesenswert?

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

von Hans (Gast)


Lesenswert?

Stimmt, das wars.
Danke.

von Hans (Gast)


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

von Simon K. (simon) Benutzerseite


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.

von Karl H. (kbuchegg)


Lesenswert?

Welcher Compilerversion?

Habs hier mit der WinAvr-20090313 ausprobiert.
Der Assemblercode sieht gut aus
1
int main(void){
2
  
3
4
    status.a = 0;
5
  7c:  80 91 60 00   lds  r24, 0x0060
6
  80:  88 7f         andi  r24, 0xF8  ; 248
7
  82:  80 93 60 00   sts  0x0060, r24
8
    status.b = 0;
9
  86:  80 91 60 00   lds  r24, 0x0060
10
  8a:  87 7c         andi  r24, 0xC7  ; 199
11
  8c:  80 93 60 00   sts  0x0060, r24
12
    status.c = 0;
13
  90:  80 91 60 00   lds  r24, 0x0060
14
  94:  8f 73         andi  r24, 0x3F  ; 63
15
  96:  80 93 60 00   sts  0x0060, r24
16
    status.a++;
17
  9a:  90 91 60 00   lds  r25, 0x0060
18
  9e:  9f 5f         subi  r25, 0xFF  ; 255
19
  a0:  97 70         andi  r25, 0x07  ; 7
20
  a2:  80 91 60 00   lds  r24, 0x0060
21
  a6:  88 7f         andi  r24, 0xF8  ; 248
22
  a8:  89 2b         or  r24, r25
23
  aa:  80 93 60 00   sts  0x0060, r24
24
}
25
  ae:  80 e0         ldi  r24, 0x00  ; 0
26
  b0:  90 e0         ldi  r25, 0x00  ; 0
27
  b2:  08 95         ret

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

von (prx) A. K. (prx)


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.

von Hans (Gast)


Lesenswert?

So, jetzt hab glaube ich verstanden zu haben, was da vor sich geht.
1
static volatile struct{
2
    unsigned a:3;
3
    unsigned b:3;
4
    unsigned c:2;
5
  }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
1
static volatile struct{
2
    unsigned char a:3;
3
    unsigned char b:3;
4
    unsigned char c:2;
5
  }status;
funktioniert das Ganze.

Was sagt ihr dazu?

Gruß,
Hans.

von (prx) A. K. (prx)


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?

von Karl H. (kbuchegg)


Lesenswert?

Hans schrieb:

> Was sagt ihr dazu?

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

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
Noch kein Account? Hier anmelden.