Stavo esaminando il shiftOut()
codice funzione in wiring_shift.c
e non ho capito bene cosa sta succedendo nella funzione digitalWrite. Vedo che !!(val & (1 << i))
sta prendendo il valore di bit da val
ma come funziona esattamente?
Lintera funzione è di seguito.
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); } }
Commenti
Risposta
Immagino che bitOrder == LSBFIRST
.
-
i
è il numero di bit, ovvero l “indice” del bit successivo da scrivere -
1
è00000001
in binario -
<<
è loperatore di spostamento a sinistra. Restituisce il suo primo argomento spostato a sinistra di tante posizioni quante sono indicate dal secondo argomento -
1<<i
è binario00000001
spostato a sinistra dii
posizioni, cioè qualcosa come0...010...0
, dove il singolo 1 è nella i-esima posizione contando da destra (più a destra essendo la posizione 0) -
&
è “bit per bit e operatore”, doveany_bit & 0
è zero eany_bit & 1
èany_bit
-
val & (1 << i)
è0...0(i-th bit of val)0...0
in binario, dove li-esimo bit di val è nella i-esima posizione del risultato -
!!
è una doppia negazione: converte zero in zero e qualsiasi valore diverso da zero in uno -
!!(val & (1 << i))
è 0 o 1 ed è esattamente li-esimo bit di val
Commenti
- lasciatemi riassumere quello che ho capito. Supponiamo che
val = '10010111'
;for i=2
!!(val & (1 << i))
=!!('10010111' & '00000100')
=!!('00000100')
=1
Se i è = 3!!(val & (1 << i))
=!!('10010111' & '00001000')
=!!('00000000')
=0
- È corretto!
- E questo significa che se fornisco a shiftOut dati a 16 bit o più, invierà gli 8 bit meno significativi e ignorerà il resto.
-
shiftOut()
accettauint8_t
dati. Se lo chiami con un argomento a 16 bit, il compilatore rimuoverà implicitamente gli 8 bit più significativi prima della chiamata effettiva ashiftOut()
. - @SteveMcDonald: Sì, loutput sarebbe lo stesso senza la doppia negazione, perché
digitalWrite()
interpreta qualsiasi non- valore zero (non solo 1) nel senso diHIGH
. Apparentemente, lautore dishiftOut()
non voleva fare affidamento su questo comportamento e invece voleva chiamare sempredigitalWrite()
con 0 (cioèLOW
) o 1 (HIGH
).
!!(val & (1 << i))
è la parte più complessa di questo codice. Se lo capisci , qual è la parte che non fai capito?shift out
un valore (in forma binaria) e insieme ad esso darà un impulso di clock.