- ベストアンサー
2バイトデータのビットシフトについて
- PIC 12F683を使った温度ロガーのプログラムにおいて、EEPROMからのデータ読み出し部分でビットシフトを行なっているが、その仕組みがわからない。
- デフォルトの左詰め10ビットのAD変換データをビットシフトして取り出す方法が理解できない。
- 具体的かつ詳細にビットシフトの仕組みを教えてほしい。
- みんなの回答 (8)
- 専門家の回答
質問者が選んだベストアンサー
配列が確保される場合、 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に代入) という操作をしていると思われます。 なお、ビットシフトの操作で元のデータが変わってしまうようにお考えのようですが、 「演算のために、仮に持ってきたデータ」 に対してシフト操作をしているだけなので、元のデータに変化はないと考えます。 ※プログラミングに関しては、かなりのブランクがあるので、間違っていたらごめんなさい。
その他の回答 (7)
- nak777r
- ベストアンサー率36% (49/136)
すみません、正確ではないですね 正確には ad = buf[1]は、adに代入してでは無く 内部的な int のバッファに代入して、という意味に訂正
- nak777r
- ベストアンサー率36% (49/136)
[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)
>10101111(10進:175) x 256 + 1100 0000(10進:192) >= 44800 + 192 >となってしまいますので、もとの 703 が得られない データは10ビットで、左詰めなので、 44800+192=44992 でさらに、6ビット右シフト(64で割る)と 44992÷64=703 となるのです。 右詰めならそのままですね。
お礼
ビットシフト後も、8ビットのままだと勘違いしていました。 1111 1111 が 1111 1111 0000 0000 と 16 ビットの値になるわけですね、ようやく理解できました。 回答ありがとうございました。
- kuma310min
- ベストアンサー率40% (212/518)
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バイトデータ」 にしていると思われます。
補足
たとえば、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)
>ad = (buf[1] << 8) + buf[0]; この計算式は、 ad = (buf[1] * 256) + buf[0]; と同じ事をやっているのですよ。
補足
ご回答ありがとうございます。 たとえば、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)
>左に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ビットシフトし、加算することの意味自体が分かりません。 するとどうなりますか?
補足
確かに、演算としては 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)
その値で計算すると ad はいくらになりますか?
補足
さっそくのご回答ありがとうございます。 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ビットシフトし、加算することの意味自体が分かりません。
お礼
自分が理解できていない箇所が明確に分かりました。 ビットシフトしても値のサイズは変わらない、と考えていたのです。 左8ビットシフト前 1111 1111 左8ビットシフト後 1111 1111 0000 0000 ではなく、 左8ビットシフト前 1111 1111 左8ビットシフト後 0000 0000 と、ビットシフト前後で値は8ビットのままという考えに固執していたので、 何のためにそんな事をするのかが理解できませんでした。 8ビットシフトによって、8ビットのデータが16ビットになるわけですね。 (ようやく、<< 8 、で256倍になるだけ、というみなさんの回答の意味が分かりました。) あまりに基礎的な理解不足で恐縮です。 今では、それぞれの回答はすべて的を射ているのが分かります。 回答をいただいた皆さん、ありがとうございました、非常に助かりました、 今後も何度かこのテキストを見て理解を深めようと思うので、保存しました。 システム上、すべてBAにするわけにはいきませんので、 個人的に理解し易かった kuma310min さんをBAとさせて いただきます。 回答をいただいたみなさん、本当にありがとうございました。