In AVR-Tutorials sehe ich oft:
DDRA |= (1 << PA0);
PORTA |= (1 << PA0);
verwendet statt:
DDRA |= PA0;
PORTA |= PA0;
Was ist der Zweck davon?
PA0
wird als 0 definiert, also die folgende Zeile:
DDRA |= (1 << PA0);
Entspricht dem Verschieben von 1 um null Bits nach links, wobei ein ODER mit dem Wert 1 übrig bleibt, um das erste Bit zu setzen. Während die folgende Zeile:
DDRA |= PA0;
Führt ein OR mit Null durch, ändert also die Register überhaupt nicht.
DDRA |= 1
. Erwarten sie , dass PA0
sie sich in verschiedenen Umgebungen ändern werden?DDRA |= 72;
oder DDRA |= (1<<PA6) | (1<<PA3);
?|= 128
sinnvoller als |= (1 << 7)
. Woher wissen Sie, dass das 7. Bit gesetzt wird, wenn Sie sich Werte wie 128 ansehen?PA0
es nicht sehr beschreibend ist, was es tatsächlich tut.Warum tun sie das? Wahrscheinlich, weil alle anderen, die sie um Hilfe bitten oder von denen sie gelernt haben, es so gemacht haben. Und weil die Standarddefinitionen seltsam gemacht sind.
Das Verschieben um eine Zahl, typischerweise eine Dezimalzahl, verschiebt diesen Wert um so viele Binärstellen. 1 << PA0
verschiebt sich um 1 PA0
nach links. Da PA0
0 ist, gibt es keine Verschiebung. Aber gegebene 1 << 6
1 wird zu 0b1000000. Gegeben 13 << 6
wird 13, binär 0b1101, um 6 verschoben, um 0b1101000000 oder 832 zu werden.
Jetzt müssen wir sehen, wie PA0 - PA7 definiert sind. Diese werden normalerweise in dem spezifischen Header für Ihren spezifischen Mikrocontroller definiert, der über io.h oder portpins.h enthalten ist
#define PA7 7
#define PA6 6
~
#define PA1 1
#define PA0 0
Sie sind als ihre numerische Position dezimal definiert!
Sie können nicht direkt als Bits zugeordnet werden, da es sich nicht um einzelne Bits handelt.
Wenn Sie davon ausgehen, PORTA |= PA7;
dass PORTA 0b00000000 ist (alles aus), erhalten Sie:
PORTA = PORTA | PA7;
oderPORTA = 0 | 7;
oderPORTA = 0 | 0b111
Sehen Sie das Problem? Sie haben gerade PA0, PA1, PA2 anstelle von PA7 eingeschaltet.
Funktioniert aber PORTA |= (1 << PA7);
wie erwartet.
PORTA = PORTA | (1 << PA7);
oderPORTA = 0 | (1 << 7);
oderPORTA = 0 | 0b10000000;
Der andere, bessere Mikrocontroller, der MSP430, hat eine Standarddefinition von Bits als:
#define BIT0 (0x0001)
#define BIT1 (0x0002)
~
#define BIT6 (0x0040)
#define BIT7 (0x0080)
Diese sind als ihre binäre Position in Hex definiert. BIT0 ist 0b0001, nicht wie PA0, das 0 ist. BIT7 ist 0b10000000, nicht wie PA7, das 0b111 ist.
Direkte Zuweisungen wie P1OUT |= BIT7;
funktionieren also genauso wie P1OUT |= (1 << 7);
würden.
Ihre Frage wurde bereits beantwortet, aber ich möchte eine Alternative vorstellen, die für einen Kommentar etwas zu viel war. Eines der ersten Dinge, die ich tue, wenn ich ein eingebettetes Projekt starte, ist, meinen Bitsatz zu definieren und Makros zu löschen.
#define bitset(var,bitno) ((var) |= 1 << (bitno))
#define bitclr(var,bitno) ((var) &= ~(1 << (bitno)))
Mit den Makros wird Ihr Code zu:
bitset(DDRA,0);
bitset(PORTA,0);
Das Endergebnis ist eine Bit-Set-Anweisung in Assembler.
Schau mal hier: http://nongnu.org/avr-libc/user-manual/FAQ.html#faq_use_bv
Diese Makros werden verwendet, wenn bestimmte Bits in einem Register gesetzt werden. Beispiel: Wenn PORTA 8 Bit breit ist, dann ist PA0 das niedrigste Bit, PA7 das höchste. Um PA0 auf 1 zu setzen, müssen Sie 0x01 in das Register schreiben ("or-write"). Wenn Sie PA2 setzen möchten, benötigen Sie einen Wert, der im Binärformat an der richtigen Stelle eine Eins enthält, für PA2 ist dies 0x04.
Die Leute wollen sich nicht merken, welches Bit eine bestimmte Position hat (da andere Register andere Bitnamen haben können, z. B. CS12, CS10, ADSC usw.), also verwenden sie abstraktere Namen. Anstatt PORTA = 0x04 einzugeben, geben Sie PORTA = _BV(PA2) ein und Sie wissen sofort, dass Pin PA2 hoch wird.
Armandas
user_1818839
PortA(PAO) := True;
krambo
Rojin
Mels
_BV()
Makro verwenden, um den "Bitwert" zu erhalten (z . B.PORTA |= _BV(PA0);
. Ich persönlich denke, es macht den Code lesbarer, aber die Meinungen in der Community gehen ziemlich weit auseinander.JDługosz