RTC(リアルタイムクロック)と接続して読み書きを行って見ます

〔PICの動かせ方入門に戻る〕


 前回の記事でArduinoとPICを接続してI2C通信を行いました、I2Cの概要等はそちらを参考にして下さい。 この頁ではPIC16F1827とRTC(RTC-8564NB)をI2Cで接続してRTC機能を利用して見たいと思います。
このRTC-8564NB利用の記事はすでに沢山の他のHPサイト様が書かれていますが、私なりに書いて見たいと思います。 尚、RTC-8564NBは秋月電子のこちらから購入しています。
 PICでも時刻カウントを行う事は可能ですがが精度が良くなくずれずれです、 なので、外部に時刻カウント専用ICのRTCを取り付けて利用したりします。
RTC-8564NBのマニュアルを見ると月差1分の誤差となっている...時計での利用は今いちか?...
(こちらのモジュールが、月差13秒相当と誤差が少ないのでお勧めかも、入手にて動作記事を書きます)
(こちらのモジュール(RX8900)が、誤差は月差9秒相当なのでお勧めかも、入手にて動作記事を書きます)

もっとぉ高性能なRTCが欲しいと言う人はSPI接続ですがこれ何か如何でしょう?月差約3秒程らしい。
私も含めて、こんなSOパッケージ(1.27mmピッチ)なんか半田付け出来るかぁ〜って人は
スイッチサイエンスのこちら何かは同でしょう、又I2C接続が良いって人はこちら(DS1307)をどうぞ*2)

 RTC-8564NBの機能として周波数出力(32.768kHz, 1024Hz, 32Hz, 1Hz)と 定周期タイマー割込み機能(244.14us〜255min)にアラーム割込み機能(何日何時何分何曜日の指定が出来る)が有ります。
周波数出力はCLKOUT端子から出力され、定周期タイマー・アラーム割込み機能はINT端子から出力されます。 尚、通常はINT端子はHIGHで設定時間になればLOW(GNDに接続される)です。

[16F1827ピンの配置図]

配置図 今回使用するピンは、
電源ピンの14番(VDD)と5番(VSS)、
I2Cピンの10番(RB4:SCL)と7番(RB1:SDA)です。

また、9番(RB3)とRTCの2番(CLKOUT)を
接続(下配線図の白色線)して外部割込み
を利用した実験も行っています。

それとRTCから読み出した時刻表示用として18番(RA1)から、別途作成した自作のLCDモニター
出力しています。

[配線図]

配線図1   配線図2
(Fritzing用のRTC-8564NB部品ダウンロードはこちらからお願いします。)

SDA/SCL ピンについて
SDA(RB1)/SCL(RB4)のピンは必ずデジタル入力に設定を行います。

I2Cのプルアップ抵抗について
I2C伝送路のプルアップ抵抗として、PIC内蔵のプルアップ抵抗を利用したので配線図には在りません。
また、RTC-8564NBモジュールは、上図のJP1とJP2の場所を半田付けすればモジュールに取り付けてある 2.2KΩでプルアップされるのですが今回は利用していません。

LEDについて
今回、定周期タイマー・アラーム割込み機能確認用としてRTCのINT端子に接続しています。
LEDは通常は消えています、定周期タイマー・アラーム割込み機能の設定時刻になると点灯します。
(通常INT端子はHIGHに接続され、設定時刻になるとLOW/GNDに接続されるので+5V電源から電流が流れてきてLEDが点灯します)
また、RTC-8564NBモジュールは、上図のJP3の場所を半田付けすればモジュールに取り付けてある
LEDで確認できるので外付けLEDと抵抗はいらなくなりますが、今回は利用していません。

LEDを外付けする場合はLEDには極性が有ります、
足の長いアノード側をVDD(5V)の方に、足の短いカソード側をINT端子側の方に接続します。
また、LEDには流せる電圧と電流が決まっています、必ず電流制限抵抗を付けましょう。

電流制限抵抗
 LEDの順方向電流(IF)と順方向電圧(VF)がデータシート等に書いてあると思います、
 例えばIFが10mAで、VFが2.5Vで、電源電圧が5Vとすると、
 (電源電圧−順方向電圧)÷ 順方向電流 = 電流制限抵抗値
 よって、(5V - 2.5V) ÷ 0.010A = 250Ω(250Ωは無いので240Ωか270Ωを使います)
 10mAは0.010AというふうにAに変換して計算します。

 だいたい120Ω〜680Ωのあたりだと思います。
 LEDは5mAくらいで使った方が目に優しいでしょう、で470Ω?
 また、抵抗はLEDのアノード側とカソード側のどちら側に接続してもOKです。

《ダウンロードプログラムについて》

サンプルプログラムは"2012/01/10 火曜 15:30:00"から時間設定を行っています、
まずはこの設定で実験を行い動作を確認した後に色々設定を変更して見て下さい。


尚、FOSCのCPUクロック周波数は8MHzでプログラムされています、変更する場合は下記の方に
書いて有る記述を良く読んで下さい。

↓ここからサンプルプログラムソースファイルをダウンロードして下さい。
rtc.lzh *1) *3)

プログラムソースをダウンロードしたら、MPLAB X(v2.15)にてプロジェクトを作成します。
以下のファイルをプロジェクトディレクトリにコピーしてプロジェクトに取込んで下さい。
次にコンパイルPIC書き込みを実行して下さい。 *3)
MPLAB(R) XC8 C Compiler Version 1.32コンパイラを使用しています。

ダウンロードしたら解凍して下さい、以下のファイル構成です。 *3)
 rtc.c ・・・・・・・・・本体のソースプログラム
 skI2Clib.c   ・・・・I2C通信部分の関数を記述したライブラリソースプログラム
 skI2Clib.h   ・・・・ヘッダファイル
 skRTClib.c  ・・・・RTC-8564NB用関数を記述したライブラリソースプログラム
 skRTClib.h  ・・・・ヘッダファイル

このプログラムにはデバッグモニタープログラム「skMonitorLCD.c」「skMonitorLCD.h」が必要です。
デバッグLCDモニターについてはこちらを参照して下さい。
「skMonitorLCD.c」は送信データをTimer2のタイミングで送る様に変更しました、
その為にrtc.cプログラムを変更しています。
 *1)

また、LCDモニターの出力はRA1から行っているので「skMonitorLCD.h」を下記の様に変更します。
#define _XTAL_FREQ 8000000  // 使用するPIC等により動作周波数値を設定する
#define BAUDRATE 51      // 9600bps(8MHz=51)(4MHz=25)(16MHz=103)(20MHz=129)
#define MONITOR_PIN RA1      // モニタ出力するピンの番号を設定する

rtc.c

このプログラムは __delay_ms(1000)1秒毎で自己ループしてそのタイミングでRTCから時刻を読み取って表示を行っています。 また、アラーム機能も起動から1分後に出力する様に設定されています。

モニター表示  起動が成功すると左図の様に1秒毎に表示が更新されます。
 起動から1分後(15:31)にアラーム機能が起動しLEDが点灯します、
 さらに1分後(15:32)にアラーム機能を停止するのでLEDが消灯
 します、表示は継続したままです。


skI2Clib.h

I2C通信の関数ライブラリ用インクルードファイルです。
"skI2Clib.c"を利用する場合に
#include "skI2Clib.h" をプログラムの先頭で記述しないとだめです。

デフォルトではMSSP1を使う様になりますが、PICによってはMSSP2が有ります。
MSSP2側を使う場合は、"#define I2C_MSSP2_USE"を記述して下さい。 *3)

skI2Clib.c

このライブラリはI2Cデバイス(RTC/EEPROM等)と接続を行う為の関数集です。
この関数集は12F1822/16F182x/16F193x/18F25K22系で利用可能です。

I2C通信の関数ライブラリの使い方を説明します。

 InitI2C_Master(speed) *3)
  I2C通信のマスターモードで初期化を行う処理です。
  I2C通信用の速度クロック周波数は100KHz/400KHzでの設定です、
  この速度はFOSC(PICのCPU周波数)8MHzの場合で初期化されています。
  FOSCを変えた場合はこちらを参考にSSP1ADDレジスタを変えて下さい。
   speed  :I2Cの通信速度を指定します。(0=100KHz 1=400KHz)

  尚、このLCDはI2C通信用の速度クロック周波数400KHzにも対応しています。
  又、通信速度を400KHzにしても、実際は250KHz程しか速度は出ません

ans = I2C_Start(adrs,rw)
 スレーブにスタートコンディションを発行する処理です。
  adrs  :スレーブのアドレスを指定します
  rw     :スレーブに対する動作の指定をします
       0 = スレーブに書込みなさい要求  1 = スレーブに送信しなさい要求
  ans   :0 = 正常 1 = 異常(相手からACKが返ってこない)

ans = I2C_rStart(adrs,rw)
 スレーブにリピート・スタートコンディションを発行する処理です。
  adrs  :スレーブのアドレスを指定します
  rw     :スレーブに対する動作の指定をします
       0 = スレーブに書込みなさい要求  1 = スレーブに送信しなさい要求
  ans   :0 = 正常 1 = 異常(相手からACKが返ってこない)

I2C_Stop()
 スレーブにストップコンディションを発行する処理です。

ans = I2C_Send(dt)
 スレーブにデータを1バイト送信する処理です。
  dt     :送信するデータを指定します
  ans   :0 = 正常 1 = 異常(相手からACKが返ってこない又はNOACKを返した)
 例)RTC_ADRSへの2バイト送信
     int ans ;

     ans = I2C_Start(RTC_ADRS,RW_0) ; // スタートコンディションを発行する
     if (ans == 0) {
          I2C_Send(0x00) ;            // レジスターアドレスは00hを指定する
          I2C_Send(0x00);             // Control1(Reg00)の設定
     } else 異常 ;
     I2C_Stop() ;                     // ストップコンディションを発行する
c = I2C_Receive(ack)
 スレーブからデータを1バイト受信する処理です。
  ack    :スレーブからデータを受信した後に返答するデータを指定します
       0 = ACKをスレーブに返す 1 = NOACKをスレーブに返す(受信データが最後なら1)
  c       :受信した1バイトのデータを返す
 例)RTC_ADRSへの1バイト送信の後に2バイト受信する
     char reg1 , reg2 ;
     int  ans ;

     ans = I2C_Start(RTC_ADRS,RW_0) ; // スタートコンディションを発行する
     if (ans == 0) {
          I2C_Send(0x01) ;            // レジスターアドレスは01hを指定する
          I2C_rStart(RTC_ADRS,RW_1) ; // リピート・スタートコンディションを発行する
          reg1 = I2C_Receive(ACK) ;   // Reg 01H を受信する
          reg2 = I2C_Receive(NOACK) ; // Reg 02H を受信する
     } else 異常 ;
     I2C_Stop() ;                     // ストップコンディションを発行する
InterI2C()
 I2C関連の割り込み処理です。
 今回は割込み発生したらフラグをクリアしているだけです。
 メインプログラム(例"rtc.c")の割込み処理で必ず呼びます。
 例)
     void interrupt InterFunction( void )
     {
          // I2C関連の割り込み処理
          InterI2C() ;
     }
skRTClib.h

RTC-8564NB(リアルタイムクロック)関数ライブラリ用インクルードファイル
"skRTClib.c"を利用する場合に
#include "skRTClib.h" をプログラムの先頭で記述しないとだめです。

また、FOSCのCPUクロック周波数を変更した場合は下記行を変更して下さい。
#define _XTAL_FREQ 8000000 // delay用に必要(クロック8MHzを指定)

skRTClib.c

このライブラリはRTC-8564NBとI2C接続でデータのやり取りを行う為の関数集です。
ですので、この関数集にはskI2Clib.c/skI2Clib.hのファイルが必要です。

この関数集を利用する場合は、"skI2Clib.c"の"InitI2C_Master( )"関数を呼び出した後使います、
使い方の例は、"rtc.c"を参照下さい。 *3)

このライブラリも他のPICでF1シリーズは使用出来ると思いますがぁ....
ダメな場合はたぶん、割り込み処理用のレジスタ名(IOCBF/IOCBP)を変更すればOKと思います。
(関数のRTC_InitとInterRTCにIOCBF/IOCBPの記述が有ります。)

PIC12F1822の場合は、レジスタ名(IOCAF/IOCAP)に変更したら利用出来ました。
ただ、時刻の表示をするだけでプログラム容量が84.5%でした、 アラーム機能使用でのコンパイルで95%今回の実験程度では何とかOKでしょうが、 他の仕事をさせる為にプログラムを追加すると厳しいかもですね。

RTC-8564NB(リアルタイムクロック)関数ライブラリの使い方を説明します。

ans = RTC_Init(Inter,Year,Mon,mDay,wDay,Hour,Min,Sec)
 RTCを利用する為の初期化を行う処理です。
  Inter :RTCからのクロック出力による外部割込み処理を行うのかを指定します
      0:割込みは無し利用しない 1-8:割込みを行う
      1:RB0 2:RB1 3:RB2 4:RB3 5:RB4 6:RB5 7:RB6 8:RB7
      クロック出力(CLKOUT)は1Hzで初期化しているのでRTCは常に出力状態です。
      その信号をPICのRB0-RB7ピンで受けて割込み処理を行う場合に使用します。
      (割込みに使用するピンはデジタル入力にします、忘れないようにね!)
      下記記載の"CLKOUT割込みの利用方法"を参照下さい。
  Year :日付の年(0-99)を指定します(西暦の下2ケタ 2000年-2099年)
    Mon  :日付の月(1-12)を指定します
    mDay:日付の日(1-31)を指定します(在りえない日を指定したら動作が不定らしい)
    wDay:曜日の指定をします 0:日 1:月 2:火 3:水 4:木 5:金 6:土
  Hour :時刻の時(0-23)を指定します
    Min   :時刻の分(0-59)を指定します
    Sec  :時刻の秒(0-59)を指定します
  ans   :0 = 正常 1 = 異常(RTCからACKが返ってこない)
 例1)外部割込みなしで"2012/01/15 火曜 15:30:00"で初期化するなら
       int ans ;

       ans = RTC_Init(0,12,1,10,2,15,30,0) ;
       if (ans == 0) 初期化成功
       else          初期化失敗

 例2)外部割込みをRB3で受けて"2012/01/15 火曜 15:30:00"で初期化するなら
       RTC_Init(4,12,1,10,2,15,30,0) ;
 定周期タイマー・アラーム割込み機能は禁止の無しで初期化されます。
 クロック出力(CLKOUT)は1Hz(1秒間に1回ON/OFF)で初期化しています。
   1Hz以外に変更したければRTCレジスタアドレス0Dhの初期化を書き換えて下さい。
   1Hz=0x83 32Hz=0x82 1024Hz=0x81 32.768KHz=0x80 の4パターンです。
 電池などでRTCがバックアップ状態時はすでに初期起動時に初期化は行われています、その
   状態でこの初期化処理が再度実行(PIC再起動等)された場合は、初期化処理は行いません。

ans = RTC_sTime(Year,Mon,mDay,wDay,Hour,Min,Sec)
 RTCに日付と時刻を書き込む処理です。
 時刻がずれた等の時に再度時刻を設定する場合に利用しましょう。
  Year :日付の年(0-99)を指定します(西暦の下2ケタ 2000年-2099年)
    Mon  :日付の月(1-12)を指定します
    mDay:日付の日(1-31)を指定します(在りえない日を指定したら動作が不定らしい)
    wDay:曜日の指定をします 0:日 1:月 2:火 3:水 4:木 5:金 6:土
  Hour :時刻の時(0-23)を指定します
    Min   :時刻の分(0-59)を指定します
    Sec  :時刻の秒(0-59)を指定します
  ans   :0 = 正常 1 = 異常(RTCからACKが返ってこない)

ans = RTC_rTime(*tm)
 RTCから現在の日付と時刻を読み取る処理です。
  *tm  :読み取ったデータを保存する配列変数を指定します(配列は7バイト必要です)
      配列にはBCDデータで秒・分・時・日・曜日・月・年の順で保存されます
  ans   :0 = 正常 1 = 異常(RTCからACKが返ってこない)
 例)LCDモニターに表示する例です。
     byte tm[7] ; 
     int  ans ;

     ans = RTC_rTime(tm) ;
     if (ans == 0) {
          for (int i=0 ; i < 7 ; i++) {
               MonitorPuth(tm[i]) ;
               MonitorPutc(' ') ;
          }
     } else MonitorPuts("RTC Read Error") ;
RTC_cTime(*tm,*c)
 RTCの日付と時刻を文字列に変換する処理です。
 RTC_rTimeはBCD値で返しますが、その値を文字列に変換します。
  *tm  :RTC_rTimeから読み込んだ配列変数を指定します
  *c    :文字列に変換したデータ(24バイト)を格納する配列変数を指定します
      変換データのフォーマットは、"yyyy/mm/dd www hh:mm:ss" (2010/01/15 TUE 15:30:00)
      で返します
 例)LCDモニターに表示する例です。
     byte tm[7] ; 
     char buf[24] ;

     RTC_rTime(tm) ;
     RTC_cTime(tm,buf) ;
     MonitorPuts(buf) ;
