RTCドライバについて

 Microchip PIC24Fの内蔵タイマーを使用した Software RTC ドライバです。起動後のアワーメータ (tick、秒、分、時、日) と時刻 (ミリ秒, 秒、分, 時, 日) をカウントします。tickは、RTCドライバの基準時間単位です。標準では 0.1ミリ秒に設定されています。

仕様 

ソースコード

  1. librtc.c
  2. librtc.h
  3. table.c
  4. table.h
  5. types.h

回路図

 ありません。内部タイマーを使用しているのみで、ソフトウェアだけで動きます。

サンプルコード

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

分解能の変更方法

 標準では、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;
}