Ich habe den Funktionscode shiftOut()
in wiring_shift.c
und ich habe nicht ganz verstanden, was in der digitalWrite-Funktion vor sich geht. Ich sehe, dass !!(val & (1 << i))
den Bitwert von val
übernimmt aber wie genau funktioniert es?
Die gesamte Funktion ist unten aufgeführt.
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val) { uint8_t i; for (i = 0; i < 8; i++) { if (bitOrder == LSBFIRST) digitalWrite(dataPin, !!(val & (1 << i))); else digitalWrite(dataPin, !!(val & (1 << (7 - i)))); digitalWrite(clockPin, HIGH); digitalWrite(clockPin, LOW); } }
Kommentare
-
!!(val & (1 << i))
ist der komplexeste Teil dieses Codes. Wenn Sie dies verstehen , was ist dann der Teil, den Sie nichtverstehe? - @ edgar-bonet Eigentlich war das die Frage. Ich kann sehen, dass es irgendwie den Bitwert berechnet, aber ich habe ' nicht verstanden, wie es tut dies.
- Sie verstehen das Verhalten der shiftOut-Funktion? Ich meine, Sie verstehen, dass es ' ll
shift out
einen Wert (in binärer Form) und gibt einen Takt dazu.
Antwort
Ich gehe davon aus, dass bitOrder == LSBFIRST
.
-
i
ist die Bitnummer, dh der „Index“ des nächsten zu schreibenden Bits -
1
ist00000001
in binär -
<<
ist der Linksverschiebungsoperator. Es gibt sein erstes Argument zurück, das um so viele Positionen nach links verschoben ist, wie durch das zweite Argument angezeigt. -
1<<i
ist binär00000001
umi
-Positionen nach links verschoben, dh so etwas wie0...010...0
, wobei sich die einzelne 1 in der i-ten Position befindet und von rechts (ganz rechts) zählt Position 0 sein) -
&
ist der „bitweise und Operator“, wobeiany_bit & 0
Null undany_bit & 1
istany_bit
-
val & (1 << i)
ist0...0(i-th bit of val)0...0
in binär, wobei sich das i-te Bit von val an der i-ten Position des Ergebnisses befindet. -
!!
ist eine doppelte Negation: es konvertiert Null in Null und jeder Wert ungleich Null in Eins. -
!!(val & (1 << i))
ist entweder 0 oder 1 und genau das i-te Bit von val
Kommentare
- Lassen Sie mich zusammenfassen, was ich verstehe. Nehmen wir an,
val = '10010111'
;for i=2
!!(val & (1 << i))
=!!('10010111' & '00000100')
=!!('00000100')
=1
Wenn i = 3 ist!!(val & (1 << i))
=!!('10010111' & '00001000')
=!!('00000000')
=0
- Das ist richtig!
- Und das bedeutet, wenn ich shiftOut 16-Bit- oder längere Daten gebe, Es werden niedrigstwertige 8 Bits gesendet und der Rest ignoriert.
-
shiftOut()
nimmtuint8_t
Daten. Wenn Sie es mit einem 16-Bit-Argument aufrufen, entfernt der Compiler implizit die 8 höchstwertigen Bits vor dem eigentlichen Aufruf vonshiftOut()
. - @SteveMcDonald: Ja, die Ausgabe wäre ohne die doppelte Negation dieselbe, weil
digitalWrite()
beliebige Nicht- interpretiert Nullwert (nicht nur 1) mit der BedeutungHIGH
. Anscheinend wollte sich der Autor vonshiftOut()
nicht auf dieses Verhalten verlassen, sondern stattdessendigitalWrite()
mit 0 (dhLOW
) oder 1 (HIGH
).