Created
May 7, 2016 01:20
-
-
Save weldtype/004599bebdad71df82dcc87f416384d0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// RTC-8564をつないでみる。 | |
// 2016/04/29:edy | |
// 2016/04/30:detachInterrupt を使う。 | |
// 2016/05/01:変数名の変更、RTCとのやり取りはBCDで行うが、内部ではDECIMAL | |
// 2016/05/07:初期電源投入時の問題を回避 | |
//参考にしたサイト | |
// | |
//Arduinoで実験 (RTCモジュール) | |
//http://baticadila.dip.jp/arduino_104.html | |
// | |
//RTC8564リアルタイムクロック | |
//http://iizukakuromaguro.sakura.ne.jp/365_rtc8564/365_rtc8564.html | |
// | |
//曜日を調べるプログラム | |
//http://edu.clipper.co.jp/pg-2-47.html | |
// | |
//Arduino 割り込みについてのメモ | |
//http://genine.web.fc2.com/contents/arduino_memo.html | |
// | |
//シリアルモニタから入力した数字列を数値に変換する | |
//forum.arduino.cc/index.php?topic=100429.msg753262#msg753262 | |
#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 の初期化 | |
// | |
//0Vからの初期電源投入時には、パワーオンリセットによってVLビットは1にセットされるので | |
//初期化する必要がある。 | |
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 なら初期化 | |
setRTC(16, 1, 1, 12, 0, 0); // 暫定的に日時を2016年1月1日12時0分0秒にセット | |
Serial.println("temporary date/time set"); | |
Serial.println("Set correct date/time"); | |
} | |
attachInterrupt(0, clk_IRQ, CHANGE); | |
} | |
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 CLKOUT用レジスタ CLKOUT Enable freq=1Hzに設定 | |
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