13.時計機能

ダイバージェンスメーターのみだと、本当に意味のないアイテムになってしまうので
時計機能だけ入れます。
時計機能をつけるやり方としては、マイコンのクロック数から1秒を計算して
順次足していき表示させる方法と、ICから時間情報を貰って表示させる方法があります。
前回とおなじくRTCモジュールを使用します。
http://akizukidenshi.com/catalog/g/gI-00233/これにバックアップ用の電池を使用して、電源が切れても時刻だけは残るようにします。
以前良くわからず買ってしまった
http://akizukidenshi.com/catalog/g/gP-00706/
が役立ちます!

よくわからないのがマイコンでは5Vを使用していて、RTCでは3Vを使用して平気なのかです。
通信はI2Cを使うのでその辺の電圧差異がどうなるのかわかりません。
が、動いちゃいましたので平気なのでしょう・・・危ない事ならばぜひお知らせください。
何せ素人なモノで。
で、どうやって動かしたかは、SCL,SDA線をプルアップして使うわけですが、これを
5Vのほうでプルアップします。そしてVDDは3V、VSSは3V,5Vと両方つなげました。

i2c通信のプログラムは、
「わかるマイコン電子工作AVRマイコン活用ブック」 の◆(4-3)MP3プレーヤ で使われている
i2c.cとi2c.hを使用しました。
ただし、i2c_eeprom_write()とvoid i2c_eeprom_read()を改造しています。
なぜこんな改造したかは思い出せません。

http://nicotak.com/avr/

void i2c_2_write(
    unsigned long addr,
    unsigned char* data,
    unsigned char bytecnt)
{
    i2c_start();
    i2c_writebyte(0xa2);     // SLA + W
    i2c_writebyte(addr);    // address(high 8bits)
    while(bytecnt > 0){
        i2c_writebyte(*data++);
        bytecnt--;
    }
    i2c_stop();
}

void i2c_2_read(
    unsigned long addr,
    unsigned char* data, unsigned char bytecnt)
{
    i2c_start();
    i2c_writebyte(0xa2);      // SLA + W
    i2c_writebyte(addr);     // address(high 8bits)
    i2c_start();
    i2c_writebyte(0xa2 | 0x01);  // SLA + R
    while(bytecnt > 0){
        *data++ = i2c_readbyte(bytecnt == 1);
        bytecnt--;
    }
    i2c_stop();
}


これを使って、初期値と割込みを指定します。(バックアップ電池をつけたので時刻初期値はいらなくなりますが。)
unsigned char init_rct_data[0x10] ={0x20,0x00,0x00,0x00,0x12,0x18,0x06,0x09,0x10
                                    ,0x80,0x80,0x80,0x80,0x00,0x00,0x00};
unsigned char set_rtc_int[3] ={0x00,0x11,0x00};
unsigned char set_rtc_int2[3] ={0x83,0x82,0x01};

    i2c_init(400000);
    i2c_2_write(0x00, init_rct_data ,0x10);    // 初期値設定
    i2c_2_write(0x00, set_rtc_int ,2); 
    i2c_2_write(0x0d, set_rtc_int2 ,3);    // 一秒周期割込み設定

    // 外部割込み初期化
    EICRA = 2;    // 立ち上がり
    EIMSK = 1;  // INT0割り込み許可
    sei();


購入すると一緒にデータシートが入っていますので、それとにらめっこしてください。
私のデータはいらないのが結構入っていますが動いてるので消してません。
これで一秒ごとに割り込みが入ります。
割り込みが入ったら、RTCから時刻を読み取って変数に格納でいいと思います。
 ///////////////////////////////////////
//
//  INT0割込み
//
///////////////////////////////////////
ISR (INT0_vect)
{
    make_time();


}
///////////////////////////////////////
//
//  時間調整
//
///////////////////////////////////////
void make_time()
{
    i2c_2_read( 0 , rw_rct_data ,0x9);

    year0 = (rw_rct_data[8] >> 4) & 0x0f;
    year1 = rw_rct_data[8] & 0x0f;
    mon0  = (rw_rct_data[7] >> 4) & 0x01;
    mon1  = rw_rct_data[7]& 0x0f;
    day0  = (rw_rct_data[5] >> 4) & 0x03;
    day1  = rw_rct_data[5]& 0x0f;
    hour0 = (rw_rct_data[4] >> 4) & 0x03;
    hour1 = rw_rct_data[4]& 0x0f;
    min0  = (rw_rct_data[3] >> 4) & 0x07;
    min1  = rw_rct_data[3]& 0x0f;
    sec0  = (rw_rct_data[2] >> 4) & 0x07;
    sec1  = rw_rct_data[2]& 0x0f;

}
変数はメンドイのでグローバルにしています。
 毎回読み込まなくても、電池またはusb使用にするならば、
起動時に一回読み込むだけで、後は秒数をカウントアップさせればいいような気もします。

最終的にそうするかもしれません。


------------------------
そういうのも試してみました。ちらつきなくなったな・・・
しょっぱなにget_time()で読み込んで、
一秒ごとにカウントアップ。
日付計算はめんどくさいので、get_time()

///////////////////////////////////////
//
//  INT0割込み
//
///////////////////////////////////////
ISR (INT0_vect)
{
    make_time();

}
///////////////////////////////////////
//
//  時間調整
//
///////////////////////////////////////
void make_time()
{
    sec1++;
    if(sec1>9){
        sec1 = 0;
        sec0++;

        if(sec0>5){
            sec0 = 0;
            min1++;

            if(min1>9){
                min1 = 0;
                min0++;

                if(min0>5){
                    min0 = 0;
                    hour1++;

                    if((hour0 * 10 +hour1) > 23){
                        get_time();

                    }else if(hour1>9){
                        hour1 = 0;
                        hour0++;
                    }
                }
            }
        }
    }


}
///////////////////////////////////////
//
//  時間調整
//
///////////////////////////////////////
void get_time()
{
    i2c_2_read( 0 , rw_rct_data ,0x9);

    year0 = (rw_rct_data[8] >> 4) & 0x0f;
    year1 = rw_rct_data[8] & 0x0f;
    mon0  = (rw_rct_data[7] >> 4) & 0x01;
    mon1  = rw_rct_data[7]& 0x0f;
    day0  = (rw_rct_data[5] >> 4) & 0x03;
    day1  = rw_rct_data[5]& 0x0f;
    hour0 = (rw_rct_data[4] >> 4) & 0x03;
    hour1 = rw_rct_data[4]& 0x0f;
    min0  = (rw_rct_data[3] >> 4) & 0x07;
    min1  = rw_rct_data[3]& 0x0f;
    sec0  = (rw_rct_data[2] >> 4) & 0x07;
    sec1  = rw_rct_data[2]& 0x0f;

}

0 件のコメント:

コメントを投稿