YS電子工作ラボ

<V.3版>

RTCCモジュール制御による
時刻表示とアラーム動作

(→プロジェクトファイル(Harmony Ver.3版 MHC v3.6.0) ダウンロード


 RTCCモジュールを使った キャラくタ液晶への時刻表示と所定時刻でのアラーム発生動作の例を紹介します。


<仕様>
 ・PIC32MZのRTCCモジュールを用いて以下をキャラクタ液晶に表示すること。
  液晶1行目: 西暦年、月、日、曜日    (例)  2017/04/30 Fri
  液晶2行目: 時、分、秒          (例)  15:03:26
 ・初期設定の時刻は 西暦2017年2月28日23時59分45秒とする。
 ・アラーム発生の時刻は 西暦2017年3月1日0時0分15秒とする。
 ・RTCCモジュールが動作している場合はLEDを周期 1sec、デューティ 50%で点滅させること。
 ・アラームが発生するまで、RCTT(RD0)ピンに RTCCセカンドパルス(0-3.3v、周期1sec、デューティ50%)を出力すること。 
  RTCCピンにコンデンサ経由でスピーカを接続してパルス立ち上がり、立下り時の音を聞けること。
 ・アラームが発生したら液晶に以下を表示のこと。
  液晶1行目: Alarm occurred
  液晶2行目: アラーム発生時刻(0:0:15)
 ・RTCCモジュールのクロック基準は32.768KHzの副発振器を用いること。
 ・RTCCドライバーは システムサービスのRTCCドライバーを使用すること。
   

<回路図>(→ PDFファイル



<外観>PIC32MZ評価ボード(→購入方法)を使った実験品の外観です。
     汎用モジュール評価ボード(段積みボード)には本テーマと関係ない部品が多々実装されています。



<動作結果> (→ 動画:1080pのHD動画を見ることができます。)


液晶表示 
①起動直後 ②初期値の時刻を表示しているところです。
 1行目: 西暦年/月/日/ 曜日
 2行目: 時/分/秒 
③2017年(平年)の2/28から 3/1に変わった
 直後の表示です。 RTCCモジュールのカレンダーが
 2月を正しく28日と処理しているのがわかります。
④アラームが発生した場合の表示です。
 2行目に アラーム発生の時刻が表示されて
 います。


RTCC(RD0)ピン出力電圧
1v/div
500msec/div
アラーム発生前では、連続して 1Hz, Duty 50% の
パルスが出力されています。
アラーム発生後(画面中央位置)からはに出力が
パルスがなくなくなっています。



<解説>以下に、記載してある内容は要点だけです。 詳細はプロジェクトファイルを精読願います

■ MHC設定
  

項目 1. [Clock Diagram]タブで、クロックの構成を外付け24MHz水晶発振器用、システムクロック200MHzに設定します。
 POSCMOD: → EC
 FPLLICLK: → POSC
 FPLLIDIV: → DIV_3
2. [Pin Settings]タブでの設定1
■ピン1のRG15ポート
 Function: → GPIO
 Direction: → OUT
3. [Pin Settings]タブでの設定2
■ピン71のRD0ポート
 Function: → RTCC
MHC
項目 4. [Prpject Graph]タブでの設定
■追加コンポーネント
  RTCC
■ コンポーネント間の接続
 なし
5. [Prpject Graph]タブでの設定
■コンポーネント RTCCの設定
 Eanble Interrupt ? にチェック追加
 RTCC Clock Select bits →
  RTCC uses External 32.768KHz Secondary Oscillator
 RTCC Output Enable bit にチェック追加
 RTCC Output Data Select bits →
  Seconds Clock is presented on the RTCC pin 
 
MHC  


■ キャラクタ液晶表示のライブラリ 1lcd_lib_XC32.h と 1lcd_lib_XC32.cを main.cと同じフォルダにコピーして、プロジェクトに追加します。
     (詳細→ キャラクタ液晶表示方法 参照)




■ main.cに、青字部分を追加します。 

①インクルードファイルを追加します。stdio.hがないと、sprintf( )がコンパイラのバージョンによってコンパイルで警告となることが
  あります。  現在時刻用とアラーム用の時刻情報保持用の構造体を宣言します。  
   #include "stdio.h"
   #include "1lcd_lib_XC32.h"
   struct tm initialTime; //年月日時分秒の構造体を宣言
   struct tm alarm_time; //アラーム時刻の 年月日時分秒の構造体を宣言


② 所要の変数、遅延関数を宣言、定義します。  曜日を表す文字列もプログラムを簡単にするために 
  2次元の配列char Week[7][4] = {{"Sun"},{"Mon"},{"Tue"},{"Wed"},{"Thu"},{"Fri"},{"Sat"}}; として定義しておきます。
   int delay_Clock = 200000000; //200MHz
   char Buf[32];
   bool LED;
   ……
   ……


③ NOPを利用した μsec、msecの遅延関数 delay_us( )、delay_ms( )を定義します。
    void delay_us(volatile unsigned int usec) //1μsec遅延
    {
       volatile int count;

    ……
    ……



④  関数RTCC_Callbackはアラーム発生時呼び出されるコールバック関数です。
   ここでアラーム発生のフラグをたて、アラームが発生した時刻をRTCC_TimeGet( )で取得して、
   Hour0、Minute0、Second0に保存します。。
    void RTCC_Callback( uintptr_t context) //アラーム発生コールバック関数
    {
      AlarmOccurrence = 1; //アラーム発生のフラグをたてる
      RTCC_TimeGet(&initialTime);
      Hour0 = initialTime.tm_hour; //時
      Minute0 = initialTime.tm_min; //分
      Second0 = initialTime.tm_sec; //秒

    }




⑤ アラーム発生時のキャラクタ液晶表示の関数を定義しておきます。
    void Display_DateTime(void) //年月日と時刻の液晶表示
    {
      lcd_cmd(0x80); //1目の先頭へ
      sprintf(Buf,"Alarm occurred ");//
      ……
      ……





⑥ APP_Initialize( )の中に 動作チェック用として液晶への文字表示のコードを記載します。
   lcd_init(); // LCD初期化
   lcd_cmd(0b00001100); // カーソル:OFF ブリンク:OFF
   lcd_clear();
   ……
   ……


⑦ つづいて RTCCモジュールの時刻初期値、アラーム発生時刻を設定します。
    // Time setting 2017年2月28日23時59分45秒 火曜日
    initialTime.tm_year = 17;
    initialTime.tm_mon = 2;
    initialTime.tm_mday = 28;
    initialTime.tm_wday = 2;
    initialTime.tm_hour = 23;
    initialTime.tm_min = 59;
    initialTime.tm_sec = 45;


    RTCC_TimeSet(&initialTime);//年月日時分秒設定

    // Alarm setting 2017年3月1日0時0分15秒 水曜日
    alarm_time.tm_year = 17;
    alarm_time.tm_mon = 3;
    alarm_time.tm_mday = 1;
    alarm_time.tm_wday = 3;
    alarm_time.tm_hour = 0;
    alarm_time.tm_min = 0;
    alarm_time.tm_sec = 15;

    RTCC_AlarmSet(&alarm_time, RTCC_ALARM_MASK_HHMISS); //RTCC_ALARM_MASK_HHMISS: Once a day
   ……
   ……



⑧ APP_Initialize ( )で初期化後、関数RTCC_CallbackRegister( )でアラーム時刻になったら呼び出す
  コールバック関数RTCC_Callback( )を設定します。
    APP_Initialize ();
    RTCC_CallbackRegister(RTCC_Callback, (uintptr_t) NULL);


⑨ 無限ループwhile(true)の中でで、Half Second bitの反転ごとのタイミングを捉えます。
   SecStatus1 = RTCCONbits.HALFSEC; //Half Second bitの状態取得
   if(SecStatus1 != SecFlag)
   ……
   ……


⑩ LEDを点滅すべく、LEDを反転します。
   if(LED == 1)
   {
     LED = 0;
     LATGbits.LATG15 = 1; //LED点灯
   ……

   ……


⑪ RTCCモジュールの時刻を読みだします。
    Year = initialTime.tm_year; //西暦年
    Month = initialTime.tm_mon; //月
    Day = initialTime.tm_mday; //日
    WeekDay = initialTime.tm_wday; //曜日
    Hour = initialTime.tm_hour; //時
    Minute = initialTime.tm_min; //分
    Second = initialTime.tm_sec; //秒



⑫ アラーム発生の割り込みが発生していない場合の現在時刻の液晶表示をおこないます。
   if(AlarmOccurrence != 1 ) //アラーム発生の割り込みが発生していない場合
   {
     lcd_cmd(0x80); //1目の先頭へ
     sprintf(Buf,"%02d/%02d/%02d %s ",Year,Month,Day,Week[WeekDay]);//
     ……
     ……



(13) RTCCピンの出力を停止して、アラーム発生の時刻を表示します。
   RTCCピンへのクロックを停止して出力を停止する関数がないようなのでレジスタを直接制御しています。
   else
   {
     RTCCONbits.RTCOE = 0; //RTCC(RD0)ピンへのRTCCクロック(1Hz,duty=50%))の停止 //RTCC output is disabled
     TRISDbits.TRISD0 = 0;
     LATDbits.LATD0 = 0     
     
     Display_DateTime(); //年月日と時刻の液晶表示
    }

以下、main.c 全文