RTCC機能を動作させて見ます

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


PICでリアルタイムクロック(日付時刻管理)を実現させるには

リアルタイムクロックIC(RX-8025NB/DS3234S等)をマイコンに接続して日付時刻を読み出す方法。
 RTC-8564NBを使ったモジュールでの記事はこちらを参照下さい。

・PICのセカンダリクロック端子に水晶振動子(32.768KHz)を取付、タイマー1の入力に入れて1秒毎に
 カウントさせる方法、この方法での記事はこちらを参照下さい。
 尚、この方法は、ソフトで日付時刻管理を行う必要が有ります。

・PICに内蔵しているRTCCモジュールを利用する方法で、今回のここの記事となります。
 PICの一部のデバイス(18F2[4]xJ11/18F2[4]xJ50 等)にはRTCC機能を内蔵している物が有ります。
 ここの記事では、18F26J50を使いましたが、18F25J11/25J50/26J50辺りが秋月通商で手に入ります

《RTCC機能概要》

RTCC機能の動作には、内部発振器のINTRC(31KHz)か、外部水晶振動子(32.768KHz)をT1OSO/
T1OSIの端子に取付て、この何れかの発振器から0.5S毎のカウントを発生させ、日付時刻管理
レジスターに積算して行きます。

2000年1月1日の夜12時00分00秒からのカウントで2099年12月31日の夜11時59分59秒まです。
(だがxx年の2桁なので、超えたら20+1xx年とすればぁ、ず〜っと使えるね!、がんばぁPIC)

閏年の検出は有りで、上手くキャリブレーションが行えれば月差3秒らしぃ?、え、うっそぉ!
設定した時刻にアラームを出力する事が可能で、割込みか、RTCCピンに出力出来ます。
又、RTCCピンには1秒毎のクロックかRTCCソースクロック(32.768KHz)を出力可能です。

SLEEP時にもRTCCモジュールを動作させる事は可能です、その辺の話は又そのうちにでも....

RTCC VALUE REGISTER

RTCCの日付時刻データレジスターに読み書きを行う場合は、ウインドウレジスター(RTCVAL)を介して
アクセスを行います、ウインドウレジスターには"RTCPTR"で指定されるデータレジスターのアドレスの
場所2バイト分が見えています。
ウインドウレジスター(RTCVAL)からデータを読み書きすれば、"RTCPTR"のアドレスは自動的に
−1されますが、アクセスはRTCVALL→RTCVALHの順番に行わないとダメです。

RTCCデータの読書き図
日付時刻のデータはBCDで格納されています。
曜日のデータは、日曜(0)で月曜(1)・・・・土曜(6)となりますよ。
時刻のデータは24時間制(00-23時)で格納。

読み出す場合の注意点
例えば、"秒"データが[59秒]だったら次に[1分][00秒]に桁上りが発生しますね、
この桁上りの最中にデータを読み出す可能性が有ります、読み出したデータが変になるでしょう。
これを避ける為に、"RTCSYNC"ビットを見て"1"の場合は”桁上りデータ更新中”です、
なので"0"になるまで待つ事をする必要が有るらしい。

書き込む場合の注意点
書き込む場合は、日付時刻データレジスターはLOCKされています、なので書込む場合は解除しないと
ダメです。
     EECON2  = 0x55 ;
     EECON2  = 0xAA ;
     RTCWREN = 1 ;       // 書き込みを許可する
の解除シーケンスを実行すればいいらしい。(但し、RTCWREN=1 にしたままで置く事!)

ALARM VALUE REGISTER

アラーム時刻データレジスターの読み書きも上記と同様ですが、読み書きする場合の注意点は
必要ないです、たぶん。

アラームデータの読書き図

アラーム時刻データレジスターでアラームイベントを発報する為の日付時刻データを設定しますが、
日付時刻データの、どのデータ範囲までを使うか指定を"ALRMCFG"レジスターの"AMASK"ビットに
設定します。 例えば、毎日12:00:00にアラームイベントを発生させるには以下の様に記述します。
AMASK = 0b0110 ;        // Every day (RTCC_ALM_DAY)
時=12 ; 分=0 ; 秒=0 ;
月=0  ; 日=0 ; 曜日=0 ; // このデータは利用されない
CHIME = 1 ;             // 無限に繰り返す
ALRMEN= 1 ;             // アラーム開始
と、こんな感じです。

