AVRのI2Cモジュール / リアルタイムクロックDS3231 / 方形波出力を見てみる

DS3231のINT/SQW端子からは、1Hz、1024Hz、4096Hz、8192Hzのいずれかの方形波が出力できる。
f:id:ti-nspire:20200205083324p:plain:h270 f:id:ti-nspire:20200205083836p:plain:h270

f:id:ti-nspire:20200205084115p:plain:w500
f:id:ti-nspire:20200205084157p:plain:w300
INTCNビットが0のとき、INT/SQW端子から方形波が出力される。

#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モジュールを有効化する。

    rtc.disable32kHz(); // 32kHz出力はoffにしておく。しなくてもよい。
    
    while(1){
        printString("Enter a freq, 1, 1024, 4096, or 8192: ");
        uint16_t freq = getNumber16();
        
        if(freq){rtc.enableSqWave(freq);}
        else    {rtc.disableSqWave();}
    }

    myI2Cv2.disable();
    return 0;
}
    void enableSqWave(uint16_t freq); // freq = 1, 1024, 4096, or 8192。これ以外の場合は出力を停止してHi-Z状態にする。
    void disableSqWave();
void DS3231::enableSqWave(uint16_t freq){
    myI2Cv2.start();              // スタートコンディションを生成して、
    myI2Cv2.writeByte(ADDRESS_W); // スレーブに呼びかけて、writeであることを示して、 
    myI2Cv2.writeByte(CONTROL);   // スレーブ側のレジスタポインタをセットして、

    myI2Cv2.start();                      // スタートコンディションを生成して、
    myI2Cv2.writeByte(ADDRESS_R);         // スレーブに呼びかけて、readであることを示して、 
    uint8_t cnt = myI2Cv2.readByteNACK(); // 目的のレジスタの内容を読み出して、

    /******* 書き改めるための1バイトデータを用意して、*******/
    cnt &= ~(1 << 4 | 1 << 3 | 1 << 2); // 一旦CONTROLレジスタのRS2、RS1、INTCNの3ビットをクリアして、
    switch(freq){                       // 目的のビットをセットするが、
        case    1: break;
        case 1024: cnt |= (1 << 3); break;
        case 4096: cnt |= (1 << 4); break;
        case 8192: cnt |= (1 << 4 | 1 << 3); break;
        default  : cnt |= (1 << 2); break; // 規定値以外であったらINTCNビットをセットして方形波出力を停止する。
    }
    /********************************************************/

    myI2Cv2.start();              // スタートコンディションを生成して、
    myI2Cv2.writeByte(ADDRESS_W); // スレーブに呼びかけて、writeであることを示して、 
    myI2Cv2.writeByte(CONTROL);   // スレーブ側のレジスタポインタをセットして、
    myI2Cv2.writeByte(cnt);       // そのレジスタを書き換えて、
    myI2Cv2.stop();               // ストップコンディションを生成する。
}
void DS3231::disableSqWave(){
    enableSqWave(0);
}