• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:2バイトデータのビットシフトについて)

2バイトデータのビットシフトについて

このQ&Aのポイント
  • PIC 12F683を使った温度ロガーのプログラムにおいて、EEPROMからのデータ読み出し部分でビットシフトを行なっているが、その仕組みがわからない。
  • デフォルトの左詰め10ビットのAD変換データをビットシフトして取り出す方法が理解できない。
  • 具体的かつ詳細にビットシフトの仕組みを教えてほしい。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.6

配列が確保される場合、 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]. (メモリアドレス   Low → High ) となるはずです。 質問文のデータ buf[1] : 1111 1111 buf[0] : 1100 0000 を当てはめると、 1100 0000  1111 1111 の順に並んでいて、adに直接代入すると ad = 1100 0000 1111 1111 となり、期待とは違う結果になってしまいます。 そのため、   1111 1111 0000 0000 (左8ビットシフトしたbuf[1]) +        1100 0000 (buf[0]) -----------------------   1111 1111 1100 0000 (これをadに代入) という操作をしていると思われます。 なお、ビットシフトの操作で元のデータが変わってしまうようにお考えのようですが、 「演算のために、仮に持ってきたデータ」 に対してシフト操作をしているだけなので、元のデータに変化はないと考えます。 ※プログラミングに関しては、かなりのブランクがあるので、間違っていたらごめんなさい。

phuseman
質問者

お礼

自分が理解できていない箇所が明確に分かりました。 ビットシフトしても値のサイズは変わらない、と考えていたのです。 左8ビットシフト前 1111 1111 左8ビットシフト後 1111 1111 0000 0000 ではなく、 左8ビットシフト前 1111 1111 左8ビットシフト後 0000 0000 と、ビットシフト前後で値は8ビットのままという考えに固執していたので、 何のためにそんな事をするのかが理解できませんでした。 8ビットシフトによって、8ビットのデータが16ビットになるわけですね。 (ようやく、<< 8 、で256倍になるだけ、というみなさんの回答の意味が分かりました。) あまりに基礎的な理解不足で恐縮です。 今では、それぞれの回答はすべて的を射ているのが分かります。 回答をいただいた皆さん、ありがとうございました、非常に助かりました、 今後も何度かこのテキストを見て理解を深めようと思うので、保存しました。 システム上、すべてBAにするわけにはいきませんので、 個人的に理解し易かった kuma310min さんをBAとさせて いただきます。 回答をいただいたみなさん、本当にありがとうございました。

その他の回答 (7)

  • nak777r
  • ベストアンサー率36% (49/136)
回答No.8

すみません、正確ではないですね 正確には ad = buf[1]は、adに代入してでは無く  内部的な int のバッファに代入して、という意味に訂正

  • nak777r
  • ベストアンサー率36% (49/136)
回答No.7

[A] ビットシフト前が buf[6], buf[5], buf[4], buf[3], buf[2], buf[1], buf[0]. pppp pppp, qqqq qqqq, xxxx xxxx, yyyy yyyy, zzzz zzzz, 0000, 1100, 1010 1111. こうである場合、 ---ソース引用部--- ad = (buf[1] << 8) + buf[0]; ------------------ を分解して書くと、 ad = buf[1]   : ad = 0000 1100 ad = ad << 8  : ad = 11 0000 0000 ad = ad + buf[0]: ad = 11 1010 1111

  • tsunji
  • ベストアンサー率20% (196/958)
回答No.5

>10101111(10進:175) x 256 + 1100 0000(10進:192) >= 44800 + 192 >となってしまいますので、もとの 703 が得られない データは10ビットで、左詰めなので、 44800+192=44992 でさらに、6ビット右シフト(64で割る)と 44992÷64=703 となるのです。 右詰めならそのままですね。

phuseman
質問者

お礼

ビットシフト後も、8ビットのままだと勘違いしていました。 1111 1111 が 1111 1111 0000 0000 と 16 ビットの値になるわけですね、ようやく理解できました。 回答ありがとうございました。

回答No.4

buf と ad は、それぞれ unsigned char buf[6]  (0~255) unsigned int ad   (0~65535) で定義されています。 adに読み込む際、直接(変換なしに)2バイトデータとして読み込めれば、 このような変換は必要ないのでしょうが、考えられる原因として、 ・(ハードウェア的な理由により?)1バイトずつしか読み込めない ・2バイトまとめて読むことは可能だが、データの格納が上位・下位逆になっている があります。 (ちょっと見た感じでは、後者っぽい?) 後者であれば、格納データが、 buf[0] buf[1] ・・・ buf[6] の順に格納されていて、buf[1]が上位・buf[0]が下位の2バイトデータで読みだしたいが、 そのままだと逆になってしまう事が考えられます。 この場合、 ・buf[1] を8ビットシフトして、上位バイトへ ・それにbuf[0]を加算 して、adを 「buf[1]が上位・buf[0]が下位の2バイトデータ」 にしていると思われます。