アラーム出力の概要

ALRMENビットONでアラームカウント開始です、OFFにすればアラーム出力中でも終了させられます。
又、アラーム出力が指定した回数(ALRMRPT)分終了すれば、ALRMENビットはOFFします。
"ALRMRPT"を3回と指定した場合は、イベントが発生すれば−1され0になるまで繰り返します。
ですが、出力ピンは下図の様にイベント毎にON/OFFする所に注意して下さい。
"CHIME"ビットが"1"の場合は、"ALRMRPT"に回数を指定しても、永久に壊れるまで繰り返します。

アラーム発生の概念図
アラーム発報回数(ALRMRPT)を3回とした場合の概念図です。
アラーム出力は"RTCOE"ビットが"1"でないとピンには出力されない

なのでぇ、アラームのイベント設定は1個のみです、アラームが終了すれば次々に設定は可能でしょう。

《RTCCのレジスター》

RTCCFGのレジスタ

ビッ ト
機能 RTCEN - RTCWREN RTCSYNC HALFSEC RTCOE RTCPTR

Bit 7   :RTCEN       RTCCモジュールの動作を許可するビット
              1=RTCCを有効にする
              0=RTCCを無効にする

Bit 5   :RTCWREN  RTCCの日付時刻データレジスター書き込み許可フラグ
              1=書き込みを許可する(1にするには解除シーケンスを実行)
              0=書き込み不可

Bit 4   :RTCSYNC     日付時刻データレジスタ読み出し同期ビット
              1=今データの更新中なのでまってね
              0=読み出してもだいじょうぶ

Bit 3   :HALFSEC     1秒における0.5secカウントは1秒の内前半か後半の何方かを知るビット
              1=後半(500-999ms)
              0=前半(0-499ms)

Bit 2   :RTCOE         RTCCの出力を外部ピンに出力するのかを選択するビット
              1=出力を行う
              0=出力をしない

Bit 1-0:RTCPTR       RTCCの日付時刻データレジスターのアドレスポインタを設定するビット

PADCFG1のレジスタ

ビッ ト
機能 - - - - - RTSECSEL PMPTTL

Bit 2-1:RTSECSEL   RTCCピンから出力させる信号の種類を選択するビット
              0=アラームをピンから出力する
              1=1秒毎のクロックを出力する
              2=RTCCソースクロック(INTRC/T1OSC)を出力する

Bit 0   :PMPTTL    PMP Moduleの関連ビット(説明を省く)

RTCCALのレジスタ

RTCCのキャリブレーション値を設定するレジスターで、-512〜0〜508が設定可能。
1分間辺りに何クロック増減させるか設定するらしい。

ALRMCFGのレジスタ

ビッ ト
機能 ALRMEN CHIME AMASK ALRMPTR

Bit 7    :ALRMEN     アラームの動作を許可するビット
               1=アラームを許可する
               0=アラームを許可しない

Bit 6    :CHIME       アラームの発報を指示するビット
               1=アラームを永久に繰り返す
               0=アラームを指定した回数繰り返す

