Ich bin in Mikrocontroller-Hacking und während ich mich sehr gut mit bitweisen Operatoren und sprechen direkt auf die Hardware bin, finde ich den resultierenden Code sehr ausführlich und Standard. Der Programmierer auf höherer Ebene in mir möchte eine effektive, aber effiziente Methode finden, ihn zu bereinigen.Ein C-Präprozessor-Makro, um Bitfelder in ein Byte zu packen?
Zum Beispiel gibt es eine Menge von Setzen von Flags in den Registern:
/* Provided by the compiler */
#define SPIE 7
#define SPE 6
#define DORD 5
#define MSTR 5
#define CPOL 4
#define CPHA 3
void init_spi() {
SPCR = (1 << SPE) | (1 << SPIE) | (1 << MSTR) | (1 << SPI2X);
}
Zum Glück gibt es Makros, die tatsächlich Port IO-Operationen (die linke Seite) verstecken, so sieht es aus wie eine einfache Aufgabe. Aber diese ganze Syntax ist für mich chaotisch.
Anforderungen sind:
- es nur auf 8 Bits zu handhaben bis hat,
- die Bit-Positionen müssen in der Lage sein, in beliebiger Reihenfolge übergeben werden, und
- nur Bits sein erfordern setzen soll bestanden.
Die Syntax Ich mag würde, ist:
SPCR = Bits (SPE, SPIE, MSTR, SPI2X);
Das Beste, was ich mit so weit kommen habe, ist eine Combo-Makro/Funktion:
#define bits(...) __pack_bits(__VA_ARGS__, -1)
uint8_t __pack_bits(uint8_t bit, ...) {
uint8_t result = 0;
va_list args;
va_start(args, bit);
result |= (uint8_t) (1 << bit);
for (;;) {
bit = (uint8_t) va_arg(args, int);
if (bit > 7)
break;
result |= (uint8_t) (1 << bit);
}
}
Das auf meinem speziellen architecure zu 32 Bytes kompiliert nimmt und 61-345 Zyklen (wie viele hängt auszuführen Bits wurden übergeben).
Idealerweise sollte dies im Präprozessor erfolgen, da das Ergebnis eine Konstante ist, und die Maschinenausgabeanweisungen sollten nur eine Zuweisung eines 8-Bit-Werts zu einem Register sein.
Kann dies besser gemacht werden?
, das wahrscheinlich ist, was ich schon von der Architektur-spezifische Compiler-Unterstützung definiert werden, wenn nicht für die Bit-Position Definitionen tun würde (in diesem Fall avr-gcc). Ziemlich dumm, denke ich. Wenn es irgendwo gibt, müssen sie anders als als Linkshänder-Argument verwendet werden ... Ich kann es nicht finden. Aber es ist was es ist. –
Auch der Code, den ich bisher gesehen habe, variiert zwischen der Verwendung von 1 << XX Formular und _BV (XX). _BV ist ein bereitgestelltes Makro, das (1 << n) tut. Aber das bedeutet immer noch zu viel tippen. –
gute Idee. aber aus Sicherheitsgründen würde ich einige Klammern hinzufügen um n #define BIT (n) (0 <<< Sie wissen, Makros können böse sein. Stellen Sie sich vor, jemand benutze das Makro mit BIT (5-1) ... – Roland