DS1307（RTCモジュール）の使い方

# 概要
DS1307（RTCモジュール）の使い方メモです
とりあえず、

https://www.petitmonte.com/robot/howto_ds1307.html

この方の記事で動作が確認できます。

デバイスのアドレス：0x68



# アドレスマップ
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/c85c56ea-19a0-61f9-a2de-9b6f50089a97.png)

アドレスのメモリ値を読み込むことで、使用できます。
日時は逆にメモリの値を書き換えることで初期化できます。
データはBCD(Binary-Coded Decimal)つまり、10進法で保存されています。

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/8885ce9d-b46f-da46-0d21-1b5e6f4298bd.png)

### 秒
|bit  |機能 |数値  |
|---|---|---|
|0~3bit|一の位|0~9|
|4~6bit|十の位|0~5|

0x12が保存されている場合、12秒という意味です。10進数に直して28にする必要はありません。

### 分
|名称|機能 |数値  |
|---|---|---|
|CH|発信機ON,OFF|1:OFF|
|12/24|12/24hour表示|1:12|
|A/P|AM/PM|1:PM|

24時間表記で考えるならば、秒と同じ考えでOKです。
12時間表記なら6bit目をHIGHにする必要がありますね。


# SQピン
特定周波数の方形波を出力することができる
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/82c83966-ef05-9df5-5355-4df2df19f8fc.png)

# I2C通信
こんな感じでOKです。
連続読み込みでも、一個ずつ読み込んでもOKです。
時間の初期設定していないときはsetup内のコメントを解除して数値を打ち込んで書き込めば行けます。
書き込んだ後は、コメント化しないと毎回その時刻に初期化されるので注意してください。

```C
#include <Wire.h>
#define RTC_address 0x68

uint8_t REG_table[7];

void setup() {
  Wire.begin();
  Serial.begin(115200);

  Serial.println("start");

  /*時刻更新時はコメント解除
    Wire.beginTransmission(RTC_address);
    Wire.write(0x00);//Register 先頭アドレス
    Wire.write(0x00);//second
    Wire.write(0x36);//minute
    Wire.write(0x20);//hour
    Wire.write(0x04);//week
    Wire.write(0x24);//day
    Wire.write(0x12);//month
    Wire.write(0x22);//year
    Wire.endTransmission();
  */
}

void loop() {
  //一つずつ読む場合
  byte sec_d = read_rtc(0x00);
  byte min_d = read_rtc(0x01);
  byte hour_d = read_rtc(0x02);
  byte day_d = read_rtc(0x04);
  byte month_d = read_rtc(0x05);


  int sec = dec_to_int(sec_d);
  int min = dec_to_int(min_d);
  int hour = dec_to_int(hour_d);
  int day = dec_to_int(day_d);
  int month = dec_to_int(month_d);

  Serial.print(sec);
  Serial.print("秒, ");
  Serial.print(min);
  Serial.print("分, ");
  Serial.print(hour);
  Serial.print("時, ");
  Serial.print(day);
  Serial.print("日, ");
  Serial.print(month);
  Serial.print("月");




  //一括で読む場合
  /*
    byte k[20];
    read_rtc_multibyte(k, 0x00, 7);
    for (int i = 0; i < 7; i++) {
    Serial.print(k[i]);
    Serial.print(", ");
    }

    int sec = dec_to_int(k[0]);
    int min = dec_to_int(k[1]);
    int hour = dec_to_int(k[2]);
    int day = dec_to_int(k[4]);
    int month = dec_to_int(k[5]);

    Serial.print(sec);
    Serial.print("秒, ");
    Serial.print(min);
    Serial.print("分, ");
    Serial.print(hour);
    Serial.print("時, ");
    Serial.print(day);
    Serial.print("日, ");
    Serial.print(month);
    Serial.print("月");
  */


  Serial.println("");

  delay(1000);


}

int dec_to_int(byte dec) {
  int data;
  data = (dec >> 4 ) * 10 + (dec & 0x0F);
  return data;
}
void write_rtc(byte add, byte data) {
  Wire.beginTransmission(RTC_address);
  Wire.write(add);
  Wire.write(data);
  Wire.endTransmission();

}
byte read_rtc(byte add) {
  byte k;
  Wire.beginTransmission(RTC_address);
  Wire.write(add);
  Wire.endTransmission();
  Wire.requestFrom(RTC_address, 1);
  while (Wire.available()) {
    k = Wire.read();
  }
  return k;
}


void read_rtc_multibyte(byte *array1, byte add, int num) {
  Wire.beginTransmission(RTC_address);
  Wire.write(add);
  Wire.endTransmission();
  Wire.requestFrom(RTC_address, num);
  int i = 0;
  while (Wire.available()) {
    array1[i] = Wire.read();
    i++;
  }
}

```