| Sketch: Rtc8564AttachInterruptSleep ▼ 
 
 /*
 * sketch name   : Rtc8564AttachInterruptSleep
 * summary       : RTC8564で定周期タイマー割り込み & スリープ
 * releases      : 2011/3/15
 */
#include <Wire.h>
#include <Rtc8564AttachInterrupt.h>
#include <Sleep.h>
/* RTCタイマ開始日付時刻 */
#define RTC_SEC  0x00  // 秒
#define RTC_MIN  0x18  // 分
#define RTC_HOUR 0x23  // 時
#define RTC_DAY  0x15  // 日
#define RTC_WEEK 0x02  // 曜日(00:日 〜 06:土)
#define RTC_MON  0x03  // 月
#define RTC_YEAR 0x11  // 西暦
byte date_time[7] = {
   RTC_SEC
  ,RTC_MIN
  ,RTC_HOUR
  ,RTC_DAY
  ,RTC_WEEK
  ,RTC_MON
  ,RTC_YEAR
};
/* 電源リセット確認フラグ */
boolean init_flg = false;
/* 計測間隔(RTC割り込み間隔) */
#define RTC_INTERRUPT_TERM 10
/* 外部割り込みピン */
#define RTC_INTERRUPT_PIN  2
/* 定周期タイマ間隔設定単位 0:秒/1:分 */
#define RTC_INTERRUPT_MODE 0
void setup() {
  Serial.begin(9600);
  
  // 日付時刻初期化
  Rtc.initDatetime(date_time);
  
  // RTC開始
  Rtc.begin();
  
  // 定周期割り込みタイマ継続確認
  if (!Rtc.isInterrupt()) {
    
    // 割り込み設定
    Rtc.syncInterrupt(RTC_INTERRUPT_MODE, RTC_INTERRUPT_TERM);
  }
  
  // 割り込み設定
  pinMode(RTC_INTERRUPT_PIN, INPUT);
  digitalWrite(RTC_INTERRUPT_PIN, HIGH);
}
void loop() {
  
  // 初期化(電源OFF=>ON)すぐ後は計測しない
  if (init_flg) ReadRTC();
  
  init_flg = true;
  
  // スリープ開始
  SleepClass::powerDownAndWakeupExternalEvent(0);
}
void ReadRTC()
{
  Rtc.available();
  Serial.print(0x2000 + Rtc.years(), HEX);
  Serial.print("/");
  Serial.print(Rtc.months(), HEX);
  Serial.print("/");
  Serial.print(Rtc.days(), HEX);
  Serial.print(" ");
  Serial.print(Rtc.hours(), HEX);
  Serial.print(":");
  Serial.print(Rtc.minutes(), HEX);
  Serial.print(":");
  Serial.print(Rtc.seconds(), HEX);
  Serial.print(" ");
  Serial.println((int)Rtc.weekdays());
  Serial.println();
}
スケッチ実行には、以下の二つのライブラリが必要となる。
 
 
 
 
 < Arduino RTC8564用定周期タイマー割り込みライブラリ >
 なんでも作っちゃう、かも。さんのRTC8564のライブラリを使わせて頂きました。
 ありがとうございます。
 
 RTC8564用ライブラリには定周期タイマー割り込みのメソッドが含まれていなかったので、改造してみた。
 以下は RTC8564ライブラリをもとに僕が追記したRTC8564定周期割り込みタイマーライブラリである。
 
 ■ Rtc8564AttachInterruptライブラリ
 Download: Rtc8564AttachInterrupt.zip
 Library Code:
 Rtc8564AttachInterrupt.h ▼
 
 Rtc8564AttachInterrupt.cpp ▼
 #ifndef Rtc8564AttachInterrupt_h