RTC_SetTimer(sclk,count)
 定周期タイマーの設定をする処理です。(タイマーの開始)
  sclk   :ソースクロックの指定です 0:244.14us 1:15.625ms 2:1sec 3:1min
  count:カウントダウン値の指定(1-255)
     ソースクロックのタイミングでcountの値がカウントダウンし、0でINT端子がON(LOW)します
     すなわち、sclk=2 count=10 なら10秒周期でINTがONします。
     又、INT端子がONしている時間は 244us(sclk=0時)か15.625ms(sclk=1-3時)でOFFします。
 例)10秒周期設定の場合
     RTC.SetTimer(2,10) ; // これを実行した後定周期タイマーの開始です
 定周期タイマー機能の動作として、設定の定周期でONとOFFを繰り返すモードと、
   ONが1回限りで終了するモードの2種類がありますが、このライブラリでは繰り返すモードのみ
   対応です。

RTC_StopTimer()
 定周期タイマー機能を無効にする処理です。(タイマーの終了)
 この処理を発行しない限り、定周期タイマー出力は永遠に繰り返しています。

RTC_SetAlarm(Hour,Min,mDay,wDay)
 アラームの日時を設定する処理です。(アラームの開始)
 設定した時刻になるとINT端子がONします、RTC_offAlarm()関数を発行しない限りONしたままです。
  Hour :時刻の時(0-23)を指定します、0xff指定でHour設定は無効となります
    Min   :時刻の分(0-59)を指定します、0xff指定でMin設定は無効となります
    mDay:日付の日(1-31)を指定します、0xff指定でmDay設定は無効となります
    wDay:曜日の指定をします 0:日 1:月 2:火 3:水 4:木 5:金 6:土 0xff指定でwDay設定無効
 例)
     RTC_SetAlarm(30,0xff,0xff,0xff) ;  // 30分の1時間毎に起動
     RTC_SetAlarm(0,12,0xff,0xff) ;     // 毎日12時に起動
     RTC_SetAlarm(0,12,1,0xff) ;        // 毎月の1日の12時に起動
     RTC_SetAlarm(0,12,0xff,1) ;        // 毎週月曜日の12時に起動
RTC_StopAlarm()
 アラーム機能を無効にする処理です。(アラーム終了)
 アラーム設定は無効になり、INT端子の出力はOFFします。

RTC_offAlarm()
 アラームの発生を解除する処理です。
 INT端子の出力のみOFFします、設定は有効なので次の時刻になるとINT端子の出力はONします。

※定周期タイマー機能とアラーム機能は同じINT端子を兼用しているので、両方設定していると
 出力がかさなります、どちらでONしたかを知るにはRTCレジスタアドレス01h(Control2)の
 AF/TFフラグを読み出さないと判断付きません、このライブラリでは行っていません。


ans = InterRTC()
 RTC関連の割り込み処理です。
 RTC_Init()関数の"Inter"で指定したピンに割り込みが発生したか調べます。
  ans : 割込みの状態を返します 0 = 割込みは発生していない 1 = 発生した
 メインプログラム(例"rtc.c")の割込み処理で呼びます。
 もちろん、RTCからの外部割込みを利用しなければ呼び出さなくてもOKです。
 例)
     void interrupt InterFunction( void )
     {
          // RTC関連の割り込み処理(割込み使用しないならこの記述はいらないでしょう)
          if (InterRTC()==1) {
               //////////////////////////////////////////////////
               //// ここで割込みが発生したので何か処理を行う ////
               //////////////////////////////////////////////////
               IOCIF = 0 ;// InterRTC()関数内ではフラグのクリアをしていないのでここでクリアする
          }
     }
RTC以外で外部割込みを利用する場合の注意点など

RTC以外からでも、他の機器から外部割込みを処理したい場合(例えばスリープ状態からの復帰等)が有ると思います、
なので、"skRTClib.c"ではIOCIFフラグをクリアしていません。
IOCIFフラグは外部割込みが発生すると1になります、だから通常はどのピンから発生したか調べ 該当する割込み処理を行った後にIOCIFフラグを0クリアします。
RTCと他の外部割込みが有る場合のサンプル例として下記を参考にして下さい。
 例)
     void interrupt InterFunction( void )
     {
          int  IOCIFcnt = 0 ;

          // RTC関連の割り込み処理
          if (InterRTC()==1) {
               ////////////////////////////////////////////////////////////
               //// ここで割込みが発生したので何かRTC関連処理を行う ////
               ////////////////////////////////////////////////////////////
               IOCIFcnt++ ;
          }
          // 他の機器からの割り込み処理
          if (IOCIF == 1) {
               if (他の機器と接続した該当ピンが1かIOCBFを調べる) {
                    //////////////////////////////////////////////////////////////
                    //// ここで割込みが発生したので何か他の機器関連処理を行う ////
                    //////////////////////////////////////////////////////////////
                    IOCBFの該当ピンフラグをクリアする
                    IOCIFcnt++ ;
               }
          }
          // ここでピンの状態変化割り込みフラグをクリアする
          if (IOCIFcnt > 0) IOCIF = 0 ;
     }
