Ich versuche, die Best Practices bei der Registerzuordnung zu befolgen. Ich habe ein analoges MAX30001-Frontend für EKG-Anwendungen ( Datenblatt ) und auf Seite 38 gibt es eine Tabelle, die Benutzerbefehle und Registerkarten enthält: 32 Wörter mit jeweils 24 Informationsbits. Soll ich Strukturen oder Makros verwenden?
Verwendung von Strukturen mit Bitfeldern:
typedef struct {
volatile uint8_t Bit0 : 1;
volatile uint8_t Bit1 : 1;
volatile uint8_t Bit2 : 1;
volatile uint8_t Bit3 : 1;
// ...
// and so on
// ...
volatile uint8_t Bit23 : 1;
} foo;
Verwendung von Makros:
#define STATUS (*(volatile uint32_t*)0x01))
Im allgemeinen Fall, in dem Sie speicherabgebildete Register haben, sollten Sie Bitfeldstrukturen immer vermeiden. Dies liegt daran, dass diese vom C-Standard sehr schlecht spezifiziert sind. Grundlegende Dinge, von denen Sie annehmen könnten, dass sie spezifiziert sind, sind es nicht. Dazu gehören Bit-Reihenfolge, Byte-Reihenfolge, Padding & Alignment.
Außerdem uint8_t
ist unter anderem Typen nicht einmal ein zulässiger Typ in Bitfeldern! Sie können nur int
Typen verwenden, wenn int
zählt als signiert oder unsigniert ist auch nicht angegeben ...
Zusammenfassend lässt sich sagen, dass Bitfelder schrecklich unzuverlässig sind und Sie der Compiler-Implementierung (falls vorhanden) ausgeliefert sind, wenn Sie sie verwenden.
Was Sie stattdessen tun sollten, ist, immer Adress- und Bitmaskenmakros zusammen mit den bitweisen Operatoren zu verwenden. Diese sind zu 100 % gut definiert und portabel.
Der MAX30001 verwendet eine SPI-Schnittstelle. Es ist kein speicherabgebildetes Gerät, daher sind hier weder Strukturen noch Makros verwendbar.
Alles, was Sie sinnvollerweise tun können, ist, eine Reihe von Makros zu definieren, um die Registernummern und einzelne Bits darin darzustellen, z.
#define MAX30001_NO_OP 0x00
#define MAX30001_STATUS 0x01
#define MAX30001_STATUS_EINT 0x800000
#define MAX30001_STATUS_EOVF 0x400000
#define MAX30001_STATUS_FSTINT 0x200000
// etc
Selbst für speicherabgebildete Geräte ist es im Allgemeinen am besten, Bitfelder (wie Bit0:1
) zu vermeiden. C-Compiler handhaben sie oft schlecht und geben nur wenige Garantien darüber, wie Bitfelder in eine Struktur gepackt werden. Verwenden Sie Makros, um einzelne Bits innerhalb eines einzelnen Registers darzustellen.
Nick Alexejew
jsotola
Pryda