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.
-
ieste numărul de biți, adică „indexul” următorului bit de scris -
1este00000001î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<<ieste binar00000001deplasat la stânga deipoziț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 & 0este zero șiany_bit & 1esteany_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')=1Dacă 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 outo valoare (în formă binară). Și va da un impuls de ceas împreună cu aceasta.