CLKOUT割込みの利用方法

本ライブラリでクロック出力(CLKOUT)をPICに接続して外部割込みとして利用する方法を説明しておきます。
"rtc.c"の様に1秒の自己ループで表示を行っていると、表示が1秒飛んで表示される場合が有ります、 なので、どうしても1秒キッチリに表示又は処理をさせたい場合は、 RTCから1秒周期で外部割込みを入れて処理する事になります。

RTCの2番ピン(CLKOUT)とPICのデジタル9番(RB3)ピンを接続した場合(上記載配線図の白色線です)
 RTC_Init(4,12,1,10,2,15,30,0) ; // 赤数字の場所を4にします
利用しない場合は赤数字は0です、もちろん配線もしなくてOK。
尚、割り込み入力するピンはデジタル入力に設定しますよ、念の為。

後は、初期化設定(RTC_Init)で1秒周期(1Hz)でCLKOUTから出力する様に設定されているので、
メインプログラムで上記の様な割込み処理を記述すればOKです。
下記にサンプルプログラム(PIC16F1827)を記載します。
--------------------------------------------------------------------- *3)
#include <xc.h>
#include "skI2Clib.h"
#include "skRTClib.h"
#include "skMonitorLCD.h"     // LCDモニター用

#define _XTAL_FREQ 8000000    // delay用に必要(クロック8MHzを指定)

// コンフィギュレーション1の設定
#pragma config FOSC = INTOSC    // 内部クロックを使用する(INTOSC)
#pragma config WDTE = OFF       // ウオッチドッグタイマー無し(OFF)
#pragma config PWRTE = ON       // 電源ONから64ms後にプログラムを開始する(ON)
#pragma config MCLRE = OFF      // 外部リセット信号は使用せずにデジタル入力(RA5)ピンとする(OFF)
#pragma config CP = OFF         // プログラムメモリーを保護しない(OFF)
#pragma config CPD = OFF        // データメモリーを保護しない(OFF)
#pragma config BOREN = ON       // 電源電圧降下常時監視機能ON(ON)
#pragma config CLKOUTEN = OFF   // CLKOUTピンをRA6ピンで使用する(OFF)
#pragma config IESO = OFF       // 外部・内部クロックの切替えでの起動はなし(OFF)
#pragma config FCMEN = OFF      // 外部クロック監視しない(FCMEN_OFF)

// コンフィギュレーション2の設定
#pragma config WRT = OFF        // Flashメモリーを保護しない(OFF)
#pragma config PLLEN = OFF      // 動作クロックを32MHzでは動作させない(OFF)
#pragma config STVREN = ON      // スタックがオーバフローやアンダーフローしたらリセットをする(ON)
#pragma config BORV = HI        // 電源電圧降下常時監視電圧(2.5V)設定(HI)
#pragma config LVP = OFF        // 低電圧プログラミング機能使用しない(OFF)