#define Rtc8564AttachInterrupt_h
#include <inttypes.h>
class Rtc8564AttachInterrupt
{
private:
 void init(void);
 uint8_t _seconds;
 uint8_t _minutes;
 uint8_t _hours;
 uint8_t _days;
 uint8_t _weekdays;
 uint8_t _months;
 uint8_t _years;
 bool _century;
 
public:
 enum {
  BCD = 0,
  Decimal = 1,
 };
 Rtc8564AttachInterrupt();
  void begin(void);
  void beginWithoutIsValid(void);
  void initDatetime(uint8_t date_time[]);
  bool isInitDatetime(void);
  void sync(uint8_t date_time[],uint8_t size = 7);
  void syncInterrupt(unsigned int mode, unsigned long term);
 bool available(void);
  bool isvalid(void);
  bool isInterrupt(void);
 uint8_t seconds(uint8_t format = Rtc8564AttachInterrupt::BCD) const;
 uint8_t minutes(uint8_t format = Rtc8564AttachInterrupt::BCD) const;
 uint8_t hours(uint8_t format   = Rtc8564AttachInterrupt::BCD) const;
 uint8_t days(uint8_t format    = Rtc8564AttachInterrupt::BCD) const;
 uint8_t weekdays() const;
 uint8_t months(uint8_t format  = Rtc8564AttachInterrupt::BCD) const;
 uint8_t years(uint8_t format   = Rtc8564AttachInterrupt::BCD) const;
 bool century() const;
};
extern Rtc8564AttachInterrupt Rtc;
#endif
 
 extern "C" {
  #include <stdlib.h>
  #include <string.h>
  #include <inttypes.h>
}
#include <WConstants.h>
#include <Wire.h>
#include "Rtc8564AttachInterrupt.h"
#define RTC8564_SLAVE_ADRS  (0xA2 >> 1)
#define BCD2Decimal(x)    (((x>>4)*10)+(x&0xf))
// Constructors ////////////////////////////////////////////////////////////////
Rtc8564AttachInterrupt::Rtc8564AttachInterrupt()
  : _seconds(0), _minutes(0), _hours(0), _days(0), _weekdays(0), _months(0), _years(0), _century(0)
{
}
void Rtc8564AttachInterrupt::init(void)
{
  delay(1000);
  Wire.beginTransmission(RTC8564_SLAVE_ADRS);
  Wire.send(0x00);  // write reg addr 00
  Wire.send(0x20);  // 00 Control 1, STOP=1
  Wire.send(0x00);  // 01 Control 2
  Wire.send(0x00);  // 02 Seconds
  Wire.send(0x00);  // 03 Minutes
  Wire.send(0x09);  // 04 Hours
  Wire.send(0x01);  // 05 Days
  Wire.send(0x01);  // 06 Weekdays
  Wire.send(0x01);  // 07 Months
  Wire.send(0x01);  // 08 Years
  Wire.send(0x00);  // 09 Minutes Alarm
  Wire.send(0x00);  // 0A Hours Alarm
  Wire.send(0x00);  // 0B Days Alarm
  Wire.send(0x00);  // 0C Weekdays Alarm
  Wire.send(0x00);  // 0D CLKOUT
  Wire.send(0x00);  // 0E Timer control
  Wire.send(0x00);  // 0F Timer
  Wire.send(0x00);  // 00 Control 1, STOP=0
  Wire.endTransmission();
}
// Public Methods //////////////////////////////////////////////////////////////
void Rtc8564AttachInterrupt::begin(void)
{
  Wire.begin();
  if(isvalid() == false) {
    
    // RTC初期設定
    init();
    
    // 日付時刻プロパティがセットされていたら、その時刻をセット
    if (isInitDatetime()) {
      byte date_time[7];
      date_time[0] = _seconds;
      date_time[1] = _minutes;
      date_time[2] = _hours;
      date_time[3] = _days;
      date_time[4] = _weekdays;
      date_time[5] = _months;
      date_time[6] = _years;
      sync(date_time);
    }
  }
}
// RTC日付時刻継続確認なしの日付時刻初期化
void Rtc8564AttachInterrupt::beginWithoutIsValid(void)
{
  Wire.begin();
  
  // RTC初期設定
  init();
  
  // 日付時刻プロパティがセットされていたら、その時刻をセット
  if (isInitDatetime()) {
    byte date_time[7];
    date_time[0] = _seconds;
    date_time[1] = _minutes;
    date_time[2] = _hours;
    date_time[3] = _days;
    date_time[4] = _weekdays;
    date_time[5] = _months;
    date_time[6] = _years;
    sync(date_time);
  }
}
// 日付時刻のプロパティセット
void Rtc8564AttachInterrupt::initDatetime(uint8_t date_time[])
{
  _seconds  = (date_time[0]) ? date_time[0] : 0x00;
  _minutes  = (date_time[1]) ? date_time[1] : 0x00;
  _hours    = (date_time[2]) ? date_time[2] : 0x09;
  _days     = (date_time[3]) ? date_time[3] : 0x01;
  _weekdays = (date_time[4]) ? date_time[4] : 0x01;
  _months   = (date_time[5]) ? date_time[5] : 0x01;
  _years    = (date_time[6]) ? date_time[6] : 0x01;
}
// 日付時刻プロパティセット確認
bool Rtc8564AttachInterrupt::isInitDatetime(void)
{
  bool flg = false;
  if ((_seconds  & 0x00) != 0x00) flg = true;
  if ((_minutes  & 0x00) != 0x00) flg = true;
  if ((_hours    & 0x09) != 0x09) flg = true;
  if ((_days     & 0x01) != 0x01) flg = true;
  if ((_weekdays & 0x01) != 0x01) flg = true;
  if ((_months   & 0x01) != 0x01) flg = true;
  if ((_years    & 0x01) != 0x01) flg = true;
  return flg;
}
// 日付時刻の初期化
void Rtc8564AttachInterrupt::sync(uint8_t date_time[],uint8_t size)
{
  // 時計機能ストップ
  Wire.beginTransmission(RTC8564_SLAVE_ADRS);
  Wire.send(0x00);  // Control1 アドレス
  Wire.send(0x20);  // 00 Control 1, STOP=1
  Wire.endTransmission();
  
  // 日付時刻設定
  Wire.beginTransmission(RTC8564_SLAVE_ADRS);
  Wire.send(0x02);              // Seconds アドレス
  Wire.send(date_time, size);   // 日付時刻セット
  Wire.endTransmission();
  
  // 時計機能スタート
  Wire.beginTransmission(RTC8564_SLAVE_ADRS);
  Wire.send(0x00);  // Control1 アドレス
  Wire.send(0x00);  // 00 Control 1, STOP=0
  Wire.endTransmission();
}
// 定周期割り込みタイマの初期化
// param
//  mode: 割り込み周期モード選択フラグ / 0: 1秒(1Hz)周期, 1: 1分(60Hz)周期
//  term: 割り込み周期(0〜255)  mode:0 選択時は単位は「秒」、mode:1 選択時は単位は「分」
void Rtc8564AttachInterrupt::syncInterrupt(unsigned int mode, unsigned long term)
{
  // Control2レジスタ(定周期タイマの繰り返し・割り込み時の信号発信設定)
  Wire.beginTransmission(RTC8564_SLAVE_ADRS);
  Wire.send(0x01);  // Control2 address
  Wire.send(0x11);  // TI/TP:1(繰り返し割り込みモード),TIE:1(定周期割り込み時、Lレベルの割り込み信号を発生させる)
  Wire.endTransmission();
  
  // 定周期タイマ設定
  byte buf[2];
  if (mode == 1) {
    buf[0] = 0x83;  // TE:1(タイマON), TD1:TD0/1;1(カウントダウン周期を60Hz/1分に設定)
  } else {
    buf[0] = 0x82;  // TE:1(タイマON), TD1:TD0/1;0(カウントダウン周期を1Hz/1秒に設定)
  }
  buf[1] = term;    // タイマ周期を設定
  Wire.beginTransmission(RTC8564_SLAVE_ADRS);
  Wire.send(0x0E);  // Timer Control address
  Wire.send(buf, 2);
  Wire.endTransmission();
}
bool Rtc8564AttachInterrupt::available(void)
{
  uint8_t buff[7];
  
  Wire.beginTransmission(RTC8564_SLAVE_ADRS);
  Wire.send(0x02);      // write reg addr 02
  Wire.endTransmission();
  
  Wire.requestFrom(RTC8564_SLAVE_ADRS, 7);
  
  for(int i=0; i<7; i++){
    if(Wire.available()){
      buff[i] = Wire.receive();
    }
  }
  
  _seconds  = buff[0] & 0x7f;
  _minutes  = buff[1] & 0x7f;
  _hours    = buff[2] & 0x3f;
  _days     = buff[3] & 0x3f;
  _weekdays = buff[4] & 0x07;
  _months   = buff[5] & 0x1f;
  _years    = buff[6];
  _century  = (buff[5] & 0x80) ? 1 : 0;
  return (buff[0] & 0x80 ? false : true);
}
bool Rtc8564AttachInterrupt::isvalid(void)
{
  Wire.beginTransmission(RTC8564_SLAVE_ADRS);
  Wire.send(0x02);      // write reg addr 02
  Wire.endTransmission();
  Wire.requestFrom(RTC8564_SLAVE_ADRS, 1);
  if(Wire.available()){
    uint8_t buff = Wire.receive();
    return (buff & 0x80 ? false : true);
  }
  return false;
}
// 定周期割り込みタイマの継続確認
bool Rtc8564AttachInterrupt::isInterrupt(void)
{
  Wire.beginTransmission(RTC8564_SLAVE_ADRS);
  Wire.send(0x01);
  Wire.endTransmission();
  Wire.requestFrom(RTC8564_SLAVE_ADRS, 1);
  if(Wire.available()){
    return ((Wire.receive() & 0x04) != 0x04 ? false : true);
  }
  return false;
}
uint8_t Rtc8564AttachInterrupt::seconds(uint8_t format) const {
  if(format == Decimal) return BCD2Decimal(_seconds);
  return _seconds;
}
uint8_t Rtc8564AttachInterrupt::minutes(uint8_t format) const {
  if(format == Decimal) return BCD2Decimal(_minutes);
  return _minutes;
}
uint8_t Rtc8564AttachInterrupt::hours(uint8_t format) const {
  if(format == Decimal) return BCD2Decimal(_hours);
  return _hours;
}
uint8_t Rtc8564AttachInterrupt::days(uint8_t format) const {
  if(format == Decimal) return BCD2Decimal(_days);
  return _days;
}
uint8_t Rtc8564AttachInterrupt::weekdays() const {
  return _weekdays;
}
uint8_t Rtc8564AttachInterrupt::months(uint8_t format) const {
  if(format == Decimal) return BCD2Decimal(_months);
  return _months;
}
uint8_t Rtc8564AttachInterrupt::years(uint8_t format) const {
  if(format == Decimal) return BCD2Decimal(_years);
  return _years;
}
bool Rtc8564AttachInterrupt::century() const {
  return _century;
}
// Preinstantiate Objects //////////////////////////////////////////////////////
Rtc8564AttachInterrupt Rtc = Rtc8564AttachInterrupt();
Rtc8564AttachInterrupt.zip をダウンロード & 解凍し、Arduino/libraries/Rtc8564AttachInterrupt として保存する。
 追加したメソッドは以下。
 
 
     
        
            | メソッド名 | 処理内容 |  
            | beginWithoutIsValid (void) | RTC日付時刻継続確認なしに日付時刻を初期化する。 |  
            | initDatetime (uint8_t date_time[]) | 日付時刻のプロパティをセットする。 |  
            | isInitDatetime (void) | 日付時刻プロパティがセットされているか確認する。 |  
            | syncInterrupt (unsigned int mode, unsigned long term) | 定周期割り込みタイマの設定を初期化する。 |  
            | isInterrupt (void) | 定周期割り込みタイマがセットされているかの確認をする。 |  次回は、RTC8564についてもうちょっと詳しく書いてみる。
 
 
 
 | 
    
0 コメント:
コメントを投稿