phuseman
質問者

補足

たとえば、AD変換の結果、 1010 1111 11 (10進:703) という10ビットのデータが得られ、 buf[0]とbuf[1]が逆に格納されると仮定した場合、 ---ソース引用部--- ad = (buf[1] << 8) + buf[0]; ------------------ の演算は、 [A] ビットシフト前 buf[6], buf[5], buf[4], buf[3], buf[2], buf[1], buf[0]. pppp pppp, qqqq qqqq, xxxx xxxx, yyyy yyyy, zzzz zzzz, 1100 0000, 1010 1111. [B] ビットシフトした値 buf[6], buf[5], buf[4], buf[3], buf[2], buf[1], buf[0]. qqqq qqqq, xxxx xxxx, yyyy yyyy, zzzz zzzz, 1100 0000, 1010 1111, 0000 0000. のように、[B] のbuf[1]と、[A]のbuf[0]は同じになってしまう気がするのですが、 間違いがあれば、ご指摘願います。

  • tsunji
  • ベストアンサー率20% (196/958)
回答No.3

>ad = (buf[1] << 8) + buf[0]; この計算式は、  ad = (buf[1] * 256) + buf[0]; と同じ事をやっているのですよ。

phuseman
質問者

補足

ご回答ありがとうございます。 たとえば、AD変換の結果、 1010 1111 11 (10進:703) という10ビットのデータが得られ、 buf[1] : 1010 1111 buf[0] : 1100 0000 と格納されたとして、 10101111(10進:175) x 256 + 1100 0000(10進:192) = 44800 + 192 となってしまいますので、もとの 703 が得られない (バイトが逆順でも、やはり703は得られない)ような気がします。 間違いがありましたらご指摘願います。

  • Wr5
  • ベストアンサー率53% (2173/4061)
回答No.2

>左に8ビットシフトし、加算することの意味自体が分かりません。 0000 0010の2進数(10進数表記で2)を1ビット分左シフトすると… 0000 0100になります。10進数表記で4ですね。 値が倍になっています。 では… 0000 0010の2進数(10進数表記で2)を3ビット分左シフトするとどうなるでしょう? 0001 0000になります。10進数表記で16です。 値が8倍になっています。 ということで、左シフトした場合は2のn乗で倍になります。 1ビット左シフトなら2の1乗で2倍。 2ビット左シフトなら2の2乗で4倍。 3ビット左シフトなら2の3乗で8倍。 4ビット左シフトなら2の4乗で16倍。 5ビット左シフトなら2の5乗で32倍。 6ビット左シフトなら2の6乗で64倍。 7ビット左シフトなら2の7乗で128倍。 8ビット左シフトなら2の8乗で256倍。 9ビット左シフトなら2の9乗で512倍。    : では…… >左に8ビットシフトし、加算することの意味自体が分かりません。 するとどうなりますか?

phuseman
質問者

補足

確かに、演算としては 2^n乗となりますので、 2^8 = 256倍して加算する、という事になるのですが、 たとえばAD変換の結果、 1010 1111 11 (10進:703) という10ビットのデータが得られ、 buf[1] : 1010 1111 buf[0] : 1100 0000 と格納されたとして、 buf[1] << 8 で、1100 0000(10進:192) が得られると思うのですが、 それと buf[0] は同じ値(buf[0]とbuf[1]が逆に格納されていたとしても、やはり同様の結果) のような気がするのですが。 間違いがあればご指摘願います。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

その値で計算すると ad はいくらになりますか?

phuseman
質問者

補足

さっそくのご回答ありがとうございます。 2進で 1111 1111 11、10進で 1023、16進で 3FF だと思います。こちらの、 http://homepage3.nifty.com/mitt/pic/pic683_1.html#conf ADCON0.ADFM が指定されていないので、デフォルトの左詰と考えると、 b[1] : 1111 1111 b[0] : 1100 0000 とbufに格納されると思うのですが、 たとえば、2バイトのデータをバイトごとに区切って 整数で加算しても、最大値は、 1111 1111 (255) + 1111 1111(255) = 510 が最大で 1023 にはならないと思うので、 左に8ビットシフトし、加算することの意味自体が分かりません。