Bit  5-2:AMASK        アラーム時刻データレジスターのどのデータ値範囲までを使うか指定
              下記記述の様に"skRTCC.h"に記載しています。
 #define RTCC_ALM_HALFSEC 0     // ALMの開始から0.5秒後にON、CHIME=1なら0.5秒毎にON/OFF
 #define RTCC_ALM_1SEC    1     // ALMの開始から1秒後にON、CHIME=1なら1秒毎にON/OFF
 #define RTCC_ALM_10SEC   2     // 指定の0-9秒後にON、以降はCHIME=1なら10秒毎にON/OFF
 #define RTCC_ALM_MIN     3     // 指定の0-59秒にON、以降はCHIME=1なら指定秒毎にON/OFF
 #define RTCC_ALM_10MIN   4     // 指定の0-9分/0-59秒にON、以降はCHIME=1なら指定時刻にON/OFF
 #define RTCC_ALM_HOUR    5     // 指定の0-59分:0-59秒にON、以降はCHIME=1なら指定時刻にON/OFF
 #define RTCC_ALM_DAY     6     // 指定の時:分:秒でON、以降はCHIME=1なら毎日の指定時刻にON/OFF
 #define RTCC_ALM_WEEK    7     // 指定曜日の時:分:秒でON、以降はCHIME=1なら毎週の指定時刻にON/OFF
 #define RTCC_ALM_MON     8     // 指定の日/時:分:秒でON、以降はCHIME=1なら毎月の指定時刻にON/OFF
 #define RTCC_ALM_YEAR    9     // 指定の月/日/時:分:秒でON、以降はCHIME=1なら毎年の指定時刻にON/OFF
Bit 1-0 :RTCPTR       アラーム時刻データレジスターのアドレスポインタを設定するビット

ALRMRPTのレジスタ

アラームの発報する回数をして指定します(0〜255)。

《配線図》

ピン構成図

18F26J50は電源が2.15V-3.6V(CORE:2.0V-2.75V)なので、回路電源は3.3Vにしました。
18F26J50を3.3Vで使うには内蔵のレギュレータ用にVDDCORE/VCAP端子(6番ピン)に、
10uFのコンデンサーを取付けVSSに落とす必要が有ります。
(10uF 6.3V以上のタンタルコンデンサーか、10V以上のセラミックコンデンサーと書いて有ります)
1番ピンはMCLR専用なのでリセット回路を取り付けないのなら1K-10KΩ抵抗でVDDに接続します。

配線図

PIC18F26J50の1番ピンは右上です、間違わない様に!。私は間違えました!!。
水晶振動子(32.768KHz)をT1OSO(11番)/T1OSI(12番)ピンに取付ますが、水晶振動子の話は
こちらを参照下さい。
日付時刻を表示する為にI2C接続LCDを使いました、LCDの話はこちらを参照下さい。
尚、I2CのSDA1(26番)/SCL1(25番)はMSSP1側を使いプルアップはPIC内蔵を利用しています。
(因みに、18F26J50の場合はMSSP2でI2Cは使えません、SPIはMSSP1/2ともOKです)
又、RTCCピン(22番)からアラーム出力やクロック出力の確認の為にLEDを取り付けています。

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

↓ここからサンプルプログラムソースファイルをダウンロードして下さい。
skRTCC.lzh(2015/06/25)

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

ダウンロードしたら解凍して下さい、以下のファイル構成です。
 INTosc.c ・・・・・・本体のサンプルソースプログラム(PIC内蔵INTRC用)
 T1osc.c ・・・・・・・本体のサンプルソースプログラム(外付けT1OSO/T1CKI用)
 skRTCC.c   ・・・・RTCCの時間管理関数ライブラリーソースプログラム
 skRTCC.h   ・・・・RTCCの時間管理関数のインクルードファイル
 skI2CLCDlib.c・・・・I2C接続LCDライブラリ関数ソースファイル
 skI2CLCDlib.h・・・・I2C接続LCDライブラリ用インクルードファイル
 skI2Clib.c・・・・・・・・I2C通信を行う関数ソースファイル
 skI2Clib.h・・・・・・・・I2C通信を行う関数のインクルードファイル

 尚、CPUのクロックは48MHzを想定しています。
 なので通信速度等(I2C)はシステムクロック48MHzで計算されています。

INTosc.c

PICに内蔵されているオシレータのINTRC(31KHz)を、RTCCのソースクロックとしたサンプルプログラム
です。
LCD表示結果  実行すると、"2015年6月24日 水曜日 9時50分00秒"からカウント
 が始まります。
 RTCC出力は、"1秒間隔クロックを出力する"の設定なので
 LEDは1秒間隔で点滅します。(アラームは設定していない)

 RTCC出力からRTCCソースクロックを出力させ、テスターで測定
 したら32.44〜32.46KHz辺りをフラフラと...んん..

