Come funziona internamente la funzione shiftOut? (spiegazione sul codice sorgente)

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

  • !!(val & (1 << i)) è la parte più complessa di questo codice. Se lo capisci , qual è la parte che non fai capito?
  • @ edgar-bonet In realtà questa era la domanda. Vedo che in qualche modo calcola il valore del bit, ma ' non ho capito come lo fai.
  • Capisci il comportamento della funzione shiftOut? Voglio dire, capisci che ' ll shift out un valore (in forma binaria) e insieme ad esso darà un impulso di clock.

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 è binario 00000001 spostato a sinistra di i posizioni, cioè qualcosa come 0...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”, dove any_bit & 0 è zero e any_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() accetta uint8_t dati. Se lo chiami con un argomento a 16 bit, il compilatore rimuoverà implicitamente gli 8 bit più significativi prima della chiamata effettiva a shiftOut().
  • @SteveMcDonald: Sì, loutput sarebbe lo stesso senza la doppia negazione, perché digitalWrite() interpreta qualsiasi non- valore zero (non solo 1) nel senso di HIGH. Apparentemente, lautore di shiftOut() non voleva fare affidamento su questo comportamento e invece voleva chiamare sempre digitalWrite() con 0 (cioè LOW) o 1 (HIGH).

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *