概要

I2Cで接続できるRTC8564(EPSONのページに移動します)向けのライブラリである。
初期化、時刻の読み出し、時刻の書き込み、バックアップ状況の取得、インターバルタイマーの設定等をサポートしている。
使用する場合はrtc.hをインクルードしrtc.cをプロジェクトに追加してください
ライブラリの関数をコールする前にI2Cモジュールの初期化をしてください。

プログラムの説明

ソースファイル

以下のファイルで構成されている
rtc.c   ・・・ RTC8564 RTCライブラリ Version 1.00
rtc.h   ・・・ RTC8564 RTCライブラリ Version 1.00

サブルーチン

以下のサブルーチンをサポート
RTC_DATE構造体についてはrtc.hの定義を参照してください。

rtc_init

RTCの初期化をします。

rtc_sput

RTC_DATE構造体の日付を文字列に変換します。

rtc_start

RTCの時刻のカウントを開始します。

rtc_stop

RTCの時刻のカウントを停止します。

rtc_write

RTC_DATE構造体の日時をRTCに書き込みます。

rtc_read

RTCより日時を読み込みRTC_DATE構造体に格納します。

rtc_vl_chk

RTCのバックアップ状態を取得します。0以外が返された場合はRTCの初期化が必要です。

rtc_read_byte

RTCの指定されたアドレスから1byteデータを取得します。

rtc_write_byte

RTCの指定されたアドレスへ1byte書き込みます。

rtc_timer_on

RTCのインターバルタイマーを初期化し有効にします。

rtc_timer_off

RTCのインタバールタイマーを停止します。

ソースコード

rtc.h

/*
 * RTC8564 RTCライブラリ Version 1.00
 * File:        rtc.c
 * Target:      PIC18F14K50 48MHz
 * コンパイラ:   Microchip MPLAB XC8 C Compiler V1.20
 * 書き込み:     PICKit 3
 * リリース:     2013/09/29 15:00
 *
 * 初期化、電圧低下フラグ検出、RTC読み書き、インターバルタイマーOn/Off
*/

#ifndef RTC_H
#define	RTC_H

//       RTCレジスタの定義

#define RTC8564_SADS    0b10100010 //   スレーブアドレス
#define RTC_CTL1    0
#define RTC_CTL2    1
#define RTC_SEC     2
#define RTC_MIN     3
#define RTC_HOUR    4
#define RTC_DAY     5
#define RTC_WEEK    6
#define RTC_MONTH   7
#define RTC_YEAR    8
#define RTC_AMIN    9
#define RTC_AHOUR   0xa
#define RTC_ADAY    0xb
#define RTC_AWEEK   0xc
#define RTC_CLOCK   0xd
#define RTC_TIMERCTL   0xe
#define RTC_TIMER   0xf


struct RTC_DATE {
    unsigned char sec;
    unsigned char min;
    unsigned char hour;
    unsigned char day;
    unsigned char week;
    unsigned char month;
    unsigned char year;
};

signed char rtc_init(void); //  RTC初期化
void rtc_sput(unsigned char* buf,struct RTC_DATE* d); //  日時を表示
void rtc_date_sput(unsigned char* buf,struct RTC_DATE* d); //  日付を表示
void rtc_time_sput(unsigned char* buf,struct RTC_DATE* d); //  時刻を表示
signed char rtc_start(void); //  RTCカウントを開始
signed char rtc_stop(void); //  RTCカウント停止
signed char rtc_write(struct RTC_DATE* d); //  日時設定
signed char rtc_read(struct RTC_DATE* d); //  日時読み出し
signed char rtc_vl_chk(void); //  VLビットチェック  1:初期化必要 0:初期化不要
void rtc_timer_on(void); //  1秒周期タイマーを開始
void rtc_timer_off(void); //  1秒周期タイマーを停止

#endif  //  RTC_H


rtc.c

/*
 * RTC8564 RTCライブラリ Version 1.00
 * File:        rtc.c
 * Target:      PIC18F14K50 48MHz
 * コンパイラ:   Microchip MPLAB XC8 C Compiler V1.20
 * 書き込み:     PICKit 3
 * リリース:     2013/09/29 15:00
 *
 * 初期化、電圧低下フラグ検出、RTC読み書き、インターバルタイマーOn/Off
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <p18f14k50.h>
#include <plib\delays.h>
#include <plib\i2c.h>
#include "i2c_ex.h"
#include "rtc.h"

//  RTCの初期値

unsigned char rtc_init_data[]={
   0b00100000, 0b00000000, // CTL1,CTL2
   0x00,0x40,       // 02h 秒,分
   0x14,0x22,       // 04h 時,日
   0x00,0x09,       // 06h 曜日,月
   0x13,0x80,       // 08h 年,アラーム 分
   0x80,0x80,       // 0ah アラーム 時,アラーム  日
   0x80,0x00,       // 0ch アラーム 曜日,CLOCKOUT 周波数
   0x00,0x00};      // 0eh タイマーCTL,タイマー

//  RTC初期化

signed char rtc_init(void){
    unsigned char* buf=rtc_init_data;
    unsigned char n;
    signed char ret;

    do{
        SSPCON1bits.WCOL=0;
        IdleI2C();
        StartI2C();
        while(SSPCON2bits.SEN);
        if(PIR2bits.BCLIF)
            return -10;
    }while(SSPCON1bits.WCOL);

    if(ret=i2c_write(RTC8564_SADS) )
        return ret-2;

    if(ret=i2c_write(RTC_CTL1))
        return ret-4;
    for(n=0;n<16;n++)
        if(ret=i2c_write(buf[n]))
            return ret;
    StopI2C();
    while(SSPCON2bits.PEN);
    return 0;
}

//  日時を表示

void rtc_sput(unsigned char* buf,struct RTC_DATE* d){
    rtc_date_sput(buf,d);
    buf[8]='\n';
    rtc_time_sput(buf+9,d);
}

//  RTCカウントを開始

signed char rtc_start(void){
    signed char ret;
    do{
        SSPCON1bits.WCOL=0;
        IdleI2C();
        StartI2C();
        while(SSPCON2bits.SEN);
        if(PIR2bits.BCLIF)
            return -10;
    }while(SSPCON1bits.WCOL);

    if( ret=i2c_write(RTC8564_SADS) )
        return ret-2;

    if(ret=i2c_write(RTC_CTL1))
        return ret-4;
    if(ret=i2c_write(0))
        return ret-6;
    StopI2C();
    while(SSPCON2bits.PEN);
    return 0;
}

//  RTCカウント停止

signed char rtc_stop(void){
    signed char ret;
    do{
        SSPCON1bits.WCOL=0;
        IdleI2C();
        StartI2C();
        while(SSPCON2bits.SEN);
        if(PIR2bits.BCLIF)
            return -10;
    }while(SSPCON1bits.WCOL);
    if(ret=i2c_write(RTC8564_SADS))
        return ret-2;
    if(ret=i2c_write(RTC_CTL1))
        return ret-4;
    if(ret=i2c_write(0b00100000))
        return ret-6;
    StopI2C();
    while(SSPCON2bits.PEN);
    return 0;
}

//  日時設定

signed char rtc_write(struct RTC_DATE* d){
    int n;
    d->month &= 0x1f;
    d->week &= 0x07;
    d->day &= 0x3f;
    d->hour &= 0x3f;
    d->min &= 0x7f;
    d->sec &= 0x7f;
    unsigned char* buf=(unsigned char*)d;
    signed char ret;
    do{
        SSPCON1bits.WCOL=0;
        IdleI2C();
        StartI2C();
        while(SSPCON2bits.SEN);
        if(PIR2bits.BCLIF)
            return -10;
    }while(SSPCON1bits.WCOL);
    if(ret=i2c_write(RTC8564_SADS))
        return ret-2;
    if(ret=i2c_write(RTC_SEC))
        return ret;
    for(n=0;n<7;n++)
        if(ret=i2c_write(buf[n]))
            return ret-4;
    StopI2C();
    while(SSPCON2bits.PEN);
    return 0;

}

//  日時読み出し

signed char _rtc_read(struct RTC_DATE* d){
    unsigned char n;
    unsigned char* buf=(unsigned char*)d;
    signed char ret;

    do{
        SSPCON1bits.WCOL=0;
        IdleI2C();
        StartI2C();
        while(SSPCON2bits.SEN);
        if(PIR2bits.BCLIF){
            return -10;
        }
    }while(SSPCON1bits.WCOL);

    ret=i2c_write(RTC8564_SADS);
    if(ret)
        return ret-2;
    if(ret=i2c_write(RTC_SEC))
        return ret-4;
    RestartI2C();
    while(SSPCON2bits.RSEN);

    if(ret=i2c_write(RTC8564_SADS | 1))
        return ret-6;

    for(n=0;n<7;n++){
        buf[n]=ReadI2C();
        SSPCON2bits.ACKDT=0;
        SSPCON2bits.ACKEN=1;
        while(SSPCON2bits.ACKEN);
    }
    buf[n]=ReadI2C();
    SSPCON2bits.ACKDT=1;
    SSPCON2bits.ACKEN=1;
    while(SSPCON2bits.ACKEN);
    StopI2C();
    while(SSPCON2bits.PEN);

    d->month = d->month & 0x1f;
    d->week = d->week & 0x07;
    d->day = d->day & 0x3f;
    d->hour = d->hour & 0x3f;
    d->min = d->min & 0x7f;
    d->sec = d->sec & 0x7f;
    return 0;
}

//  日時読み出し

signed char rtc_read(struct RTC_DATE* d){
    unsigned char try=TRY;
    signed char ret;
    do{
        if( (ret=_rtc_read(d)) == 0 )
            break;
        Delay1TCYx( 24);  //  2μs*(48MHz/4)= 24
    }while(--try);
    return ret;
}

//  VLビットチェック  1:初期化必要 0:初期化不要

signed char rtc_vl_chk(void){
    unsigned char n;
    unsigned char sec;
    signed char ret;
    do{
        SSPCON1bits.WCOL=0;
        IdleI2C();
        StartI2C();
        if(PIR2bits.BCLIF){
           return -12;
       }
        while(SSPCON2bits.SEN);

    }while(SSPCON1bits.WCOL);
    ret=i2c_write(RTC8564_SADS);

    if(i2c_write(RTC_SEC))
        return 1;
    RestartI2C();
    while(SSPCON2bits.RSEN);
    if(i2c_write(RTC8564_SADS | 1))
        return 1;
    while(DataRdyI2C());
    sec=ReadI2C();
    SSPCON2bits.ACKDT=1;
    SSPCON2bits.ACKEN=1;
    while(SSPCON2bits.ACKEN);
    StopI2C();
    while(SSPCON2bits.PEN);
    if(sec & 0x80)
        return 1;
    else
        return 0;
}

//  1byte読み出し

signed char rtc_read_byte(unsigned char ads){
    unsigned char data;
    signed char ret;
    do{
        SSPCON1bits.WCOL=0;
        IdleI2C();
        StartI2C();
        if(PIR2bits.BCLIF){
           return -12;
       }
        while(SSPCON2bits.SEN);

    }while(SSPCON1bits.WCOL);
    ret=i2c_write(RTC8564_SADS);

    if(i2c_write(ads))
        return 1;
    RestartI2C();
    while(SSPCON2bits.RSEN);
    if(i2c_write(RTC8564_SADS | 1))
        return 1;
    while(DataRdyI2C());
    data=ReadI2C();
    SSPCON2bits.ACKDT=1;
    SSPCON2bits.ACKEN=1;
    while(SSPCON2bits.ACKEN);
    StopI2C();
    while(SSPCON2bits.PEN);
    return data;
}

//  1byte出力

signed char rtc_write_byte(unsigned char ads,unsigned char data){
    signed char ret;
    do{
        SSPCON1bits.WCOL=0;
        IdleI2C();
        StartI2C();
        while(SSPCON2bits.SEN);
        if(PIR2bits.BCLIF)
            return -10;
    }while(SSPCON1bits.WCOL);

    if( ret=i2c_write(RTC8564_SADS) )
        return ret-2;

    if(ret=i2c_write(ads))
        return ret-4;
    if(ret=i2c_write(data))
        return ret-6;
    StopI2C();
    while(SSPCON2bits.PEN);
    return 0;
}

//  1秒周期タイマーを開始

void rtc_timer_on(void){
    rtc_write_byte(RTC_TIMERCTL,0); //  タイマーOFF TE=0
    rtc_write_byte(RTC_CTL2,0); // TF=TIE=0

    rtc_write_byte(RTC_CTL2,0b00010001);    // TI/TP=1 割り込み動作継続,TIE=1 INT出力イネブル
    rtc_write_byte(RTC_TIMERCTL,0b00000010); // 1Hz TD=10
    rtc_write_byte(RTC_TIMER,0x1);  // 1秒置きに割り込み
    rtc_write_byte(RTC_TIMERCTL,0b10000010); // タイマーON TE=1
}

//  1秒周期タイマーを停止

void rtc_timer_off(void){
    rtc_write_byte(RTC_TIMERCTL,0); //  タイマーOFF TE=0
    rtc_write_byte(RTC_CTL2,0);
}