// 割り込み関数
void interrupt InterFunction( void )
{
     char tm[7] ; 
     char buf[24] ;
	int  IOCIFcnt = 0 ;

     // I2C関連の割り込み処理
     InterI2C() ;
     // RTC関連の割り込み処理
     if (InterRTC()==1) {
          // RTCから現在の日付と時刻を読込む
          RTC_rTime(tm) ;
          RTC_cTime(tm,buf) ;      // 日付と時刻を文字列に変換する
          // LCDモニターに表示を行う
          buf[14] = 0x00 ;
          MonitorPutc(0x02) ;
          MonitorPuts(&buf[0]) ;   // 1行目に表示
          MonitorPutc(0x15) ;
          MonitorPuts(&buf[15]) ;  // 2行目に表示
          IOCIFcnt++ ;
     }
     // ここでピンの状態変化割り込みフラグをクリアする
     if (IOCIFcnt > 0) IOCIF = 0 ;
}
// メインの処理関数
void main()
{
     OSCCON     = 0b01110010 ; // 内部クロックは8MHzとする
     OPTION_REG = 0b00000000 ; // デジタルI/Oに内部プルアップ抵抗を使用する
     ANSELA     = 0b00000000 ; // AN0-AN4は使用しない全てデジタルI/Oとする
     ANSELB     = 0b00000000 ; // AN5-AN11は使用しない全てデジタルI/Oとする
     TRISA      = 0b00000000 ; // ピン(RA)は全て出力に割当てる(RA5は入力のみとなる)
     TRISB      = 0b00011010 ; // ピン(RB)はRB4(SCL1)/RB1(SDA1)/RB3(割込み)のみ入力
     WPUB       = 0b00010010 ; // RB1/4は内部プルアップ抵抗を指定する
     PORTA      = 0b00000000 ; // RA出力ピンの初期化(全てLOWにする)
     PORTB      = 0b00000000 ; // RB出力ピンの初期化(全てLOWにする)

     // I2C通信のマスターモードでSSP1を初期化する、通信速度は100KHz
     InitI2C_Master(0) ;
     // LCDモニターに送信出来る様に初期化する
     MonitorInit() ;

     RTC_Init(4,12,1,10,2,15,30,0) ; // 2012/01/10 火 15:30:00 でRTCを初期化する

     while(1) {
     }
}
---------------------------------------------------------------------
定周期タイマーの利用方法

定周期タイマーを実験する場合は"rtc.c"のサンプルプログラムを下記の様に書き換えて下さい。
     RTC_SetAlarm(15,31,0xff,0xff) ;// アラームを1分後に設定する
     //RTC_SetTimer(2,10) ;          // 定周期タイマーを10秒間隔で設定する

               RTC_StopAlarm() ;   // アラーム機能終了し無効にする
               //RTC_StopTimer() ;   // タイマー機能終了し無効にする

 と上の様に記述されている場所が有ります、この4行を

     //RTC_SetAlarm(15,31,0xff,0xff) ;// アラームを1分後に設定する
     RTC_SetTimer(2,10) ;          // 定周期タイマーを10秒間隔で設定する

               //RTC_StopAlarm() ;   // アラーム機能終了し無効にする
               RTC_StopTimer() ;   // タイマー機能終了し無効にする

の様に書き換えます。
そしてこれを実行すると10秒に1回LEDが点灯(点滅)します、 それから2分後(15:32)になるとLEDは点灯しなくなります。

《バッテリバックアップについて》

実験風景
バッテリバックアップの実験風景です。

配線図3
バッテリバックアップ電源部分のみの実体配線図

配線図4
上の実体配線図からFritzingで出力した回路図
それにしても、Fritzingの自動配線機能この位は真っ直ぐ線を引けよ!、お願い。
(Fritzing用のRTC-8564NB部品ダウンロードはこちらからお願いします。)

RTC-8654NBの仕様を見てみると、電源電圧は1.8V〜5.5Vで、計時(保持)電圧は1.0V〜5.5Vとなっています、 って事はバックアップ電圧に1.0V以上は必要って事よね、 電池からダイオード1N4007を通過した電圧は測った所2.8VなのでOKでしょう。
通常はRTCにはメインからの電源4.8Vが流れています、電池側は2.8Vで低いので流れません、 でぇ、メイン電源が切れると0Vになり2.8V側が高くなるのでぇ流れてバックアップします。

最初に起動した時は、RTC_Init()関数で初期時間がRTCに書き込まれます、
でぇ、メイン電源を切り、しばらくしてメイン電源を入れるとPICが起動しますが、 この時はRTC_Init()関数では初期時間等の設定処理を行わないので、前回の続きからの時刻を表示します。


・ EEPROM(24LC256)と接続した記事はこちらを参照下さい。
・ RTC-8564NBとArduinoを接続した記事はこちらを参照下さい。
・ PICで"32.768KHzの水晶振動子を使ってRTCを行ってみます"の記事はこちらを参照下さい。



MPLAB X用に記事変更(*3) 2015/10/07
追記(*2) 2014/12/27
"skMonitorLCD.c"変更により"rtc.c"のプログラム変更(*1) 2014/02/02


【きむ茶工房ガレージハウス】
Copyright (C) 2006-2020 Shigehiro Kimura All Rights Reserved.