wiring_shift.c
関数コードを調べていました
そして私はdigitalWrite関数で何が起こっているのかよくわかりませんでした。!!(val & (1 << i))がvalからビット値を取得しているようです。しかし、どのように正確に機能しますか?
関数全体は以下のとおりです。
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); } }
コメント
回答
bitOrder == LSBFIRSTと仮定します。
-
iはビット番号、つまり次に書き込むビットの「インデックス」です -
1はバイナリの00000001です -
<<は左シフト演算子です。最初の引数を、2番目の引数で示される位置だけ左にシフトして返します -
1<<iはバイナリです00000001iの位置だけ左にシフトします。つまり、0...010...0のように、単一の1が右から数えてi番目の位置(右端)にあります。位置0) -
&は「ビット単位の演算子」です。ここで、any_bit & 0はゼロで、any_bit & 1はany_bit -
val & (1 << i)は0...0(i-th bit of val)0...0バイナリで、valのi番目のビットが結果のi番目の位置にある -
!!は二重否定です。ゼロをゼロに変換し、ゼロ以外の値を1に変換します -
!!(val & (1 << i))は0または1であり、正確にvalのi番目のビットです
コメント
- 私が理解していることを要約します。
val = '10010111'と仮定します。for i=2!!(val & (1 << i))=!!('10010111' & '00000100')=!!('00000100')=1iが= 3の場合!!(val & (1 << i))=!!('10010111' & '00001000')=!!('00000000')=0 - これは正しいです!
- これは、16ビット以上のデータをshiftOutに与えると、最下位8ビットを送信し、残りを無視します。
-
shiftOut()はuint8_tデータを取得します。 16ビットの引数を使用して呼び出すと、コンパイラはshiftOut()への実際の呼び出しの前に8つの最上位ビットを暗黙的に削除します。 - @SteveMcDonald:はい、二重否定がなくても出力は同じになります。
digitalWrite()は any non-を解釈するためです。HIGHを意味するゼロ値(1だけではない)。どうやら、shiftOut()の作成者はこの動作に依存することを望まず、代わりに常にdigitalWrite()を0(つまりLOW)または1(HIGH)。
!!(val & (1 << i))は、このコードの最も複雑な部分です。これを理解している場合、理解していない部分は何ですか / i>わかりますか?shift out値(バイナリ形式)。それに伴ってクロックパルスが発生します。