Examinam codul funcției shiftOut()
în wiring_shift.c
și nu prea am înțeles ce se întâmplă în funcția digitalWrite. Văd că !!(val & (1 << i))
ia valoarea bitului de la val
dar cum funcționează exact?
Întreaga funcție este mai jos.
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); } }
Comentarii
Răspuns
Voi presupune bitOrder == LSBFIRST
.
-
i
este numărul de biți, adică „indexul” următorului bit de scris -
1
este00000001
în binar -
<<
este operatorul shift stânga. Revine primul său argument deplasat la stânga cu câte poziții indică al doilea argument -
1<<i
este binar00000001
deplasat la stânga dei
poziții, adică ceva de genul0...010...0
, unde singurul 1 se află în poziția a I numărând din dreapta (cel mai dreapta) fiind poziția 0) -
&
este „bit și operator”, undeany_bit & 0
este zero șiany_bit & 1
esteany_bit
-
val & (1 << i)
este0...0(i-th bit of val)0...0
în binar, unde bitul i al lui val se află în poziția i a rezultatului -
!!
este o dublă negație: convertește zero la zero și orice valoare diferită de zero la una -
!!(val & (1 << i))
este fie 0, fie 1 și este exact bitul i-al lui val
Comentarii
- permiteți-mi să rezum ceea ce înțeleg. Să presupunem
val = '10010111'
for i=2
!!(val & (1 << i))
=!!('10010111' & '00000100')
=!!('00000100')
=1
Dacă i este = 3!!(val & (1 << i))
=!!('10010111' & '00001000')
=!!('00000000')
=0
- Este corect!
- Și asta înseamnă dacă dau date de 16 biți sau mai mult pentru shiftOut, va trimite cel puțin semnificativ 8 biți și va ignora restul.
-
shiftOut()
ia dateuint8_t
. Dacă îl numiți cu un argument pe 16 biți, compilatorul va elimina implicit cei 8 biți cei mai semnificativi înainte apelului efectiv cătreshiftOut()
. - @SteveMcDonald: Da, ieșirea ar fi aceeași fără negarea dublă, deoarece
digitalWrite()
interpretează orice care nu este valoarea zero (nu doar 1) ca semnificațieHIGH
. Se pare că autorulshiftOut()
nu a vrut să se bazeze pe acest comportament și, în schimb, a dorit să apeleze întotdeaunadigitalWrite()
fie cu 0 (adicăLOW
) sau 1 (HIGH
).
!!(val & (1 << i))
este cea mai complexă parte a acestui cod. Dacă înțelegeți acest lucru, care este partea pe care o faceți nu înțeleg?shift out
o valoare (în formă binară). Și va da un impuls de ceas împreună cu aceasta.