Zkoumal jsem shiftOut() funkční kód v wiring_shift.c a úplně jsem nepochopil, co se děje ve funkci digitalWrite. Vidím, že !!(val & (1 << i)) bere bitovou hodnotu z val ale jak přesně to funguje?
Celá funkce je níže.
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); } }
Komentáře
Odpověď
Předpokládám bitOrder == LSBFIRST.
-
ije číslo bitu, tj. „index“ dalšího bitu, který se má zapsat -
1je00000001v binární podobě -
<<je operátor posunu vlevo. Vrátí svůj první argument posunutý doleva o tolik pozic, kolik naznačuje druhý argument -
1<<ije binární00000001posunuto doleva oipozice, tj. něco jako0...010...0, kde je singl 1 v i-té pozici počítající zprava (úplně vpravo) pozice 0) -
&je „bitový a operátor“, kdeany_bit & 0je nula aany_bit & 1jeany_bit -
val & (1 << i)je0...0(i-th bit of val)0...0v binární podobě, kde i-tý bit val je v i-té pozici výsledku -
!!je dvojitá negace: it převede nulu na nulu a jakoukoli nenulovou hodnotu na jednu -
!!(val & (1 << i))je buď 0 nebo 1 a je přesně i-tým bitem val
Komentáře
- dovolte mi shrnout, čemu rozumím. Předpokládejme
val = '10010111';for i=2!!(val & (1 << i))=!!('10010111' & '00000100')=!!('00000100')=1Pokud je i = 3!!(val & (1 << i))=!!('10010111' & '00001000')=!!('00000000')=0 - To je správné!
- A to znamená, že pokud na shiftOut dám 16bitová nebo delší data, pošle nejméně významných 8 bitů a zbytek bude ignorovat.
-
shiftOut()vezmeuint8_tdata. Pokud jej zavoláte 16bitovým argumentem, kompilátor implicitně odstraní 8 nejvýznamnějších bitů před skutečným volánímshiftOut(). - @SteveMcDonald: Ano, výstup by byl stejný bez dvojí negace, protože
digitalWrite()interpretuje jakékoli jiné než nulová hodnota (nejen 1) znamenáHIGH. AutorshiftOut()se zjevně nechtěl spoléhat na toto chování a místo toho chtěl vždy volatdigitalWrite()buď s 0 (tj.LOW) nebo 1 (HIGH).
!!(val & (1 << i))je nejsložitější částí tohoto kódu. Pokud tomu rozumíte , pak jaká je vaše část, ne rozumět?shift outhodnota (v binární formě). A spolu s ní dá hodinový puls.