T1osc.c

PICのセカンダリクロック端子"T1OSO/T1CKI"に外部水晶振動子(32.768KHz)を、RTCCのソース
クロックとしたサンプルプログラムです。

外部水晶振動子なので電源ONから正常に安定発振するまでに2秒程掛かりそう。
LCDの出力表示は上図と同じです。
RTCC出力は、"アラームを永久に出力する"の設定です。
アラームの設定データは
 月 / 日   曜日   時 : 分 : 秒
[xx]/[xx]  [x]   [xx]:[x1]:[30]   // アラームマスクによりxx部分は不使用
なので、
9時5130秒が1回目、10時0130秒が2回目、10時1130秒が3回目.......
って感じで10分毎に繰り返す事になります、だからぁLEDは10分毎にON/OFFします。
RTCCソースクロック出力のテスター値は22pF/15pFとも32.76KHzでした、ならロジアナに入れて
見ます、32.787KHzに所々で32.68KHzが現れます。
(22pFも15pFもぉ、クロック出力に大差有りませんでした、まあ、INTRCよりは安定していますかね)

RTCCのソースクロックの切り替え
コンフィギュレーションで切り替えます。
#pragma config RTCOSC = INTOSCREF// RTCCのクロックは内蔵INTRC(31KHz)を使う
#pragma config RTCOSC = T1OSCREF // RTCCのクロックは外部T1OSO/T1CKIを使う
それとぉ、外部T1OSO/T1CKIを使う場合はTimer1を有効にする必要が有ります、RTCC_Init( )関数の
パラメータ(t1osc)で有効にすれば良いでしょう。

skRTCC.h

RTCCの時間管理関数用のインクルードファイルです。
"skRTCC.c"を利用する場合に
#include "skRTCC.h" をプログラムの先頭で記述して下さい。

skRTCC.c

このライブラリは、PICのRTCC機能を使う為の関数集です。
なのでPICに"RTCCモジュール"が内蔵しているデバイスのみ動作可能です、
但し、18F46J50系統のみとします。(他のPICが無いので不明)

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

ans = RTCC_Init(t1osc,Year,Mon,mDay,wDay,Hour,Min,Sec)
 RTCCの時刻設定と初期化を行う処理です。
 この関数をコールすればRTCCモジュールはカウント開始します。
  t1osc :ソースクロックで外部のT1OSO/T1OSIから供給するなら1を指定
  Year :日付の年(0-99)を指定(西暦の下2ケタ 2000年-2099年)
  Mon  :日付の月(1-12)を指定
  mDay :日付の日(1-31)を指定(2月は28/29日)
  wDay :カレンダの曜日を指定(0=日 1=月 〜 6=土)
  Hour :時刻の時(0-23)を指定(24時間で指定)
  Min  :時刻の分(0-59)を指定
  Sec  :時刻の秒(0-59)を指定

 ※ もちろんバッテリのバックアップがないので電源OFFなら再設定ですよ。

RTCC_SetInterrupt(priority)
 RTCCの割り込みを許可する処理です。
 アラームのイベント発生を割り込みさせたい場合に使用します、但し実際の割り込み処理は
 自分でコーディングして下さい。
  priority : 割り込みの優先順を指示 0=低い優先度 1=最優先(デフォルト値)
 割り込み処理の例)
  int Flag = 0 ;
  void interrupt InterFunction( void )
  {
       if (RTCCIF==1) {
            Flag = ~Flag ;
            if (Flag == 0) LATB1 = 0 ;
            else           LATB1 = 1 ;
            RTCCIF = 0 ;
       }
  }
  main( ) {
       RTCC_SetInterrupt(1) ;
       RTCC_Init(RTCC_INTOSCREF,15,6,24,3,9,50,30) ;
       RTCC_SetPin(RTCC_1SECOUT) ;

  }
