Ik was shiftOut()
functiecode aan het onderzoeken in wiring_shift.c
en ik begreep niet helemaal wat er in de digitalWrite-functie gebeurt. Ik zie dat !!(val & (1 << i))
de bitwaarde overneemt van val
maar hoe werkt het precies?
De hele functie staat hieronder.
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); } }
Reacties
Antwoord
Ik “neem aan bitOrder == LSBFIRST
.
-
i
is het bitnummer, dwz de “index” van het volgende te schrijven bit -
1
is00000001
in binair formaat -
<<
is de operator voor verschuiven naar links. Het geeft het eerste argument terug dat evenveel posities naar links is verschoven als aangegeven door het tweede argument. -
1<<i
is binair00000001
naar links verschoven meti
posities, dat wil zeggen zoiets als0...010...0
, waarbij de enkele 1 op de i-de positie staat, geteld vanaf de rechterkant zijnde positie 0) -
&
is de “bitsgewijze en operator”, waarbijany_bit & 0
nul is enany_bit & 1
isany_bit
-
val & (1 << i)
is0...0(i-th bit of val)0...0
in binair, waarbij het i-de bit van val zich in de i-de positie van het resultaat bevindt -
!!
is een dubbele negatie: het converteert nul naar nul en elke niet-nulwaarde naar één -
!!(val & (1 << i))
is 0 of 1, en is precies het i-de bit van val
Reacties
- laat me samenvatten wat ik begrijp. Laten we aannemen dat
val = '10010111'
;for i=2
!!(val & (1 << i))
=!!('10010111' & '00000100')
=!!('00000100')
=1
If i is = 3!!(val & (1 << i))
=!!('10010111' & '00001000')
=!!('00000000')
=0
- Dit is correct!
- En dit betekent dat als ik 16bit of meer gegevens geef om uit te schakelen, het zal de minst significante 8 bits verzenden en de rest negeren.
-
shiftOut()
neemtuint8_t
gegevens. Als je het aanroept met een 16-bits argument, zal de compiler impliciet de 8 meest significante bits verwijderen voor de daadwerkelijke aanroep vanshiftOut()
. - @SteveMcDonald: Ja, de uitvoer zou hetzelfde zijn zonder de dubbele ontkenning, omdat
digitalWrite()
interpreteert elke niet- nulwaarde (niet alleen 1) als betekenisHIGH
. Blijkbaar wilde de auteur vanshiftOut()
niet vertrouwen op dit gedrag, en wilde in plaats daarvan altijddigitalWrite()
aanroepen met een 0 (dwzLOW
) of 1 (HIGH
).
!!(val & (1 << i))
is het meest complexe deel van deze code. Als je dit begrijpt , wat is dan het deel dat je niet begrepen?shift out
een waarde (in binaire vorm) en geeft daarbij een klokpuls.