Microchip PIC24Fの内蔵タイマーを使用した Software RTC ドライバです。起動後のアワーメータ (tick、秒、分、時、日) と時刻 (ミリ秒, 秒、分, 時, 日) をカウントします。tickは、RTCドライバの基準時間単位です。標準では 0.1ミリ秒に設定されています。
標準では、1 tickの時間は 0.1ミリ秒ですが、下記のマクロを変更することで分解能を任意に変更できます。分解能を下げる (0.1ミリ秒より大きくする) と CPU負荷が下がり、分解能を上げる (0.1ミリ秒より小さくする) と CPU負荷も上がります。また、アワーメータの計算を正しく行うために、_T1Interrupt()関数内の時刻計算処理を修正してください。
CPUクロックを動的に変更する場合は、RTC_init_timer()を適宜呼び出して PR1を初期化してください。
void __attribute__((interrupt, auto_psv)) _T1Interrupt(void) { IFS0bits.T1IF = 0; /* tick is 0.1ms */ rtc.tick++; if(rtc.tick % 10 != 0) return; /* ミリ秒 */ rtc.msec++; rtc.msec = rtc.msec % 1000; if(rtc.msec != 0) return; /* 秒 */ rtc.secmeter++; rtc.sec++; rtc.sec = rtc.sec % 60; if(rtc.sec != 0) return; /* 分 */ rtc.minmeter++; rtc.min++; rtc.min = rtc.min % 60; if(rtc.min != 0) return; /* 時 */ rtc.hourmeter++; rtc.hour++; rtc.hour = rtc.hour % 24; if(rtc.hour != 0) return; /* 日 */ rtc.day++; return; }
void RTC_init_timer(void) { PR1 = cpu_fcy[ OSCTUN ] / 10000; /* 0.1ミリ秒 */ return; }
void __attribute__((interrupt, auto_psv)) _T1Interrupt(void) { IFS0bits.T1IF = 0; /* tick is 1ms */ rtc.tick++; /* ミリ秒 */ rtc.msec++; rtc.msec = rtc.msec % 1000; if(rtc.msec != 0) return; /* 秒 */ rtc.secmeter++; rtc.sec++; rtc.sec = rtc.sec % 60; if(rtc.sec != 0) return; /* 分 */ rtc.minmeter++; rtc.min++; rtc.min = rtc.min % 60; if(rtc.min != 0) return; /* 時 */ rtc.hourmeter++; rtc.hour++; rtc.hour = rtc.hour % 24; if(rtc.hour != 0) return; /* 日 */ rtc.day++; return; }
void RTC_init_timer(void) { PR1 = cpu_fcy[ OSCTUN ] / 1000; /* 1ミリ秒 */ return; }
Aと Bの時刻から、時間差を得ます。
#include <p24FJ64GA002.h> #include "librtc.h" _CONFIG1( JTAGEN_OFF & GCP_OFF & GWRP_OFF & BKBUG_OFF & WINDIS_OFF & COE_OFF & ICS_PGx1 & FWDTEN_ON & WDTPS_PS256) _CONFIG2( IESO_OFF & FNOSC_FRCPLL & FCKSM_CSDCMD & OSCIOFNC_ON & IOL1WAY_OFF & I2C1SEL_PRI & POSCMOD_NONE) int main(void) { unsigned int tick; /* Fosc = 8.96MHz, Fcy = 17.92MHz, Core 35.84MHz */ CLKDIV = 0; OSCTUN = 0b0000000000011111; SRbits.IPL = 0; /* ポートの入出力モード設定 */ /* FEDCBA9876543210 */ TRISA = 0b0000000000000011; TRISB = 0b0000111101100001; RTC_init(); /* メインループ */ tick = rtc.tick; while(1){ ClrWdt(); /* 100ms経過したら処理を行う */ if(RTC_get_ticks(tick, rtc.tick) > 1000){ /* 何かさせる */ } } return(0); }