DS3231には、内蔵クリスタルを温度補償するための温度センサー(10ビット分解能)が内蔵されている。その温度を見てみる。値は64秒ごとに更新される。
#include <avr/io.h> #include <util/delay.h> #include "USART.h" #include "myI2Cv2.h" #include "DS3231.h" int main(){ initUSART(); DS3231 rtc; // リアルタイムクロックDS3231 (I2Cスレーブ)を実体化する。 myI2Cv2.enable(80); // AVRのI2Cモジュールを有効化する。 while(1){ printFloat(rtc.getTempFloat()); printString(" deg C\n"); _delay_ms(1000); } myI2Cv2.disable(); return 0; }
uint16_t getTempRaw(); float getTempFloat(); uint8_t isCalibrating(); void calibrate(); // TCXO (temperature-compensated crystal oscillator)を強制的に較正する。
uint16_t DS3231::getTempRaw(){ uint8_t buff[2]; myI2Cv2.start(); // スタートコンディションを生成して、 myI2Cv2.writeByte(ADDRESS_W); // スレーブに呼びかけて、writeであることを示して、 myI2Cv2.writeByte(MSB_OF_TEMP); // スレーブ側のレジスタポインタをセットして、 myI2Cv2.start(); // スタートコンディションを生成して、 myI2Cv2.writeByte(ADDRESS_R); // スレーブに呼びかけて、readであることを示して、 myI2Cv2.readBytesNACK(2, buff); // 2バイトぶんの温度データを読み出して、 myI2Cv2.stop(); // ストップコンディションを生成して、 return ((uint16_t)buff[0] << 8) | (buff[1] & 0xC0); // 16ビットに並べ換えて返す(有効なのは上位10ビット)。 } float DS3231::getTempFloat(){ return (float)getTempRaw() / 256.0; } uint8_t DS3231::isCalibrating(){ myI2Cv2.start(); // スタートコンディションを生成して、 myI2Cv2.writeByte(ADDRESS_W); // スレーブに呼びかけて、writeであることを示して、 myI2Cv2.writeByte(CONTROL_STATUS); // スレーブ側のレジスタポインタをセットして、 myI2Cv2.start(); // スタートコンディションを生成して、 myI2Cv2.writeByte(ADDRESS_R); // スレーブに呼びかけて、readであることを示して、 uint8_t cs = myI2Cv2.readByteNACK(); // 目的のレジスタ(CONTROL_STATUS)の内容を読み出して、 myI2Cv2.stop(); // ストップコンディションを生成して、 return (cs & (0b100)) == 0b100; // 目的のビット[2] (BSYビット)が立っているかどうか(較正中かどうか)を返す。 } void DS3231::calibrate(){ if(!isCalibrating()){ // (較正中でないときだけ実行する) myI2Cv2.start(); // スタートコンディションを生成して、 myI2Cv2.writeByte(ADDRESS_W); // スレーブに呼びかけて、writeであることを示して、 myI2Cv2.writeByte(CONTROL); // スレーブ側のレジスタポインタをセットして、 myI2Cv2.start(); // スタートコンディションを生成して、 myI2Cv2.writeByte(ADDRESS_R); // スレーブに呼びかけて、readであることを示して、 uint8_t cnt = myI2Cv2.readByteNACK(); // 目的のレジスタ(CONTROL)の内容を読み出して、 cnt |= (1 << 5); // 目的のビット[5] (CONVビット)に1を立てて、 myI2Cv2.start(); // スタートコンディションを生成して、 myI2Cv2.writeByte(ADDRESS_W); // スレーブに呼びかけて、writeであることを示して、 myI2Cv2.writeByte(CONTROL); // スレーブ側のレジスタポインタをセットして、 myI2Cv2.writeByte(cnt); // スレーブ側のCONTROLレジスタを書き換えて、 myI2Cv2.stop(); // ストップコンディションを生成する。 } }