このところI2CでつなげるアイテムとAVRで遊んできました。
- 温度センサーLM73
- カラーセンサーADJD-S371-QR999
今回は秋月で売っているリアルタイムクロックモジュールRTC-8564NBを使ってみました(通販番号I-00233)。このICはある意味定番のようで、ぐぐってみると、いろいろな方が使われています。
メーカーのサイトです。データシートとアプリケーションノートがダウンロードできます。
秋月のモジュールは変換基板上に実装されているので、そのままブレッドボードに挿して使えます。

デフォルトではI2Cのラインはプルアップされていないので、自分でプルアップしてやる必要があります。もしくはジャンパをはんだで盛って接続してやります。プルアップ抵抗は2.2kΩにしています。
ピン配置です(写真と合わせてあります)。
CLKOUTは設定で周期を変えれますが、今回は1Hzのパルスを出力しています。CLKOUTをAVRの外部割込み入力INT0につないでいます。割り込みが起きるたびにRTC-8564NBから時間を読み取ってLCDに表示しています。

ソースです。
時間の調整機能がないので、時計としては不完全です。
データはBCDなので、表示するのに割り算がいりません。読み出したデータの上位にはゴミがついているのでちゃんとマスクしてやらないといけません。
今回はじめて使ったのは外部割込みとCPUのスリープです。
勝手にカウントアップしてくれるし、60進数のこととか考えなくても読み出すだけで時計になっているので簡単です。
- 温度センサーLM73
- カラーセンサーADJD-S371-QR999
今回は秋月で売っているリアルタイムクロックモジュールRTC-8564NBを使ってみました(通販番号I-00233)。このICはある意味定番のようで、ぐぐってみると、いろいろな方が使われています。
メーカーのサイトです。データシートとアプリケーションノートがダウンロードできます。
秋月のモジュールは変換基板上に実装されているので、そのままブレッドボードに挿して使えます。

デフォルトではI2Cのラインはプルアップされていないので、自分でプルアップしてやる必要があります。もしくはジャンパをはんだで盛って接続してやります。プルアップ抵抗は2.2kΩにしています。
ピン配置です(写真と合わせてあります)。
5 SDA 4 Vss 6 SCL 3 INT 7 NC 2 CLKOUT 8 Vdd 1 CLKOE
CLKOUTは設定で周期を変えれますが、今回は1Hzのパルスを出力しています。CLKOUTをAVRの外部割込み入力INT0につないでいます。割り込みが起きるたびにRTC-8564NBから時間を読み取ってLCDに表示しています。

ソースです。
#include <avr/io.h> #include <avr/interrupt.h> #include <avr/sleep.h> #include <util/twi.h> #include <util/delay.h> #include "lcd.h" #include "i2c.h" #define RTC8564 (0x51 << 1) #define CTRL1 0x00 #define CTRL2 0x01 #define SEC 0x02 #define MIN 0x03 #define HOUR 0x04 #define DAY 0x05 #define WDAY 0x06 #define MONTH 0x07 #define YEAR 0x08 #define CKOUT 0x0d // CLKOUT frequency 7:FE 1:FD1 0:FD0 #define CTRLT 0x0e // Timer Control 7:TE 1:TD1 0:TD0 // RTC8564にコマンドを送る void write(uint8_t address, uint8_t data) { i2c_start(RTC8564 | TW_WRITE); i2c_write(address); i2c_write(data); i2c_stop(); } // 曜日の名前 const char *wdname[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", }; // 割り込み処理ルーチン (see iomx8.h) ISR(INT0_vect) { uint8_t year, month, day, wday, hour, min, sec; // RTC-8564の読み込み i2c_start(RTC8564 | TW_WRITE); i2c_write(SEC); i2c_stop(); i2c_start(RTC8564 | TW_READ); sec = i2c_read_ack() & 0x7f; // 02 秒 min = i2c_read_ack() & 0x7f; // 03 分 hour = i2c_read_ack() & 0x3f; // 04 時 day = i2c_read_ack() & 0x3f; // 05 日 wday = i2c_read_ack() & 0x07; // 06 曜日 month = i2c_read_ack() & 0x1f; // 07 月 year = i2c_read_nak(); // 08 年 i2c_stop(); // 表示 lcd_locate(0, 0); lcd_hex2(0x20); lcd_hex2(year); lcd_putc('/'); lcd_hex2(month); lcd_putc('/'); lcd_hex2(day); lcd_locate(0, 1); lcd_hex2(hour); lcd_putc(':'); lcd_hex2(min); lcd_putc(':'); lcd_hex2(sec); lcd_locate(0, 2); lcd_puts(wdname[wday]); } int main() { lcd_init(); i2c_init(); _delay_ms(1000); // 1秒待つ // 外部割込み初期化 EICRA = _BV(ISC01) | _BV(ISC00); // INT0立ち上がりエッジ EIMSK = _BV(INT0); // INT0割り込み許可 // RTC8564初期化 write(CTRL1, 0x20); // stop write(CTRL2, 0x00); write(CTRLT, 0x00); write(CKOUT, 0x83); // 7:FE=1 10:FD=11 (1Hz) write(YEAR, 0x08); // 年 (下位2桁) write(MONTH, 0x10); // 月 write(DAY, 0x12); // 日 write(HOUR, 0x23); // 時 write(MIN, 0x59); // 分 write(SEC, 0x50); // 秒 write(WDAY, 0x00); // 曜日 write(CTRL1, 0x00); // start sei(); // 割り込み許可 while(1){ sleep_enable(); // CPUスリープ sleep_cpu(); sleep_disable(); } }
時間の調整機能がないので、時計としては不完全です。
データはBCDなので、表示するのに割り算がいりません。読み出したデータの上位にはゴミがついているのでちゃんとマスクしてやらないといけません。
今回はじめて使ったのは外部割込みとCPUのスリープです。
勝手にカウントアップしてくれるし、60進数のこととか考えなくても読み出すだけで時計になっているので簡単です。
※コメント投稿者のブログIDはブログ作成者のみに通知されます