Skip to content

Instantly share code, notes, and snippets.

@weldtype
Created April 30, 2016 22:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save weldtype/d7f54fcf196b914879d9b70304057849 to your computer and use it in GitHub Desktop.
Save weldtype/d7f54fcf196b914879d9b70304057849 to your computer and use it in GitHub Desktop.
//
// RTC-8564をつないでみる。
// 2016/04/29:edy
// 2016/04/30:detachInterrupt を使う。
// 2016/05/01:変数名の変更、RTCとのやり取りはBCDで行うが、内部ではDECIMAL
// 参考にしたサイト
//http://baticadila.dip.jp/arduino_104.html
//http://iizukakuromaguro.sakura.ne.jp/365_rtc8564/365_rtc8564.html
//http://edu.clipper.co.jp/pg-2-47.html
//http://genine.web.fc2.com/contents/arduino_memo.html
#include <Wire.h>
#define I2C_ADDR (0xA2 >> 1) // 1ビット目未使用のため1ビット右シフトする。
// DECIMAL not BCD
int gYear, gMonth, gDay, gSec, gMin, gHour, gWeek;
void clk_IRQ(void)
{
interrupts();// 割り込みを有効にする。
Wire.beginTransmission(I2C_ADDR);
Wire.write(0x02);
Wire.endTransmission();
delay(1);
Wire.requestFrom(I2C_ADDR, 7);
gSec = bcd2dec(Wire.read() & 0x7f) ; // 秒
gMin = bcd2dec(Wire.read() & 0x7f) ; // 分
gHour = bcd2dec(Wire.read() & 0x3f) ; // 時
gDay = bcd2dec(Wire.read() & 0x3f) ; // 日
gWeek = bcd2dec(Wire.read() & 0x07) ; // 曜日
gMonth = bcd2dec(Wire.read() & 0x1f) ; // 月
gYear = bcd2dec(Wire.read()); // 年
Serial.print(gYear);
Serial.print("/");
Serial.print(gMonth);
Serial.print("/");
Serial.print(gDay);
Serial.print("(");
Serial.print(gWeek);
Serial.print(")");
Serial.print(gHour);
Serial.print(":");
Serial.print(gMin);
Serial.print(":");
Serial.println(gSec);
}
void setup() {
Serial.begin(9600);
Serial.println("RTC Test Start");
Wire.begin(); // I2C の初期化
attachInterrupt(0, clk_IRQ, CHANGE);
/*
Wire.beginTransmission(I2C_ADDR);
Wire.write(byte(0x02)); // RTCモジュールへレジスタの先頭番号を指定
Wire.endTransmission();
Wire.requestFrom(I2C_ADDR, 1); // レジスタの先頭より1バイト転送依頼
byte b = Wire.read(); // 1バイト受信
if (b & 0x80) { // データの bit7 を判定し true なら初期化
}
Serial.println("begin");
*/
}
void loop() {
String sInput;
while (Serial.available()) {
delay(3); //delay to allow buffer to fill
if (Serial.available() > 0) {
char c = Serial.read(); //gets one byte from serial buffer
sInput += c; //makes the string readString
}
}
if (sInput.length() >= 12) {
Serial.print("length:"); Serial.println(sInput.length());
Serial.println(sInput); //see what was received
int year = (sInput.substring(0, 2)).toInt();
int month = (sInput.substring(2, 4)).toInt();
int day = (sInput.substring(4, 6)).toInt();
int hour = (sInput.substring(6, 8)).toInt();
int min = (sInput.substring(8, 10)).toInt();
int sec = (sInput.substring(10, 12)).toInt();
detachInterrupt(0);
setRTC(year, month, day, hour, min, sec);
attachInterrupt(0, clk_IRQ, CHANGE);
}
// 秒が30以上なら切り上げ、未満なら秒切捨て。
if (sInput.substring(0, 1) == "*")
{
Serial.println("sec clear");
if (gSec >= 30) {
// 処理が複雑になるので59分では切り上げはしない
if (gMin < 59) {
gMin++;
}
}
gSec = 0;
detachInterrupt(0);
setRTC(gYear, gMonth, gDay, gHour, gMin, gSec);
attachInterrupt(0, clk_IRQ, CHANGE);
}
sInput = "";
}
void setRTC(int year, int month, int day, int hour, int min, int sec)
{
Wire.beginTransmission(I2C_ADDR);
Wire.write((0x00)); // データを転送する先頭のレジスタ番号を指定
Wire.write((0x20)); // 00 Control 1 STOP(bit5)-1 をセットし動作を停止させる。
Wire.write((0x00)); // 01 Control 2
Wire.write(byte(dec2bcd(sec))); // 02 Seconds 初期値を転送(秒)0 ~ 59
Wire.write(byte(dec2bcd(min))); // 03 Minutes    〃   (分)0 ~ 59
Wire.write(byte(dec2bcd(hour))); // 04 Hours     〃   (時)0 ~ 23
Wire.write(byte(dec2bcd(day))); // 05 Days      〃   (日)1 ~ 31
Wire.write(byte(dec2bcd(subZeller(year + 2000, month, day)))); // 06 Weekdays    〃   (曜日)0 ~ 6
Wire.write(byte(0x80 | dec2bcd(month))); // 07 Months     〃   (月)1 ~ 12
Wire.write(byte(dec2bcd(year))); // 08 Years     〃   (年)0 ~ 99
Wire.write(byte(0x00)); // 09 Minutes Alarm アラームの初期値を転送(分)0 ~ 59
Wire.write(byte(0x00)); // 0A Hours Alarm       〃      (時)0 ~ 23
Wire.write(byte(0x00)); // 0B Days Alarm        〃      (日)1 ~ 31
Wire.write(byte(0x00)); // 0C Weekdays Alarm     〃      (曜日)0 ~ 6
Wire.write(byte(0xff)); // 0D CLKOUT     タイマー用レジスタ
Wire.write(byte(0x00)); // 0E Timer control     〃
Wire.write(byte(0x00)); // 0F Timer         〃
Wire.write(byte(0x00)); // 00 Control 1 STOP(bit5)-0 をリセットし動作を開始する。
// アドレス 0F の次は先頭アドレスの 00 に戻る。
Wire.endTransmission();
}
int subZeller( int y, int m, int d )
{
if ( m < 3 ) {
y--; m += 12;
}
return ( y + y / 4 - y / 100 + y / 400 + ( 13 * m + 8 ) / 5 + d ) % 7;
}
// DECIMAL -> BCD
byte dec2bcd( byte data )
{
return ((( data / 10) << 4) + (data % 10));
}
// BCD -> DECIMAL
byte bcd2dec( byte data )
{
return ((( data >> 4) * 10) + (data % 16));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment