Hvordan fungerer shiftOut-funksjonen internt? (forklaring på kildekoden)

Jeg undersøkte shiftOut() funksjonskode i wiring_shift.c og jeg forstod ikke helt hva som skjer i digitalWrite-funksjonen. Jeg ser !!(val & (1 << i)) tar bitverdien fra val men hvordan fungerer det akkurat?

Hele funksjonen er under.

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); } } 

Kommentarer

  • !!(val & (1 << i)) er den mest komplekse delen av denne koden. Hvis du gjør forstår dette, hva er den delen du gjør ikke forstår?
  • @ edgar-bonet Egentlig var dette spørsmålet. Jeg kan se det på en eller annen måte beregner bitverdien, men jeg forsto ikke ' hvordan gjør det dette.
  • Forstår du oppførselen til shiftOut-funksjonen? Jeg mener, du forstår at den ' ll shift out en verdi (i binær form). Og vil gi en klokkepuls sammen med den.

Svar

Jeg antar bitOrder == LSBFIRST.

  • i er bitnummeret, dvs. «indeksen» til neste bit som skal skrives
  • 1 er 00000001 i binær
  • << er skiftet til venstre. Den returnerer sitt første argument skiftet til venstre med så mange posisjoner som angitt av det andre argumentet
  • 1<<i er binært 00000001 skiftet til venstre av i posisjoner, dvs. noe sånt som 0...010...0, der singelen 1 er i den i-posisjonen teller fra høyre (høyre å være posisjon 0)
  • & er «bitvis og operator», der any_bit & 0 er null og any_bit & 1 er any_bit
  • val & (1 << i) er 0...0(i-th bit of val)0...0 i binær, der i-bit av val er i i-posisjon av resultatet
  • !! er en dobbel negasjon: det konverterer null til null og en verdi som ikke er null til en
  • !!(val & (1 << i)) er enten 0 eller 1, og er nøyaktig den i-biten av val

Kommentarer

  • la meg oppsummere det jeg forstår. La oss anta val = '10010111'; for i=2 !!(val & (1 << i)) = !!('10010111' & '00000100') = !!('00000100') = 1 Hvis jeg er = 3 !!(val & (1 << i)) = !!('10010111' & '00001000') = !!('00000000') = 0
  • Dette er riktig!
  • Og dette betyr at hvis jeg gir 16bit eller lengre data å skifte ut, det vil sende minst betydelige 8 biter og ignorere resten.
  • shiftOut() tar uint8_t data. Hvis du kaller det med et 16-bits argument, vil kompilatoren implisitt fjerne de 8 mest betydningsfulle bitene før selve anropet til shiftOut().
  • @ SteveMcDonald: Ja, utdataene ville være de samme uten den dobbelte negasjonen, fordi digitalWrite() tolker noen ikke- null verdi (ikke bare 1) som betyr HIGH. Tilsynelatende ønsket ikke forfatteren av shiftOut() å stole på denne oppførselen, og ville i stedet alltid ringe digitalWrite() med enten 0 (dvs. LOW) eller 1 (HIGH).

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *