PICでI2C - リアルタイムクロック(RTC) DS1307+の使い方
リアルタイムクロック(RTC) DS1307+について簡単に使い方をまとめてみました。
記事を書いておいてなんですが、RTCについてはDS3234Sがお勧めです。
「PICでSPI - 超高精度SPIバスRTC(リアルタイムクロック)DS3234Sの使い方」 (ソース付き)
「PICでSPI - 超高精度SPIバスRTC(リアルタイムクロック)DS3234Sの実装」
名前とおりとても精度(確度)がいいです。1周間で1秒も狂わないような。歩度の微調整が可能なのですが、それをしなくてもこの精度でした。
DS3234Sの問題は上のタイトルにあるようにインターフェースがSPIであることでしょうか。私はRTCだけSPIでその他のデバイスは(今のところ)ぜんぶI2Cです。まあ一度作ってしまえばSPIもI2Cもそのままソースを使えるので問題ないと言えば問題ないんですが。
SSPが一つしかないのでI2CとSPIが同時に使えないと悩んでいる方はこちらの記事をどうぞ。PIC16F1705でI2CのLCDとSPIのDS3234Sを使った例があります。
「ほよほよのブログ - 超高精度リアルタイムクロックDS3234Sを動かす」
=====================
例によって秋月電子通商で買ってきました(I2C接続RTC(リアルタイムクロック)DS1307+)
これは8ピンDIPなので扱いやすいです。
外付けの水晶振動子が必要ですので忘れずに買っておきます(例えば同じ秋月ですと「クリスタル(水晶発振子) 32.768kHz」があります)つまり精度は水晶振動子の精度に依存します。
--------
まず電源電圧は5Vです。データシートには4.5V~5.5Vとあります。3.3Vでは動かなかったと思います。
RTCですからバックアップ電源が必要でしょう。バックアップ電源は2V~3.5Vとなっています。主電源(Vcc)の電圧がバックアップ電源の1.25倍より低くなるとバックアップモードに入ります。つまり主電源とバックアップ電源を同じ電圧なんかにしてしまうと動きませんので注意が必要です(データシート上はこの倍率は1.216倍~1.284倍とばらつきがありますのでギリギリの設計はしない方がいいでしょう)
私は3.3Vから逆流防止用のダイオードを介して充電している1Fの電気二重層コンデンサーをバックアップ電源としていますがリチウム電池を使うというのが常識的だと思います。
電源電圧が5Vとなると3.3Vで使っているPICの回路で使えるかというのが心配になるのですがこれはだいじょうぶです。
VIH 2.2Vmin、VIL 0.8Vmaxなので3.3VでプルアップしてあるSCL/SDAバスに接続して使うことができます(出力ピンはとうぜんオープンコレクタです)
------
使い方は簡単です。レジスタのアドレスを指定して読み書きするだけです。
レジスタはアドレス0から順番に
Seconds
Minutes
Hours
Day
Date
Month
Year
Control
とならんでおりそのあとに自由に使えるRAMが56byteあります。
日付時刻のデータは原則BCDです。つまり上位4ビットが十の位、下位4ビットが一の位です。
Hoursのbit6は12/24の切り替えのためのビットで1だったら12時間表示です。12時間表示の場合はbit5がAM/PMを表し1だったらPMです。
Dayは1~7で曜日です。1が何曜日だったか調べていません。すみません。
Yearは下位二桁のみです。
Controlは秒信号等の出力の制御用です。毎秒1回パルスを出力するのであれば0x10と設定しておきます。
------
使い方は簡単なんですが、時計の場合は日時の初期設定をやったり進み遅れが出たときの調整したりといった機能が必要なのでけっこう面倒です。
時刻合わせについては別に記事を書きました。
「RTC(リアルタイムクロック)の時刻を合わせる方法 - DS3234Sを例に」
DS3234Sについてのものですが手法としては参考になると思います。
基本的なところだけソースを示します。
いつもどおり「きむ茶工房ガレージハウス - I2C通信の実験」にあるI2Cライブラリを使うことを前提に書いています。
=> “自前”のものも用意しました。
「I2Cのソース - PIC12F1822/16F1705/16F1938/18F26K22 - LCD(ACM1602)を例にして」
日時データの取得
ans = I2C_Start(0x68,RW_0);
if (ans == 0) {
I2C_Send(0) ;
ans = I2C_rStart(0x68,RW_1);
if (ans == 0) {
for( j=0; j < 7; j++ ) {
ip_DS1307[j] = I2C_Receive(ACK);
}
ip_DS1307[j] = I2C_Receive(NOACK);
}
}
I2C_Stop() ;
取得したデータをそのまま16進表示すればいいです。
LCD_SetCursor(0,0);
for( j=6; j > -1 ; j-- ) {
if( j == 3 ) {
LCD_Putc(' '); // 日付と時刻の間に空白を入れる
continue;
}
putLCDhex(ip_DS1307[j]); // 十六進表示すればOK
}
LCD_Putc(' ');
日時の初期設定や調整のときは該当するデータのアドレスに書き込みます。
ans = I2C_Start(0x68,RW_0);
if (ans == 0) {
I2C_Send(iLoc);
switch(iLoc) {
case 0: // 秒をリセットする
I2C_Send(0x00);
break;
case 1: // 分の設定
if(ip_DS1307[iLoc] < 0x59) {
I2C_Send(ip_DS1307[iLoc]+1);
} else {
I2C_Send(0);
}
break;
case 2: // 時の設定
if(ip_DS1307[iLoc] < 0x23) {
I2C_Send(ip_DS1307[iLoc]+1);
} else {
I2C_Send(0);
}
break;
case 3: // 曜日の設定
if(ip_DS1307[iLoc] < 0x07) {
I2C_Send(ip_DS1307[iLoc]+1);
} else {
I2C_Send(0);
}
break;
case 4: // 日の設定
if(ip_DS1307[iLoc] < 0x31) {
I2C_Send(ip_DS1307[iLoc]+1);
} else {
I2C_Send(1);
}
break;
case 5: // 月の設定
if(ip_DS1307[iLoc] < 0x12) {
I2C_Send(ip_DS1307[iLoc]+1);
} else {
I2C_Send(1);
}
break;
case 6: // 年の設定
if(ip_DS1307[iLoc] < 0x15) {
I2C_Send(ip_DS1307[iLoc]+1);
} else {
I2C_Send(0x14);
}
break;
default:
break;
}
}
I2C_Stop() ;
------
関連
「I2Cデバイス・アドレス一覧」
「同じアドレスのI2Cデバイスを使う」
「PICで平方根 - 白金薄膜抵抗で温度を測る」
「PICでI2C - 1 (温度計を作る)」
「PICでI2C - 液晶(LCD)ディスプレイ(ACM1602N1-FLW-FBW)に表示する」
「PICでI2C - LCD(液晶)ディスプレイによる違い」
「I2C大気圧センサーLPS331の驚くべき分解能」
「I2C大気圧温度センサーLPS331 - 海面更生気圧を気象庁とくらべてみた」
「炭素皮膜抵抗の温度係数を測定する話」
「サーミスタによる温度測定の精度」
「サーミスタ温度計の精度を調べる - 1」
「ミニ恒温槽の作成に向けて - 1」
参考
「きむ茶工房ガレージハウス - PICの動かせ方入門はこちら - 16F1938覚書」
「きむ茶工房ガレージハウス - I2C通信の実験」
「きむ茶工房ガレージハウス - 気圧センサーで大気圧と標高を測定して見ます(MPL115A1)(MPL115A2)」
「ほよほよのブログ - 超高精度リアルタイムクロックDS3234Sを動かす」
(I2CとSPIの共用)
« 今日10月31日から三日連続で星食が見られます | トップページ | PCオーディオでリサジュー図形を見る »
「趣味の電子工作」カテゴリの記事
- PICで作る100MHz周波数カウンタ検証用XOR(エクスクルーシブオア)逓倍器(2016.03.08)
- 150MHz(~200MHz?)周波数カウンター用プリスケーラー(1/4分周器)(2016.03.06)
- 測温抵抗体(Pt100、白金薄膜温度センサー)の抵抗値を温度に変換する(平方根を使わない)計算式(2016.03.01)
- GPS/JJY(標準電波)を基準周波数源とするためのPLLの詳細(2016.02.27)
- GPS受信モジュール1PPS対決 - GE-612T vs GM-5157A(2016.02.21)
この記事へのコメントは終了しました。
コメント