山本ワールド
RTC8564 RTCライブラリ
概要
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);
}
Copyright (C) 2012 山本ワールド All Rights Reserved.