RTCC_SetPin(rtout)
 RTCCの出力ピンを設定する処理です。
 RTCCの出力ピンに出力する信号を選択出来ます。
 出力する場合はピンをデジタル出力に、TRISxレジスターで設定します。
  rtout : RTCCピンに出力する信号を指定、出力しないなら0を指定します
       1=アラームを出力 2=1秒クロックを出力 3=RTCCのソースクロックを出力

ans = RTCCtime( )
 RTCCから日付と時刻を読み出す処理です。
  ans : tm型の構造体(time.h)に値を設定して返します
      RTCCから得られる"月"の値は"1-12"ですが、time標準関数のtm型の設定方法の慣習に
      習い"0-11"でわざと-1でセットします。
 struct tm {
	int	tm_sec;
	int	tm_min;
	int	tm_hour;
	int	tm_mday;
	int	tm_mon;
	int	tm_year;
	int	tm_wday;
	int	tm_yday;  // 年の通算日だがここではセットしていない
	int	tm_isdst; // サマータイムは無効としてセットして置く
 };
 ※ tm型構造体で返すのは、後々time標準関数が利用出来る様にする為です。

RTCC_SetAlarm(rpt,mask,Mon,mDay,wDay,Hour,Min,Sec)
 RTCCのアラームデータを設定する処理です。
  rpt   :アラーム発報の繰り返す回数を指定(0-255回)
       0を指定した場合永久に壊れるまで繰り返します。
  mask :アラームを発報する時の、月日時分秒指定内のどの数値範囲までを有効とするのか
       範囲を指定(0-9の値)  上記に記述した#defineを使えば良いでしょう。
  Mon  :日付の月(1-12)を指定
  mDay :日付の日(1-31)を指定(2月は28/29日)
  wDay :カレンダの曜日を指定(0=日 1=月 〜 6=土)
  Hour :時刻の時(0-23)を指定(24時間で指定)
  Min  :時刻の分(0-59)を指定
  Sec  :時刻の秒(0-59)を指定

 ※ この関数はアラームデータを設定するだけです、RTCC_StartAlarmで開始させます。
 ※ "mask"の値を毎年指定で、発報を2月29日に設定した場合は4年に1回の発生となりますよ。

(以下は"skRTCC.h"内にマクロ定義されています)

RTCC_StartAlarm
 RTCCのアラームを開始する処理です。

RTCC_StopAlarm
 RTCCのアラームを無効(停止)にする処理です。

RTCC_SetCAL(value)
 RTCCののキャリブレーションを行う処理です。
 指定の値(value)で毎分ごとに、RTCCクロック値を増減させます。
  value : (+508)-0-(-512)RTC clock の値が指定可能
       キャリブレーション範囲は月2.64秒の誤差を修正するとあるがぁ....

 例) RTCC_SetCAL(10) ; // RTCCクロック値に毎分辺り10clock足されます

skI2CLCDlib.c
skI2CLCDlib.h
skI2Clib.c
skI2Clib.h

この内容は”秋月電子I2C接続小型LCDモジュールに表示を行う”を参照下さい。

尚、システムクロックを変えた人は"skI2Clib.c"ファイル内の"InitI2C_Master( )"関数と、
"skI2CLCD.h"のファイルを変更する必要が有ります。
また、I2C接続LCDはI2C通信速度が最大400KHz対応です、ここでは400KHzで行っています。

《その他》

実験風景
VDDCORE/VCAP端子のコンデンサーは、上では手持ちから10uF/16V電界コンデンサーです。
28PのPICを抜き差しでのプログラム書換えは面倒だったので上では直接PICkit3を繋いでいます。
ですので、電源もPICkit3から供給しています。IDEの"Power"設定値は"3.25V"です。

PICのSLEEP時でもRTCCを動作させる事が出来て、RTCCのアラームでSLEEPから目覚める事も
出来る様だが、バックアップ電池をPICのピン(VRTCな感じで)に繋いでRTCCモジュールのみを
動作し続ける仕様にしても良さそうな気がするのだがぁ

尚、何かに組み込む場合は、日付時刻の入力方法を何らかの方法で操作する必要が有るでしょう。




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