Hur fungerar shiftOut-funktionen internt? (förklaring på källkod)

Jag undersökte shiftOut() funktionskod i wiring_shift.c och jag förstod inte riktigt vad som händer i digitalWrite-funktionen. Jag ser att !!(val & (1 << i)) tar bitvärdet från val men hur fungerar det exakt?

Hela funktionen är nedan.

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)) är den mest komplexa delen av den här koden. Om du gör förstår detta, vad är det då du gör inte förstår?
  • @ edgar-bonet Egentligen var detta frågan. Jag kan se att det på något sätt beräknar bitvärdet, men jag förstod inte ' det gör det.
  • Du förstår beteendet hos shiftOut-funktionen? Jag menar, du förstår att det ' ll shift out ett värde (i binär form) Och kommer att ge en klockpuls tillsammans med det.

Svar

Jag antar bitOrder == LSBFIRST.

  • i är bitnumret, dvs ”index” för nästa bit som ska skrivas
  • 1 är 00000001 i binär
  • << är skift till vänster. Det returnerar sitt första argument skiftat åt vänster med så många positioner som indikeras av det andra argumentet
  • 1<<i är binärt 00000001 förskjutas åt vänster av i positioner, dvs något som 0...010...0, där singeln 1 är i den i: e positionen räknas från höger (längst till höger vara position 0)
  • & är ”bitvis och operatör”, där any_bit & 0 är noll och any_bit & 1 är any_bit
  • val & (1 << i) är 0...0(i-th bit of val)0...0 i binär, där den i: e biten av val är i den i: e positionen av resultatet
  • !! är en dubbel negation: det konverterar noll till noll och alla icke-nollvärden till ett
  • !!(val & (1 << i)) är antingen 0 eller 1, och är exakt den i-biten av val

Kommentarer

  • låt mig sammanfatta vad jag förstår. Låt oss anta val = '10010111'; for i=2 !!(val & (1 << i)) = !!('10010111' & '00000100') = !!('00000100') = 1 Om jag är = 3 !!(val & (1 << i)) = !!('10010111' & '00001000') = !!('00000000') = 0
  • Det här är korrekt!
  • Och det betyder att om jag ger 16bit eller längre data att skifta, det skickar minst 8 bitar och ignorerar resten.
  • shiftOut() tar uint8_t data. Om du kallar det med ett 16-bitars argument tar kompilatorn implicit bort de 8 viktigaste bitarna före det faktiska samtalet till shiftOut().
  • @ SteveMcDonald: Ja, produktionen skulle vara densamma utan den dubbla negationen, eftersom digitalWrite() tolkar någon icke- nollvärde (inte bara 1) som betyder HIGH. Uppenbarligen ville författaren till shiftOut() inte förlita sig på detta beteende och ville istället alltid ringa digitalWrite() med antingen 0 (dvs. LOW) eller 1 (HIGH).

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *