Forum: Mikrocontroller und Digitale Elektronik AVR-GCC: warum eigentlich _BV verwenden?


von Micha (Gast)


Lesenswert?

Neulich bin ich in einem Quelltext über die Verwendung von _BV 
gestolpert, einem Präprozessor-Macro, das aus einer Pin-Nr. per shift 
die entsprechende Bitmaske zaubert, wie ich durch googeln herausgefunden 
habe, also etwa so:
1
# define LED_PIN 3
2
3
...
4
5
PORTx |= _BV(LED_PIN);

In dem Artikel wurde behauptet, dass es empfehlenswert ist, die Pins 
zunächst direkt per Nummerierung zu definieren und dann eben _BV zu 
verwenden. Allerdings wurde nicht begründet warum.
Ich mach das bisher immer so:
1
#define LED_PIN 0b00001000
2
3
...
4
5
PORTx |= LED_PIN;
für mich erschliesst sich der Grund nicht, was an der Version oben 
besser sein soll. Gibt es einen triftigen Grund, oder ist das am Ende 
einfach nur Geschmackssache?

von Sebastian H. (technik_freak)


Lesenswert?

Hallo,

Ich könnte mir vorstellen, dass _BV(x) das selbe macht, wie (1 << x).

Deine Variante mit der Darstellung eines ganzen Bytes entspricht dabei 
auch der Schreibweise (1<<3), aber (1<<3) ist etwas besser zu lesen als 
00001000, vor allem kann man sich weniger verschreiben, da eine 
vergessene 0 zu einem anderen Ergebnis fürhren kann als gewollt.

von Micha (Gast)


Lesenswert?

genau: _BV produziert mittels Verschieberei aus der Nummer des Bits die 
entsprechende Maske.

Selber hab ich bisher dazu tendiert zu denken, es ist am Ende 
Geschmackssache, wie man das handhabt. Bis ich heute beim programmieren 
drüber gestolpert bin, dass das ganze vorgefertigte Zeugs in AVR-GCC 
eben mit Pin-Nummern als symbolische Namen arbeitet, die man dann noch 
per shift zu Masken umwandeln muss. Wenn man es mit eigenen Konstrukten 
auf die andere Art angeht und beide Vorgehensweisen im Projekt 
vermischt, kommt man schnell in Teufels Küche...

von Detlev T. (detlevt)


Lesenswert?

Diese Headerdateien sind halt schon ein bisschen älter. Bei den XMegas 
werden in der Regel beides definiert, die Nummer UND eine Bitmask.

Das könntest du ja übernehmen in der Form
1
#define LED_PIN     3
2
#define LED_PIN_bm (1<<LED_PIN)

Die Nummer ist sicher nützlich, wenn es ums shiften geht, sollte man 
also idR auch definieren.

von Nosnibor (Gast)


Lesenswert?

Die Bitnummern statt Masken kommen aus dem Assemblerbereich: der AVR hat 
eigene Befehle um einzelne Bits in den Portregistern zu setzen und zu 
löschen. Im Assemblerquelltext muß man dazu die Bitnummer angeben, also 
sind die Bits im Headerfile mit ihrer Nummer (anstatt Maske) definiert.
Wenn man jetzt das gleiche Headerfile auch für C verwenden will, geht 
die Bitschieberei los, weil C mit Bitnummern direkt nichts anfangen 
kann. _BV ist eine Möglichkeit, diese Schiebeoperation, die ja mit dem 
Programm nichts zu tun hat und auch nicht wirklich stattfindet, zu 
verstecken, damit der Quelltext übersichtlicher wird.

von Karl H. (kbuchegg)


Lesenswert?

Nicht nur das.
Aus den Bitnummern die jeweiligen Masken zu erzeugen ist trivial.
Aber die Umkehrung, aus der Maske die Bitnummer zu extrahieren (selbst 
wenn in der Maske tatsächlich nur ein einziges Bit gesetzt ist), die ist 
nicht trivial.

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.