Como a função shiftOut funciona internamente? (explicação sobre o código-fonte)

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

  • !!(val & (1 << i)) é a parte mais complexa deste código. Se você entende isso, então qual é a parte que você não entendeu?
  • @ edgar-bonet Na verdade, esta era a pergunta. Posso ver que de alguma forma calcula o valor do bit, mas não ' não entendi como ele faz isso.
  • Você entende o comportamento da função shiftOut? Quer dizer, você entende que ela ' ll shift out um valor (na forma binária). E fornecerá um pulso de clock junto com ele.

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ário 00000001 deslocado para a esquerda por i posições, ou seja, algo como 0...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”, onde any_bit & 0 é zero e any_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ém uint8_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 para shiftOut().
  • @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), significando HIGH. Aparentemente, o autor de shiftOut() não queria confiar neste comportamento e, em vez disso, sempre quis chamar digitalWrite() com 0 (ou seja, div id = “a09f0b06d5″>

) ou 1 (HIGH).

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *