/* ======================================================== RTC $Id$ ======================================================== */ #ifndef _WIN32 #pragma sfr #pragma inline #endif #include "incs.h" #define RTC_DATA_SIZE 7 // ======================================================== static u8 rtc_work[RTC_DATA_SIZE]; static bit rtc_lock; static bit rtc_dirty; bit rtc_alarm_dirty; /********************************************//** ペリフェラルの初期化 レジスタの電池交換ビットのセット ***********************************************/ void RTC_init( void ) { if( !RTCEN ) // ビットが立っていたらリブート { RTCEN = 1; // モジュールON // RTC設定 RTCC0 = bits8(0,0,0,0, 1,0,0,0); /* 動作停止、24時間制、32k出力「まだなし」、定周期割り込みなし */ // (RTCE 0 RCLOE1 RCLOE0 AMPM CT2 CT1 CT0) RTCC1 = bits8(1,1,0,0, 0,0,0,0); /* アラーム割り込み有効&動作開始 */ // (WALE WALIE 0 WAFG RIFG 0 RWST RWAIT) RTCC2 = bits8(1,0,0,0, 0,0,0,0); /* インターバル:32k/2^6=2ms、RTCDIV出力なし */ // (RINTE RCLOE2 RCKDIV 0 0 ICT2 ICT1 ICT0) HOUR = 0x00; MIN = 0x00; SEC = 0x00; MONTH = 0x01; DAY = 0x01; WEEK = 0x01; // Mon YEAR = 0x01; ALARMWW = 0x7F; vreg_ctr[VREG_C_MCU_STATUS] |= REG_BIT_RTC_BLACKOUT; } // 割り込み設定 RTCIF = 0; RTCIIF = 0; RTCMK = 1; /* 割り込み(定周期)禁止 */ RTCIMK = 0; /* 割り込み(アラーム&インターバル)許可 */ RTCE = 1; /* 動作開始 */ RWAIT = 1; while( !RWST ) {;} RWAIT = 0; rtc_lock = false; rtc_dirty = false; rtc_alarm_dirty = false; } /********************************************//** RTC アラーム割り込み ***********************************************/ __interrupt void int_rtc( ) { RWAIT = 1; while( !RWST ) {;} // 日付も指定日で if( ( vreg_ctr[VREG_C_RTC_ALARM_DAY] == DAY ) && ( vreg_ctr[VREG_C_RTC_ALARM_MONTH] == MONTH ) && ( vreg_ctr[VREG_C_RTC_ALARM_YEAR] == YEAR ) ) { set_irq( VREG_C_IRQ1, REG_BIT_RTC_ALARM ); } RWAIT = 0; } /********************************************//** RTC のリード レジスタは、sec,min,hour,week,day,month,year の順 ***********************************************/ void rtc_buf_refresh( ) { if( !rtc_lock ) { rtc_lock = true; RWAIT = 1; while( !RWST ) {;} memcpy( &vreg_ctr[VREG_C_RTC_SEC], &SEC, RTC_DATA_SIZE ); RWAIT = 0; // renge_task_immed_add( tski_rtc_close ); } } /********************************************//** RTC のライト set_rtc_close と対で使って下さい。 こいつはバッファにコピーするだけで、 実際にRTCにセットするのはset_rtc_close()です。 ***********************************************/ void set_rtc( u8 adrs, u8 data ) { if( !rtc_dirty ) { rtc_dirty = true; memcpy( rtc_work, &SEC, RTC_DATA_SIZE ); // renge_task_immed_add( tski_rtc_close ); // I2C終了時に行う } rtc_work[adrs] = data; } /********************************************//** 必要ならば、RTCレジスタの更新 ***********************************************/ // task_status_immed tski_rtc_close(){ void rtc_unlock( ) { // リードロック rtc_lock = false; // ライトロック if( rtc_dirty ) { rtc_dirty = false; RWAIT = 1; while( !RWST ) {;} memcpy( &SEC, rtc_work, RTC_DATA_SIZE ); RWAIT = 0; } // アラームセット if( rtc_alarm_dirty ) { rtc_alarm_dirty = false; WALE = 0; ALARMWM = vreg_ctr[VREG_C_RTC_ALARM_MIN]; ALARMWH = vreg_ctr[VREG_C_RTC_ALARM_HOUR]; WALE = 1; } } /********************************************//** RTC システムチックタイマ割り込みベクタ 2^6/fXT(1.953125 ms) ***********************************************/ __interrupt void int_rtc_int( ) { // renge_flg_interval ++; // インクリメント/デクリメント命令を使うので DI()不要 renge_flg_interval = 1; // set1命令を使うので DI()不要 }