目次

ArduinoMega2560RTC処理

 ArduinoMega2560はピン数が多いので、Real Time Clockを
 2種接続してみることにします。

 ビニルハウスの温湿度計測で利用したRTCは、以下。



 バックアップ電池を使って、マイコンが電源消失でも
 動き続けるRTCは、以下。



 電池でバックアップするので、CR2032を使うとして
 回路図は、次のように配線。



 どちらもIICバスを利用するので、ArduinoMega2560には
 使うたびに、交換するとします。

 IICバスのピンは、次のように20、21を使います。

    D20  SDA <IIC bus>
    D21  SCL <IIC bus>

 IICバスを利用するため、ライブラリをインクルードするのと
 setupの中で開始を宣言しておきます。

#include <Wire.h>

  Wire.begin();

 電池でのバックアップをしない方のRTCでは
 初期化をしておきます。

#define RTC_ADRS  0x32

byte xdatx[6];

void initRtc()
{
  /* start condition */
  Wire.beginTransmission(RTC_ADRS);
  Wire.write(0xE0);
  Wire.write(0x20); /* 24hour Mode */
  Wire.write(0x00); /* PON Clear */
  /* stop condition */
  Wire.endTransmission();
  /* wait */
  delay(1);
  /* initialize */
  *(xdatx+0) = 0x19 ;
  *(xdatx+1) = 0x06 ;
  *(xdatx+2) = 0x01 ;
  *(xdatx+3) = 0x00 ;
  *(xdatx+4) = 0x00 ;
  *(xdatx+5) = 0x00 ;
  /* store */
  putDateTime();
}

 初期化では、2019年06月01日00時00分00秒に指定。
 また、RTCの方にパラメータを格納する関数を用意
 しておきます。

void putDateTime()
{
  Wire.beginTransmission(RTC_ADRS);
  Wire.write(0x00); /* start register addess */
  Wire.write( *(xdatx+5) );
  Wire.write( *(xdatx+4) );
  Wire.write( *(xdatx+3) );
  Wire.write(0x00); /* Sunday */
  Wire.write( *(xdatx+2) );
  Wire.write( *(xdatx+1) );
  Wire.write( *(xdatx+0) );
  Wire.endTransmission();
  /* wait */
  delay(1);
}

 RTCは、BCDフォーマットで扱うので、EEPROMへの格納や
 LCDでの表示のための関数も定義しておきます。

void setDateTime()
{
  byte ptr ;
  byte ii ;
  byte xdt[6] ;
  byte xtmp ;
  word yadr ;
  /* set base pointer */
  ptr = 1 ;
  /* generate BCD code */
  for ( ii = 0 ; ii < 6 ; ii++ ) {
    /* x10 */
    xtmp = getHex( *(sbuf+ptr) ) ;
    xtmp *= 10 ;
    ptr++ ;
    /* x1 */
    xtmp += getHex( *(sbuf+ptr) );
    *(xdt+ii) = convHEX2BCD( xtmp );
    ptr++ ;
    /* copy */
    *(xdatx+ii) = *(xdt+ii) ;
  }
  /* store RTC */
  putDateTime() ;
  /* store EEPROM */
  yadr = SYS_ADRS ;
  for ( ii = 0 ; ii < 6 ; ii++ ) {
    put_eeprom(yadr,*(xdatx+ii));
    yadr++ ;
  }
  /* set ROM entry addess */
  rom_address = 0 ;
}

 RTCにパラメータを出し入れするために
 インタプリタを用意しておけばよく、次
 のように処理します。

    /* adjust real time clock */
    if ( cmd == 'A' ) { setDateTime(); }
    /* show Months Days hour minute */
    if ( cmd == 'a' ) { showRtc(); }

 関数showRtcの内容は、以下。

