ダイバージェンスメーターのみだと、本当に意味のないアイテムになってしまうので
時計機能だけ入れます。
時計機能をつけるやり方としては、マイコンのクロック数から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 件のコメント:
コメントを投稿