AVRのI2Cモジュール / 温度センサーLM75BD / I2Cでとにかくデータを読み出してみる

pp.361ff.
(ほかにマイコンにプラス! シリアル拡張IC サンプルブック[基板付き] (トライアルシリーズ), pp.115ff.)
LM75のOS端子はOvertemperature Shutdown output (オープンドレイン)。
f:id:ti-nspire:20200123144752p:plain:h280 f:id:ti-nspire:20200123144239p:plain:h280
f:id:ti-nspire:20200123143508p:plain
f:id:ti-nspire:20200123145129p:plain:w600
↑ Wはwrite、Sはrepeated start、Rはread、aはacknowledge、~aはnot acknowledge。

#include <avr/io.h>
#include <util/delay.h>
#include "USART.h"

int16_t tempData;

int main(){
    initUSART();
    
    TWBR = 32; // i2cビットレート=システムクロック÷(16 + 2 * TWBR * PrescalerValue)。PrescalerValueは1がデフォルト。
    TWCR |= (1 << TWEN); // スタートコンディションを生成する前に念のためI2Cを有効化しておく。

    while(1){

        // スタートコンディションを生成する。
        TWCR = (1 << TWINT | 1 << TWEN | 1 << TWSTA); // 割り込みフラグをクリアしてI2Cは有効化したままでスタートコンディションを生成する。
        loop_until_bit_is_set(TWCR, TWINT);           // 処理が終わるのを待つ。

        // 書き込み通知をスレーブへ出す。
        TWDR = 0b10010000;
        TWCR = (1 << TWINT | 1 << TWEN);    // 割り込みフラグをクリアしてI2Cは有効化したままにする。
        loop_until_bit_is_set(TWCR, TWINT); // 処理が終わるのを待つ。

        // 書き込む値(ここではTempレジスタのポインタ)を送る。
        TWDR = 0b00000000;
        TWCR = (1 << TWINT | 1 << TWEN);    // 割り込みフラグをクリアしてI2Cは有効化したままにする。
        loop_until_bit_is_set(TWCR, TWINT); // 処理が終わるのを待つ。

        // もう一度スタートコンディションを生成する。
        TWCR = (1 << TWINT | 1 << TWEN | 1 << TWSTA); // 割り込みフラグをクリアしてI2Cは有効化したままでスタートコンディションを生成する。
        loop_until_bit_is_set(TWCR, TWINT);           // 処理が終わるのを待つ。

        // 読み出し通知をスレーブへ出す。
        TWDR = 0b10010001;
        TWCR = (1 << TWINT | 1 << TWEN);    // 割り込みフラグをクリアしてI2Cは有効化したままにする。
        loop_until_bit_is_set(TWCR, TWINT); // 処理が終わるのを待つ。

        // 温度データを1バイト受信したらACKを生成する。
        TWCR = (1 << TWINT | 1 << TWEN | 1 << TWEA); // 割り込みフラグをクリアしてI2Cは有効化したままにし、受信し終えたらACKを出す設定にする。
        loop_until_bit_is_set(TWCR, TWINT);          // 処理が終わるのを待つ。
        tempData = (int16_t)(TWDR << 8);             // 温度データの上位8ビットを16ビットの上位8ビットにはめ込む。

        // 温度データをもう1バイト受信するが今度はACKを生成しない(NACKを生成する)。
        TWCR = (1 << TWINT | 1 << TWEN);    // 割り込みフラグをクリアしてI2Cは有効化したままにし、受信し終えたらNACKを出す設定にする。
        loop_until_bit_is_set(TWCR, TWINT); // 処理が終わるのを待つ。
        tempData |= TWDR;                   // 温度データの下位8ビット(うち下位5ビットは無視する)を16ビットの下位8ビットにはめ込む。

        // ストップコンディションを生成する。
        TWCR = (1 << TWINT | 1 << TWEN | 1 << TWSTO); // 割り込みフラグをクリアしてI2Cは有効化したままでストップコンディションを生成する。

        printFloat((float)(tempData & 0xffe0) / 256.0);
        printString("\n");

        _delay_ms(1000);
    }

    //TWCR &= ~(1 << TWEN); // I2Cを無効化する。
    return 0;
}