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);
}