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é00000001em 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ário00000001deslocado para a esquerda poriposiçõ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...0em 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')=1Se 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_tdados. 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 outum valor (na forma binária). E fornecerá um pulso de clock junto com ele.