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
Svar
Jag antar bitOrder == LSBFIRST.
-
iär bitnumret, dvs ”index” för nästa bit som ska skrivas -
1är00000001i 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ärt00000001förskjutas åt vänster avipositioner, dvs något som0...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ärany_bit & 0är noll ochany_bit & 1ärany_bit -
val & (1 << i)är0...0(i-th bit of val)0...0i 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')=1Om 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()taruint8_tdata. Om du kallar det med ett 16-bitars argument tar kompilatorn implicit bort de 8 viktigaste bitarna före det faktiska samtalet tillshiftOut(). - @ SteveMcDonald: Ja, produktionen skulle vara densamma utan den dubbla negationen, eftersom
digitalWrite()tolkar någon icke- nollvärde (inte bara 1) som betyderHIGH. Uppenbarligen ville författaren tillshiftOut()inte förlita sig på detta beteende och ville istället alltid ringadigitalWrite()med antingen 0 (dvs.LOW) eller 1 (HIGH).
!!(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?shift outett värde (i binär form) Och kommer att ge en klockpuls tillsammans med det.