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
はバイナリです00000001
i
の位置だけ左にシフトします。つまり、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')
=1
iが= 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
値(バイナリ形式)。それに伴ってクロックパルスが発生します。