Eu estava examinando o shiftOut()
código de função em wiring_shift.c
e não entendi muito bem o que está acontecendo na função digitalWrite. Vejo que !!(val & (1 << i))
está pegando o valor de bit de val
mas como funciona exatamente?
Toda a função está abaixo.
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); } }
Comentários
Resposta
Presumo bitOrder == LSBFIRST
.
-
i
é o número do bit, ou seja, o “índice” do próximo bit a ser gravado -
1
é00000001
em binário -
<<
é o operador shift left. Ele retorna seu primeiro argumento deslocado para a esquerda em tantas posições quanto indicado pelo segundo argumento -
1<<i
é binário00000001
deslocado para a esquerda pori
posições, ou seja, algo como0...010...0
, onde o único 1 está na i-ésima posição contando da direita (extrema direita sendo a posição 0) -
&
é o “bit a bit e operador”, ondeany_bit & 0
é zero eany_bit & 1
éany_bit
-
val & (1 << i)
é0...0(i-th bit of val)0...0
em binário, onde o i-ésimo bit de val está na i-ésima posição do resultado -
!!
é uma dupla negação: converte zero em zero e qualquer valor diferente de zero em um -
!!(val & (1 << i))
é 0 ou 1 e é exatamente o i-ésimo bit de val
Comentários
- deixe-me resumir o que entendi. Suponha que
val = '10010111'
;for i=2
!!(val & (1 << i))
=!!('10010111' & '00000100')
=!!('00000100')
=1
Se i is = 3!!(val & (1 << i))
=!!('10010111' & '00001000')
=!!('00000000')
=0
- Correto!
- E isso significa que se eu der dados de 16 bits ou mais para deslocar para fora, ele enviará 8 bits menos significativos e ignorará o resto.
-
shiftOut()
obtémuint8_t
dados. Se você chamá-lo com um argumento de 16 bits, o compilador removerá implicitamente os 8 bits mais significativos antes da chamada real parashiftOut()
. - @SteveMcDonald: Sim, a saída seria a mesma sem a negação dupla, porque
digitalWrite()
interpreta qualquer não valor zero (não apenas 1), significandoHIGH
. Aparentemente, o autor deshiftOut()
não queria confiar neste comportamento e, em vez disso, sempre quis chamardigitalWrite()
com 0 (ou seja, div id = “a09f0b06d5″>
) ou 1 (HIGH
).
!!(val & (1 << i))
é a parte mais complexa deste código. Se você entende isso, então qual é a parte que você não entendeu?shift out
um valor (na forma binária). E fornecerá um pulso de clock junto com ele.