Jeg undersøkte shiftOut()
funksjonskode i wiring_shift.c
og jeg forstod ikke helt hva som skjer i digitalWrite-funksjonen. Jeg ser !!(val & (1 << i))
tar bitverdien fra val
men hvordan fungerer det akkurat?
Hele funksjonen er under.
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 antar bitOrder == LSBFIRST
.
-
i
er bitnummeret, dvs. «indeksen» til neste bit som skal skrives -
1
er00000001
i binær -
<<
er skiftet til venstre. Den returnerer sitt første argument skiftet til venstre med så mange posisjoner som angitt av det andre argumentet -
1<<i
er binært00000001
skiftet til venstre avi
posisjoner, dvs. noe sånt som0...010...0
, der singelen 1 er i den i-posisjonen teller fra høyre (høyre å være posisjon 0) -
&
er «bitvis og operator», derany_bit & 0
er null ogany_bit & 1
erany_bit
-
val & (1 << i)
er0...0(i-th bit of val)0...0
i binær, der i-bit av val er i i-posisjon av resultatet -
!!
er en dobbel negasjon: det konverterer null til null og en verdi som ikke er null til en -
!!(val & (1 << i))
er enten 0 eller 1, og er nøyaktig den i-biten av val
Kommentarer
- la meg oppsummere det jeg forstår. La oss anta
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 riktig!
- Og dette betyr at hvis jeg gir 16bit eller lengre data å skifte ut, det vil sende minst betydelige 8 biter og ignorere resten.
-
shiftOut()
taruint8_t
data. Hvis du kaller det med et 16-bits argument, vil kompilatoren implisitt fjerne de 8 mest betydningsfulle bitene før selve anropet tilshiftOut()
. - @ SteveMcDonald: Ja, utdataene ville være de samme uten den dobbelte negasjonen, fordi
digitalWrite()
tolker noen ikke- null verdi (ikke bare 1) som betyrHIGH
. Tilsynelatende ønsket ikke forfatteren avshiftOut()
å stole på denne oppførselen, og ville i stedet alltid ringedigitalWrite()
med enten 0 (dvs.LOW
) eller 1 (HIGH
).
!!(val & (1 << i))
er den mest komplekse delen av denne koden. Hvis du gjør forstår dette, hva er den delen du gjør ikke forstår?shift out
en verdi (i binær form). Og vil gi en klokkepuls sammen med den.