mikrocontroller.net

Forum: Compiler & IDEs Bit value _BV ??????? AVR-libc


Autor: Calik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo.

Ich bin ein Neuling im Bereich AVR. wenn ich es richtig verstanden
habe, steht in der AVR-libc, das man mit diesem macro "_BV" einzelne
Bits in besonderen Registern setzen kann, z.B. für USART : UCRSB =
_BV(Bit-name);.

Wird Bit dann logisch high?

Die Frage hört sich zwar blöd an (setzt Bits = logisch high), aber dann
lese ich weiter und da steht "DDRD = _BV(PD7); //make PD7 an output".

Wird hier PD7 auch gleichzeitig gesetzt?
____________________________________________________________________

Also heisst das explizit:

1. Ich kann mit _BV Eingänge und Register-Bits setzen und
2.  "   "    "   "  Pins zum output machen.

?????????????????????????????????????????????????????????
____________________________________________________________________

Danke.

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Jan Le (flednanders)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
habe gerade das selbe problem wie der threadsteller, aber der link ist 
nich mehr verfügbar. Kann mir jemand helfen? was macht _BV() jetzt 
genau?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
_BV ist nur ein Makro, welches den Ausdruck 1 << Bitnummer kapselt

#define _BV(bit)   (1 << (bit))


Was auch immer man damit dann weiter macht, hat mit _BV nichts zu tun.

Das Setzen bzw. Löschen von Bits machen die |= bzw. &= ~ Operationen


   register |= ( 1 << Bitnummer );   // bit setzen
   register &= ~( 1 << Bitnummer );  // bit löschen


ob man das jetzt so schreibt, oder ob man es so schreibt

   register |= _BV( Bitnummer );
   register &= ~ _BV( Bitnummer );

schenkt sich nichts. Denn nach der Makroersetzung von _BV kommt erst mal 
exakt das gleiche raus. Der Threadersteller interpretiert in das _BV 
Makro etwas hinein, was es nicht leistet. Er hat nicht verstanden, was 
an den ganzen Bit-Operationen der wesentliche Kernpunkt ist, der das 
gewünschte leistet und was nur Schreiberleichterung ist.

Es ist als ob man sagen würde:

Die Fläche eines Rechtecks errechnet sich zu

  Fläche = Länge * Breite

definiere ich mir statt dessen ein Makro
#define AREA(l,b)  (l*b)
und schreibe

  Fläche = AREA(Länge, Breite)

kann ich dann mit AREA auch die Fläche eines Kreises ausrechnen?

Es ist nicht die Multiplikation an sich oder dieses Makro, die die 
Fläche berechnet. Es ist die komplette Operation, die das für ein 
Rechteck macht. Und es ist völlig egal, ob ich da einen Teil dieser 
Operation in einem Makro verstecke oder nicht.

Autor: Bernd S. (bernds1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Beispiel:
PORTB |= _BV(PB7);

macht das gleiche wie:
PORTB |= 1<<PB7;

Nur eine andere Schreibweise. Wobei ich die zweite bevorzuge, weil man 
dort schon am Operator sieht, was gemacht wird. Nämlich eine 1 um 7 
Stellen nach links geschoben.

Gruß Bernd

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eine Zahl erzeugen, die die als Parameter übergebene Bitnummer als
einziges Bit gesetzt hat.

Wenn der Parameter eine Konstante ist, ist das Ergebnis ebenfalls
eine Konstante.

Das ist keine weitere Magie als ganz simpel:
#define _BV(x) (1 << (x))

Hintergrund ist, dass beim AVR alle Bitnamen für die IO-Register
nur in Bitnummern auflösen.  Das hat man seinerzeit wohl so gewählt,
damit man einen dummen Assembler bauen kann, der die Bitnummern in
seinen SBI- und CBI-Befehlen direkt als Operand angeben kann.(*)
Da man in C jedoch nicht mit Bitnummern direkt arbeiten kann, sondern
immer Bitmasken benutzen muss, haben in der Folge alle C-Programmierer
nun die idiotische Aufgabe, für jede Bitnummer die zugehörige Maske
zu errechnen.  Man hat also zugunsten eines dummen Assemblers alle
C-Programmierer mit Strafarbeit versorgt (und das, obwohl eigentlich
von vornherein C das Primat für diese Controller haben sollte …).

(*) Es wäre kein Problem gewesen, diese Definition anders aufzuziehen
und die Bits gleich als Masken zu definieren.  Symbolisch ändert sich
gar nichts:
SBI  DDRB, PB5
nur numerisch wäre es dann:
SBI  0x04, 0x20
statt derzeit
SBI  0x04, 5

Für einen Assembler sollte es eine Kleinigkeit sein, das Argument
0x20 dahingehend zu überprüfen, dass genau 1 Bit im Bereich 0 bis
7 darin gesetzt ist, und dann dessen Nummer in den Opcode zu
übernehmen.

Autor: Jan Le (flednanders)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen dank für die ausführlichen erklärungen

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bernd S. schrieb:
> Beispiel:
> PORTB |= _BV(PB7);
>
> macht das gleiche wie:
> PORTB |= 1<<PB7;
>
> Nur eine andere Schreibweise. Wobei ich die zweite bevorzuge, weil man
> dort schon am Operator sieht, was gemacht wird. Nämlich eine 1 um 7
> Stellen nach links geschoben.

Wobei die erste Schreibeise den Vorteil hat, dass Anfänger nicht zu 
konstrukten wie
 PORTB |= 0 << PB7;
verleitet werden, wenn sie ein Bit löschen wollen...

Autor: Shadow (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und und möchte lieber _BV() schreiben, weil mein kleiner Finger bei << 
nicht so zielsicher ist.
vielleicht mach ich mir aber noch Textschnippsel in gedit für
(1<< )
aber was wenn ich doch im vim bin?
hab da noch keine textschnippel-funktion...
wobei mir _ und großbuchstaben auch wieder nerven, vielleicht doch 
wieder ein eigenes #define wie bv oder sbit odersowas

Autor: Andreas B. (andreas_b77)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Shadow schrieb:
> aber was wenn ich doch im vim bin?
> hab da noch keine textschnippel-funktion...

:help abbreviations

Autor: Shadow (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> :help abbreviations
ah, danke, spiel ich gleich mal mit rum.
Und ich hab gestern snipMate gefunden, werd ich auch noch probieren.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.