void showRtc()
{
  byte ii ;
  byte tmp ;
  byte tmpH ;
  byte tmpL ;
  /* show */
  for ( ii = 0 ; ii < 6 ; ii++ ) {
    tmp = *(xdatx+ii) ;
    tmpL = (tmp & 15 ) + '0' ;
    tmp >>= 4 ;
    tmpH = tmp + '0' ;
    rs_putchar( tmpH );
    rs_putchar( tmpL );
    if ( ii < 2  ) { rs_putchar('-'); }
    if ( ii == 2 ) { rs_putchar(' '); }
    if ( ii == 3 ) { rs_putchar(':'); }
    if ( ii == 4 ) { rs_putchar(':'); }
  }
  crlf();
}

 ここまでの関数は、データシートから必要な内容を
 読み込んで定義しています。

 レジスタに関係するデータシートの内容は、以下。



 レジスタから複数パラメータをリードするには
 次のような便利な読み出し方法があります。



 レジスタへの書き込みは、次のシーケンスを利用。



 電池でバックアップできる方のRTCのレジスタ構成は以下。



 レジスタは、数値をBCDで表現しているのがわかります。

 レジスタとしては、0から6までの7レジスタですが
 時間は、12時間制と24時間制の2種あるので選択
 して使わなければなりません。

 レジスタ7には、SQW/OUTから出力する矩形波の周波数を
 指定するのと、矩形波にするのか固定値とするかを指定
 可能となっています。

 パラメータ設定のシーケンスは、以下。



 西暦年の下2桁、月日、曜日、時分秒が含まれて
 いるとすれば、設定関数は、次のように定義。

#define RTC_ADRSX 0x68

byte get_BCD(byte x)
{
  byte result ;
  byte dh ;
  byte dl ;
  /* separate */
  dl = x % 10 ;
  dh = x / 10 ;
  /* concatenate */
  result = (dh << 4) | dl ;

  return result ;
}

void putDateTime(byte *ptr)
{
  /* store */
  Wire.beginTransmission(RTC_ADRSX);
  Wire.write(0x00); /* start register addess */
  Wire.write( get_BCD( *(ptr+6) ) ); /* second  */
  Wire.write( get_BCD( *(ptr+5) ) ); /* minute  */
  Wire.write( get_BCD( *(ptr+4) ) ); /* hour    */
  Wire.write( *(ptr+3) ) )         ; /* weekday */
  Wire.write( get_BCD( *(ptr+2) ) ); /* date    */
  Wire.write( get_BCD( *(ptr+1) ) ); /* month   */
  Wire.write( get_BCD( *(ptr+0) ) ); /* year    */
  Wire.endTransmission();
}

 データリードは、次のシーケンスとなっています。



 レジスタアドレスを指定することなく、年月日曜日時分秒を読み出せる
 モードを持っているため、専用関数を定義します。

byte get_BHEX(byte x)
{
  byte result ;
  /* separate */
  result = (x >> 4) ;
  result *= 10 ;
  result += (x & 15) ;

  return result ;
}

void getDateTime(byte *ptr)
{
  byte xdd[7] ;
  byte ii ;
  /* read */
  Wire.requestFrom(RTC_ADRSX,7);
  *(xdd+6) = Wire.read(); /* ss */
  *(xdd+5) = Wire.read(); /* mm */
  *(xdd+4) = Wire.read(); /* hh */
  *(xdd+3) = Wire.read(); /* weekday */
  *(xdd+2) = Wire.read(); /* DD */
  *(xdd+1) = Wire.read(); /* MM */
  *(xdd+0) = Wire.read(); /* YY */
  /* store */
  for ( ii = 0 ; ii < 7 ; ii++ ) {
    *(ptr+ii) = get_BHEX( *(xdd+ii) );
    if ( ii == 3 ) { *(ptr+ii) = *(xdd+ii) ; }
  }
}

 最後に、1Hzの矩形波を出力するか否かを指定
 する処理を扱う専用関数を定義していきます。

 データシートの関連情報は、以下。



 矩形波を出力するか否かの指定は、SQWEビットに
 論理値を設定すればよいので、そのビットを設定
 するように、関数を定義。

void setSQR(boolean x)
{
  byte xx ;
  /* SQWE bit */
  xx = 0 ;
  if ( x ) { xx |= (1 << 4) ; }
  /* store */
  Wire.beginTransmission(RTC_ADRSX);
  Wire.write(0x07); /* set control register */
  Wire.write( xx ); /* second  */
  Wire.endTransmission();
}

 1Hzの矩形波を出力する場合、セレクタには00を
 指定するので、SQREビットのみを'1'か'0'へと
 設定するだけで済みます。


目次

inserted by FC2 system