2の補数を含むディジタル温度計情報の変換について
今回は2の補数を含むデータの扱い方について触れたいと思います。
I2C I/Fを用いてディジタル温度を読み取る温度計IC(例えば、TI製のLM75x)は、2の補数を持った9ビットの情報を出力します。I2C I/Fから2バイトデータとしてリードし、その情報をプログラム内で補正する必要があります。データフォーマットは図1の様になっており、D7からD15が有効な温度データ、D0~D6が無効データとなっています。このフォーマットを見ると、取り込んだバイトデータを2バイトの符号付整数型(signed short)に変換し、7bit右シフトすれば良いように一見すると読めます。
ここに落とし穴があって、D15が2の補数になっているため、マイナス温度の時にビットシフトをすると異なる温度を表示してしまいます。7ビット右シフトしたときの結果を図2に示します。-25℃の時に、プログラム上では231℃と表示してしまう結果になりました。2の補数で表示されるデータを扱うときは、計算リソースを使ってしまいますが、2^7 = 128で割った商を用いることで正しく変換することが出来ます。
組込みプログラムでは、計算リソースを有効活用をするために掛け算、割り算ではビットシフトを用いします。2の補数を扱うときに、このような落とし穴がありますので、小さい単位(モジュール)での検証をこまめに行うことや、ちょっとマージンを持たせた条件での検証(使用温度範囲に対して10℃広げる、電源電圧範囲に対して5%広げる等)を行って早期に発見できるように対処をすることが重要と考えます。

図1 データフォーマット

図2 7bit右シフトで補正

図3 128で割って補正
<以下、10/22加筆>
補数を含む計算では、ビット反転とビットシフトを組み合わせる方法があります。散歩しているときに思い出したので加筆しました。
【ビット反転とビットシフトを組み合わせた補正方法】
- -25℃の時にディジタル温度計から出力されるデータ(2進数)は、b'11100111 00000000' (10進数で表示すると-6400)
- ビット反転すると、b'00011000 11111111' (10進数で表示すると6399)
- ビット反転した結果に+1して7ビット右シフト、b'00000000 00110010'(10進数で表示すると50)
- もう一回ビット反転した結果に+1すると、b'11111111 11001110'(10進数で表示すると-50、1LSB=0.5℃で換算すると-25℃)
改めて見直すと、2の補数は良くできた考え方だなって思います。

