Forum: Mikrocontroller und Digitale Elektronik Bit-Felder per structs verschachteln


von Jörg (Gast)


Lesenswert?

Hallo,

ich möchte mehrere TLC5948A LED Treiber ansprechen. Diese benutzen ein 
257Bit Shiftregister.

Bevor ich mir nun Funktionen schreibe, welche ein byte/bit an eine 
gewünschte Position in einem byte-Array schreiben, dachte ich kann man 
das evtl. auch mit bit-Feldern lösen.

Das folgende Beispiel, auf einem STM32F070 mit Atollic Studio erzeugt 
laut sizeof eine Größe von 2 Byte. Kann ich dem Compiler sagen, dass es 
das trotzdem in einem Byte packen darf/soll?
1
typedef struct{
2
  uint8_t MSB :  6;
3
} s_component;
4
5
typedef struct {
6
  uint8_t MSB1 :  1;
7
  s_component oTest;
8
  uint8_t MSB2 :  1;
9
} s_shiftregister;

Im weiteren Verlauf dachte ich dann an folgendes, doch auch diese Lösung 
erzeugt wesentlich mehr Bytes, als erwartet.
1
typedef struct{
2
  uint8_t MSB :  1;
3
  uint8_t u8Data[32];
4
} s_component;
5
6
typedef struct {
7
  s_component aoData[7];
8
} s_shiftregister;

Dass diese Lösung dann stark Compiler abhängig wäre, ist mir bewusst.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Meine in Serialisierung vorgestellte Library µSer kann genau das 
portabel.

https://github.com/Erlkoenig90/uSer

von Jörg (Gast)


Lesenswert?

Danke, aber ich benutze kein C++ und zusätzlich möchte ich für dieses 
Problem nicht unbedinkt eine fette Library einbinden.

von bssst (Gast)


Lesenswert?

Das was du evtl sucht ist:
1
__attribute__((packed))
 Aber pass auf, da gibt es noch so tolle Geschichten wie memory 
alignment

von Irgendwer (Gast)


Lesenswert?

Dir dürfte das padding und alignment der struct hier einen strich durch 
deinen Denkfehler machen.

https://en.wikipedia.org/wiki/Data_structure_alignment

Beim unteren Beispiel würde ich mindestens 33 x 7 Bytes erwarten...

In der vorhergehenden struct wird nach deinem einen Bit 7 Patting-Bits 
eingefügt weil sich der darauffolgende Typ ändert. Insgesamt sind es am 
ende immer ganze Bytes bzw. ein vielfaches davon die eine struct groß 
ist (C/C++ kennt eigentlich keine echten Bits als Datentyp).

Das aligment (wenn es denn größer als eine Byte ist) kannst du teilweise 
mit "packed" überschreiben.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

bssst schrieb:
> Das was du evtl sucht ist:

Das funktioniert nicht mit Bitfeldern.

Jörg schrieb:
> zusätzlich möchte ich für dieses
> Problem nicht unbedinkt eine fette Library einbinden.

Die Bibliothek ist sehr kompakt (1 Datei) und generiert nur das absolute 
Minimum an nötigem Code. Hier wäre ein Beispiel für deinen Fall:
1
#include <iostream>
2
#include <uSer.hh>
3
4
struct s_component {
5
  USER_STRUCT (s_component, uSer::AttrNone)
6
  
7
  USER_MEM(std::uint8_t, MSB, uSer::Width<6>)
8
9
  USER_ENUM_MEM (MSB)
10
};
11
12
struct s_shiftregister {
13
  USER_STRUCT (s_shiftregister, uSer::AttrNone)
14
  
15
  USER_MEM(std::uint8_t, MSB1, uSer::Width<1>)
16
  s_component oTest;
17
  USER_MEM(std::uint8_t, MSB2, uSer::Width<1>)
18
  
19
  USER_ENUM_MEM (MSB1, oTest, MSB2)
20
};
21
22
int main () {
23
  s_shiftregister sr;
24
  sr.MSB1 = 1;
25
  sr.MSB2 = 1;
26
  sr.oTest.MSB = 0xC;
27
  
28
  std::uint8_t raw [1];
29
  
30
  uSer::serialize (raw, sr);
31
  
32
  std::cout << std::hex << int { raw [0] } << std::endl;
33
}

Das Kompilat dieses Codes ist exakt identisch zu "std::cout << std::hex 
<< 0x99 << std::endl;" - also Null Overhead. Die Bibliothek ist auch 
C-Kompatibel, es muss nur 1 Datei mit C++ übersetzt werden.

von Jörg (Gast)


Lesenswert?

Irgendwer schrieb:
> Beim unteren Beispiel würde ich mindestens 33 x 7 Bytes erwarten...

Genau das passiert auch.

Irgendwer schrieb:
> Das aligment (wenn es denn größer als eine Byte ist) kannst du teilweise
> mit "packed" überschreiben.

Pakced bringt keine Veränderung.

von Mutluit M. (mutluit)


Lesenswert?

Weiss jetzt nicht auf Anhieb ob für dieses Problem relevant sein könnte, 
aber ich habe vor einigen Wochen C-Code für sizeof() und offsetof() für 
Bitfelder (insb. in structs) entwickelt (dabei heisst es ja man kann die 
C-Operatoren sizeof und offsetof nicht bei Bitfeldern benutzen, was ja 
auch stimmt; meine Lösung ist ein Workaround mit C-macros).
Falls Interesse besteht kann ich es hier posten.

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.