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è00000001in 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è binario00000001spostato a sinistra diiposizioni, 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...0in 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')=1Se 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_tdati. 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 outun valore (in forma binaria) e insieme ad esso darà un impulso di clock.