shiftOut関数は内部でどのように機能しますか? (ソースコードの説明)

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); } } 

コメント

  • !!(val & (1 << i))は、このコードの最も複雑な部分です。これを理解している場合、理解していない部分は何ですか / i>わかりますか?
  • @ edgar-bonet実際、これが問題でした。どういうわけかビット値を計算していることがわかりますが、'方法がわかりませんでした。これを行います。
  • shiftOut関数の動作を理解していますか?つまり、' ll shift out値(バイナリ形式)。それに伴ってクロックパルスが発生します。

回答

bitOrder == LSBFIRSTと仮定します。

  • iはビット番号、つまり次に書き込むビットの「インデックス」です
  • 1はバイナリの00000001です
  • <<は左シフト演算子です。最初の引数を、2番目の引数で示される位置だけ左にシフトして返します
  • 1<<iはバイナリです00000001 iの位置だけ左にシフトします。つまり、0...010...0のように、単一の1が右から数えてi番目の位置(右端)にあります。位置0)
  • &は「ビット単位の演算子」です。ここで、any_bit & 0はゼロで、any_bit & 1any_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)。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

Deep Theme Powered by WordPress