Jeg undersøgte shiftOut()
funktionskode i wiring_shift.c
og jeg forstod ikke helt, hvad der foregår i digitalWrite-funktionen. Jeg ser !!(val & (1 << i))
tager bitværdien fra val
men hvordan fungerer det nøjagtigt?
Hele funktionen er nedenfor.
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); } }
Kommentarer
Svar
Jeg antager bitOrder == LSBFIRST
.
-
i
er bitnummeret, dvs. “indekset” for den næste bit, der skal skrives -
1
er00000001
i binært -
<<
er skiftet til venstre. Det returnerer sit første argument skiftet til venstre med så mange positioner som angivet af det andet argument -
1<<i
er binært00000001
skiftet til venstre medi
positioner, dvs. noget som0...010...0
, hvor single 1 er i den i-position og tæller fra højre (højre at være position 0) -
&
er “bitvis og operator”, hvorany_bit & 0
er nul ogany_bit & 1
erany_bit
-
val & (1 << i)
er0...0(i-th bit of val)0...0
i binær, hvor den i-bit af val er i den i-position af resultatet -
!!
er en dobbelt negation: det konverterer nul til nul, og enhver værdi, der ikke er nul, til en -
!!(val & (1 << i))
er enten 0 eller 1, og er nøjagtigt den i-bit af val
Kommentarer
- lad mig opsummere, hvad jeg forstår. Lad os antage
val = '10010111'
;for i=2
!!(val & (1 << i))
=!!('10010111' & '00000100')
=!!('00000100')
=1
Hvis jeg er = 3!!(val & (1 << i))
=!!('10010111' & '00001000')
=!!('00000000')
=0
- Dette er korrekt!
- Og det betyder, at hvis jeg giver 16bit eller længere data til at skifte ud, det sender mindst signifikante 8 bits og ignorerer resten.
-
shiftOut()
tageruint8_t
data. Hvis du kalder det med et 16-bit argument, fjerner compileren implicit de 8 mest betydningsfulde bits før det aktuelle opkald tilshiftOut()
. - @ SteveMcDonald: Ja, output ville være det samme uden den dobbelte negation, fordi
digitalWrite()
fortolker enhver ikke- nul værdi (ikke kun 1) som betydningHIGH
. Tilsyneladende ønskede forfatteren afshiftOut()
ikke at stole på denne adfærd og ville i stedet altid kaldedigitalWrite()
med enten 0 (dvs.LOW
) eller 1 (HIGH
).
!!(val & (1 << i))
er den mest komplekse del af denne kode. Hvis du gør forstår dette, hvad er den del, du laver ikke forstår?shift out
en værdi (i binær form). Og giver en urpuls sammen med den.