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.
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?
_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.
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
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:
1 | #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:
1 | SBI DDRB, PB5 |
nur numerisch wäre es dann:
1 | SBI 0x04, 0x20 |
statt derzeit
1 | 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.
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...
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
Shadow schrieb: > aber was wenn ich doch im vim bin? > hab da noch keine textschnippel-funktion... :help abbreviations
> :help abbreviations
ah, danke, spiel ich gleich mal mit rum.
Und ich hab gestern snipMate gefunden, werd ich auch noch probieren.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.