Cum funcționează funcția shiftOut intern? (explicație privind codul sursă)

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

  • !!(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?
  • @ edgar-bonet De fapt, aceasta a fost întrebarea. Îl văd cum calculează cumva valoarea bitului, dar nu am înțeles ' face asta.
  • Înțelegeți comportamentul funcției shiftOut? Adică, înțelegeți că ' ll shift out o valoare (în formă binară). Și va da un impuls de ceas împreună cu aceasta.

Răspuns

Voi presupune bitOrder == LSBFIRST.

  • i este numărul de biți, adică „indexul” următorului bit de scris
  • 1 este 00000001 î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 binar 00000001 deplasat la stânga de i poziții, adică ceva de genul 0...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”, unde any_bit & 0 este zero și any_bit & 1 este any_bit
  • val & (1 << i) este 0...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 date uint8_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ătre shiftOut().
  • @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ție HIGH. Se pare că autorul shiftOut() nu a vrut să se bazeze pe acest comportament și, în schimb, a dorit să apeleze întotdeauna digitalWrite() fie cu 0 (adică LOW) sau 1 (HIGH).

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *