概要
RTC-8564NBというリアルタイムクロックを使った実験です。実際には、秋月電子通商で販売しているリアルタイムクロックモジュールを使った実験です。
Arduinoは内蔵カレンダーを持っていないので、日時や時刻が必要な場合に利用することができます。
目的
RTC-8564NBの全ての機能をArduinoから使えるようにします。
データシート
データシートからわかることをまとめます。
ピン配置
RTC-8564NBは、ピン間隔0.5mmのチップですが、秋月電子通商で販売しているリアルタイムクロックモジュールはこのチップを8ピンのDIPにしたもので、使いやすくなっています。
各ピンの意味は以下の通りです。
ピン番号 | 記号 | 意味 |
---|---|---|
1 | CLKOE | 後述するFEビット、FD1ビット、FD0ビットと組み合わせて使用し、CLKOUT出力状態を制御します。 |
2 | CLKOUT | クロック出力端子。C-MOS出力です。 |
3 | /INT | アラームと定周期タイマ割り込みの割り込み信号を出力します。オープンドレイン端子です。 |
4 | VSS | アース端子。 |
5 | SDA | I2C通信用の信号線です。 |
6 | SCL | I2C通信用のシリアルクロック入力です。 |
7 | N.C. | 未使用。 |
8 | VDD | +5Vに接続します。 |
機能
まずは、データシートから、RTC-8564NBを使って何ができるかを調べます。大きく以下の4種類の機能があります。
項番 | 機能 | 概要 |
---|---|---|
1 | 時計機能 | 西暦(二桁)・月・日・曜・時・分・秒の設定と読み出しが可能。 |
2 | 定周期タイマ割り込み機能 | 244.14μ秒から255分後に割り込みを発生させる。定周期で繰り返し割り込みを発せさせることも可能です。割り込み発生時に/INTにLOWを出力することも可能。 |
3 | アラーム割り込み機能 | 月・日・曜・時・分に対する割り込みを発生させる。割り込み発生時に/INTにLOWを出力することも可能。 |
4 | クロック出力機能 | 32.768kHz、1024Hz, 32Hz, 1HzのCMOS出力が可能。クロックは2番ピンから出力されます。 |
これらの機能は、チップに内蔵されているレジスタを設定することにより実現可能です。このチップはI2Cで制御するので、ArduinoではWireライブラリを用いて制御することができます。
各機能を実現するレジスタ
各機能を実現するためのレジスタの操作方法を調べます。レジスタを示す表の中で、0は実行時には0を設定して利用するビット、xは書き込み不可・読み出し値不定のビットです。
コントロールレジスタ
コントロールレジスタは、機能の起動・停止や、イベントの動作設定、イベント発生状況の把握を行うためのレジスタです。Control1とControl2の2種類があります。
アドレス | 機能 | bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
---|---|---|---|---|---|---|---|---|---|
0x00 | Control 1 | TEST | 0 | STOP | 0 | TEST | 0 | 0 | 0 |
0x01 | Control 2 | 0 | x | 0 | TI/IP | AF | TF | AIE | TIE |
- TEST
- チップメーカーのテスト用ビットです。利用時は0を設定します。
- STOP
- 1のときは、時計などの機能が停止(カウント停止)します。
- TI/IP(Interrupt Signal Output Mode Select. Interrupt/ Periodic)
- 1のときは、定周期タイマ割り込みイベント発生時に、その動作を繰り返します。0のときは、1回だけ動作します。
- AF(Alarm Flag)
- アラーム割り込みイベントが発生すると1になります。自動では0に戻りません(自分で設定する必要があります)。
- TF(Timer Flag)
- 定周期タイマイベントが発生すると1になります。自動では0に戻りません(自分で設定する必要があります)。
- AIE(Alarm Interrupt Enable)
- 1のときはアラーム割り込みイベント発生時に、/INT端子にLOWが出力されます。
- TIE(Timer Interrupt Enable)
- 1のときは定周期割り込みイベント発生時に、/INT端子にLOWが出力されます。
時計・カレンダー機能を制御するためのレジスタ
年月日時分秒曜日を保持するためのレジスタ群です。
アドレス | 機能 | bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
---|---|---|---|---|---|---|---|---|---|
0x02 | Seconds | VL | 40 | 20 | 10 | 8 | 4 | 2 | 1 |
0x03 | Minutes | x | 40 | 20 | 10 | 8 | 4 | 2 | 1 |
0x04 | Hours | x | x | 20 | 10 | 8 | 4 | 2 | 1 |
0x05 | Days | x | x | 20 | 10 | 8 | 4 | 2 | 1 |
0x06 | Weekdays | x | x | x | x | x | 4 | 2 | 1 |
0x07 | Months/Century | C | x | x | 10 | 8 | 4 | 2 | 1 |
0x08 | Years | 80 | 40 | 20 | 10 | 8 | 4 | 2 | 1 |
- VL(Voltage Low Flag)
- 1のときは電圧低下を検出した場合です。この場合はすべてのレジスタを初期設定する必要があります。
- C(Century Bit)
- Cビットが0のとき、年の桁が99から00にオーバーフローすると1になります。1のときは、年の桁がオーバーフローすると0に戻ります。
Seconds/Minutes/Hours/Days/Months/Yearsは、BCD形式で値を保持しています。上位4ビットと下位4ビットがそれぞれ10進数の10の位と1の位を表します。例えば、Yearsレジスタが"0001 0011"のときは、上位4ビットが1、下位4ビットが3なので、13となります。16進表記した値を10進のまま読むことと同等です。
Weekdaysは0から6まで値をとり、それぞれ日曜日から土曜日に対応します。
上記のレジスタ群は読み書き可能なレジスタです。読み込みは時刻の取得、書き込みは時刻の設定です。時刻を設定する際は、コントロールレジスタControl1のSTOPビットを1にして、時刻の更新を停止させます。設定後、STOPビットを0に戻して時刻の更新を再開します。
定周期タイマ割り込み機能を制御するためのレジスタ
定周期タイマ割り込み機能を制御するためのレジスタ群です。
アドレス | 機能 | bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
---|---|---|---|---|---|---|---|---|---|
0x01 | Control 2 | 0 | x | 0 | TI/IP | AF | TF | AIE | TIE |
0x0e | Timer Control | TE | x | x | x | x | x | TD1 | TD0 |
0x0f | Timer | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
- TI/IP(Interrupt Signal Output Mode Select. Interrupt/ Periodic)
- 1のときは、定周期タイマ割り込みイベント発生時に、その動作を繰り返します。0のときは、1回だけ動作します。
- TF(Timer Flag)
- 定周期タイマイベントが発生すると1になります。自動では0に戻りません(自分で設定する必要があります)。
- TIE(Timer Interrupt Enable)
- 1のときは定周期割り込みイベント発生時に、/INT端子にLOWが出力されます。
- TE(Timer Enable)
- 1のときは定周期割り込み機能が動作します。0のときは停止します。
- TD1、TD0
- 定周期割り込みのソースクロックを指定します。また、TI/IPが1のときの/INTへLOWを出力時間はTD1とTD0、Timerレジスタの設定値の組み合わせで決まります。
TD1とTD0の組み合わせによるソースクロックの値、TI/IPが1のときの/INTへのLOW出力時間は以下の通りです。
TD1 | TD0 | 周波数 | 周期 | /INT出力時間(Timer=1 ) | /INT出力時間(Timer>1) |
---|---|---|---|---|---|
0 | 0 | 4096Hz | 244.14μs | 122μs | 244μs |
0 | 1 | 64Hz | 15.625ms | 7.813ms | 15.625ms |
1 | 0 | 1Hz | 1秒(1秒桁更新時)(※) | 15.625ms | 15.625ms |
1 | 1 | 1/60Hz | 1分(1分桁更新時))(※) | 15.625ms | 15.625ms |
(※)時計の秒もしくは分の更新と同期します。このため、最初の1周期が設定より短い時間で割り込みが発生します。
Timerは、設定するタイマ値(16進)です。例えば、TD1=1、TD0=0で、Timerが0x0aと設定すると、1Hz x 10=10秒で割り込みが発生します。さらにControl2のTI/IPが1であれば、10秒ごとに割り込みが発生します。
アラーム割り込み機能を制御するためのレジスタ
アラーム割り込み機能を制御するためのレジスタ群です。
アドレス | 機能 | bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
---|---|---|---|---|---|---|---|---|---|
0x01 | Control 2 | 0 | x | 0 | TI/IP | AF | TF | AIE | TIE |
0x09 | Minute Alarm | AE | 40 | 20 | 10 | 8 | 4 | 2 | 1 |
0x0a | Hour Alarm | AE | x | 20 | 10 | 8 | 4 | 2 | 1 |
0x0b | Day Alarm | AE | x | 20 | 10 | 8 | 4 | 2 | 1 |
0x0c | Weekday Alarm | AE | x | x | x | x | 4 | 2 | 1 |
- AF(Alarm Flag)
- アラーム割り込みベントが発生すると1になります。自動では0に戻りません(自分で設定する必要があります)。
- AIE(Alaram Interrupt Enable)
- 1のときはアラーム割り込みイベント発生時に、/INT端子にLOWが出力されます。
- AE
- AEが1のときは、そのレジスタは比較対象とはなりません。例えば、毎時1分にアラーム割り込みを発生させたいときは、Hour/Day/WeekdayのAEを1にし、MinuteのAEだけを0にします。ただし、全てのAEを1にすると、アラーム割り込みイベントは発生しません。
Minute Alarm/Hour Alarm/Day Alarmは、AEビットを除いて、BCD形式で値を保持しています。
Weekday Alarmは、AEビットを除いて、0から6まで値をとり、それぞれ日曜日から土曜日に対応します。
クロック出力機能を制御するためのレジスタ
クロック出力機能を制御するためのレジスタです。
アドレス | 機能 | bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
---|---|---|---|---|---|---|---|---|---|
0x0d | CLKOUT Frequency | FE | x | x | x | x | x | FD1 | FD0 |
- FE(Frequency output Enable)
- 1のときはクロック出力機能を有効になります。
- FD1、FD0
- 2つのビットの組み合わせにより出力する周波数を決定します。
クロック周波数は以下の通りです。
FD1 | FD0 | 周波数 |
---|---|---|
0 | 0 | 32768Hz |
0 | 1 | 1024Hz |
1 | 0 | 32Hz |
1 | 1 | 1Hz |
クロック出力は、CLKOEピンがHIGHのときだけ有効となります。LOWのときはレジスタの設定に関係なく無効です。
Arduinoからの操作
レジスタの読み書き
Arduinoからチップのレジスタへの読み書きは、以下のように行います。このチップのスレーブアドレスは0x51です。
レジスタからの読み込み
レジスタから値を読み込む手順は以下の通りです。
- Wire.beginTransmission(スレーブアドレス)
- Wire.write(レジスタのアドレス)
- Wire.endTransmision()
- Wire.requestFrom(スレーブアドレス, 読み込むバイト数)
- Wire.read() (上記で指定したバイト数文繰り返し)
レジスタのアドレスを書き込んだ後、データを1バイトずつ読み込みます。2度目以降のWire.read()では、チップが自動的にアドレスをインクリメントするので、連続したレジスタから値を読み込むことができます。 レジスタへの書き込み
レジスタに値を書き込む手順は以下の通りです。
- Wire.beginTransmission(スレーブアドレス)
- Wire.write(レジスタのアドレス)
- Wire.write(データ、書き込むデータの個数)
- Wire.endTransmission()
レジスタのアドレスを書き込んだ後、続けてデータを1バイトずつ書き込みます。複数のデータを書き込む場合は、チップが自動的にアドレスをインクリメントするので、連続したレジスタに値を書き込むことができます。
ライブラリ
RTC8545をArduinoから利用するためのライブラリを作成しました。RTC8564というオブジェクトを作成します。
データ型
時刻とアラームを表すために以下の2つのデータ型を定義しています。POSIXのstruct tm型に似せていますが、月が0からではなく1から始まるところが違います。Arduinoで、月の名前を配列に入れて利用するケースがあまりなさそうなので、日本語としてわかりやすいようにしました。
|
|
API(メソッド)
以下のAPIを実装しました。
項番 | API(シグネチャ) | 説明 | 備考 |
---|---|---|---|
1 | void begin() | オブジェクトを初期化します。カレンダーを13年1月1日(火)0時0分0秒に設定します。 | |
2 | void begin(struct dateTime *dt) | オブジェクトを初期化します。dtに格納したカレンダーを設定します。 | dtはポインタ渡しです。 |
3 | void setDateTime(struct dateTime *dt) | カレンダーを設定します。 | dtはポインタ渡しです。 |
4 | int getDateTime(struct dateTime *dt) | カレンダーを取得します。VLフラグが1のときは-1を返すので、カレンダーを再設定する必要があります。 | dtはポインタ渡しです。dtの領域は呼び出し側が確保する必要があります。 |
5 | void setAlarm(uint8_t enableFlag, struct alarmTime *at, uint8_t interruptEnable) | アラーム割り込みを設定します。enableFlagsを設定した要素がアラーム対象となります。interruptEnableをtrueにすると、アラーム割り込み発生時に/INTがLOWになります。 | atはポインタ渡しです。 |
6 | void getAlarm(uint8_t *enableFlags, struct alarmTime *at) | アラーム情報を取得します。 | atはポインタ渡しです。atの領域は呼び出し側が確保する必要があります。 |
7 | int getAlarmFlag() | アラームフラグを取得します。 | |
8 | void clearAlarmFlag() | アラームフラグをクリアします。 | |
9 | void setTimer(uint8_t enableFlag, uint8_t repeatMode, uint8_t clockMode, uint8_t counter, uint8_t interruptEnable) | タイマー割り込みを設定します。 | |
10 | int getTimerFlag() | タイマーフラグを取得します。 | |
11 | void clearTimerFlag() | タイマーフラグをクリアします。 | |
12 | void setClkoutFrequency(uint8_t enableFlag, uint8_t flag) | CLKOUTに出力する周波数を設定します。 |
Arduinoとの接続
サンプルスケッチを動作させるには、以下の通りArduinoとRTC8564モジュールを接続します。
RTC8564のピン番号 | Arduinoのピン番号 | 意味 |
---|---|---|
1 | - | CLKOE |
2 | - | CLKOUT |
3 | 12 | /INT |
4 | GND | VSS |
5 | A4 | SDA |
6 | A5 | SCL |
7 | - | N.C. |
8 | +5V | VDD |
スケッチ
今回の実験に使用したスケッチを以下に示します。GitHubのリポジトリは、こちら。
sample.ino
|
|
RTC8564.h
|
|
RTC8564.cpp
|
|
バージョン
Hardware: | Arduino UNO R3 |
Software: | Arduino IDE 1.5.5 |
最終更新日
July 14, 2024