/********************************(RTC-DS1307.c)***
 *  RTC (DS1307) ライブラリ
 ****************************************************/
#include "string.h"
#include "myProject.h"
#define DS1307  0x68    // RTCのI2Cアドレス
#define NO_PRINTF
//===   RTC用変数(2進数で格納)
                
uint16_t J_Week[]={'日','月','火','水','木','金','土'};
char     D_Week[][4]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
uint8_t DayTm[] = { 0,	// Seconds
                    30,	// minutes
                    10,	// Hours(24h)
                    4,	// day[week]
                    1,	// date
                    1,	// month
                    25,	// year (下2桁)
                    0	// SQW/OUT
                 };
static uint8_t ClockMd = 1;    // 起動時は時計表示モード
static uint8_t Sec = 0;
/****** 汎用関数 ***************************/
//---- BCD数を2進数に変換
uint8_t bcd2bin(uint8_t bcd){
    return  ((bcd >> 4)& 0x0F) * 10 + (bcd & 0x0F);
}
//---- 2進数をBCD数に変換
uint8_t bin2bcd(uint8_t bin){
    return  (uint8_t)((uint16_t)(bin/10) << 4)+(bin % 10);
}
//---- 文字列から数値を取り出し、1バイト配列に逆順で格納
/*      buf:    取り出した数値を格納する1バイト配列
 *      src:    数値を取り出す文字列
 *      delim:  区切り文字を文字列にしたもの
 *  (戻り値): 取得出来た数値の数                   */
uint8_t get_NumRev(uint8_t *buf, char *src, char *delim){
    char    *ptr;
    uint8_t bt, n = 0;
    ptr = strtok(src, delim);
    while(ptr != NULL){
        bt = (uint8_t)atoi(ptr);  //無効データでも0を返す
        *buf-- = bt;
        n++;
        ptr = strtok(NULL, delim);
    }
    return n;
}
/****** RTC用関数 ******************************/
//--- RTCのadr番地にdatデータを書き込む
void RTC_write(uint8_t adr, uint8_t dat){
    uint8_t bf[3];
    bf[0] = adr;                     // Address = adr
    bf[1] = dat;                     // Set Data
    I2C1_WriteNBytes(DS1307, bf, 2); // Write Data
}
//--- RTCのadr番地のデータを読み込む
uint8_t RTC_read(uint8_t adr){
    uint8_t bf[3];
    bf[0] = adr;                     // Address = adr
    I2C1_WriteNBytes(DS1307, bf, 1); // Set Address
    I2C1_ReadNBytes(DS1307, bf, 1);  // Read Data
    return bf[0];
}
//--- RTCの全てのrtcデータをbuf[]読み込む
void RTC_readAll(uint8_t *buf,uint8_t bcd){
    uint8_t rtc[8],i;
    rtc[0] = 0;                       // Address = 0
    I2C1_WriteNBytes(DS1307, rtc, 1); // Set Address
    I2C1_ReadNBytes(DS1307, rtc, 8);  // Read Data
    for(i = 0; i < 8; i++){
        if(bcd) buf[i] = bcd2bin(rtc[i]);
        else    buf[i] = rtc[i];
    }
}
//--- RTCの全てにrtcデータを書き込む
void RTC_writeAll(uint8_t *buf){
    uint8_t rtc[8],i;
    rtc[0]=0;                         // Address = 0
    for(i=0; i < 8; i++){
        rtc[i+1] = bin2bcd(buf[i]);
    }
    I2C1_WriteNBytes(DS1307, rtc, 9);
}
//--- RTCの指定アドレスからnバイトのデータを書き込む
void RTC_writePrt(uint8_t *buf, uint8_t adr, uint8_t n){
    uint8_t rtc[9],i;
    rtc[0] = adr;                      // Address = adr
    for(i = 0;i < n; i++){
        rtc[i+1] = bin2bcd(buf[adr+i]);
    }
    I2C1_WriteNBytes(DS1307, rtc, n+1);
}
//--- RTCの初期化(通常は使用しない)
void RTC_init(){
    RTC_writeAll(DayTm);
}
/*======================================
 * 	BCDデータ表示サブルーチン
 *=====================================*/
//--- BCDデータを文字変換し文字列に差し込む
char *RTC_HsetBCD(char *str, uint8_t bcd,uint8_t zero){
    uint8_t hcd;
    if( (zero>0) & ((bcd>>4)==0) )
        hcd = 0x20;  
    else
        hcd = 0x30 + (bcd >> 4);
    *str++ = hcd;
    hcd = 0x30 + (bcd & 0x0F);
    *str++ = hcd;
    return str;
}
//--- BCDデータを全角文字列に変換して表示
/*	x:表示x位置、pg:表示ページ位置、gap:表示文字間ドット数
 *	bcd:表示したいBCD文字、zero:ゼロサプレスが無し(0)/有り(1)	*/
void RTC_ZprtBCD(uint8_t x, uint8_t pg, uint8_t gap, uint8_t bcd,uint8_t zero){
    uint16_t kcd;
    if( (zero>0) & ((bcd>>4)==0) )
        kcd = 0x2121;  
    else
        kcd = 0x2330 + (bcd >> 4);
    i2cOLED_ZchrX(x,pg,kcd,2);
    kcd = 0x2330 + (bcd & 0x0F);
    i2cOLED_ZchrX(x+16+gap,pg,kcd,2);  
}
//--- BCDデータを拡張全角文字列に変換して表示
/*	x:表示x位置、pg:表示ページ位置、gap:表示文字間ドット数
 *	bcd:表示したいBCD文字、zero:ゼロサプレスが無し(0)/有り(1)	*/
void RTC_2ZprtBCD(uint8_t x, uint8_t pg, uint8_t gap, uint8_t bcd,uint8_t zero){
    uint16_t kcd;
    if( (zero>0) & ((bcd>>4)==0) ){
        kcd = 0x2121;
        i2cOLED_ZchrX(x,pg,kcd,2);        
        i2cOLED_ZchrX(x,pg+2,kcd,2);      
    }else{
        kcd = 0x2659 + (bcd >> 4)*2;
        i2cOLED_ZchrX(x,pg,kcd,2);
        i2cOLED_ZchrX(x,pg+2,kcd+1,2);      
    }
    kcd = 0x2659 + (bcd & 0xF)*2;
    i2cOLED_ZchrX(x+16+gap,pg,kcd,2);
    i2cOLED_ZchrX(x+16+gap,pg+2,kcd+1,2);   
}
//---- RTC データをOLED に表示(BCDデータを利用)
void RTC_prtOLED(){
    char buf[20];
    uint8_t d;
    uint16_t kcd;
    RTC_readAll(DayTm,0);
    strcpy(buf,"2000/01/01(");
    RTC_HsetBCD(buf+2,DayTm[6],0);
    RTC_HsetBCD(buf+5,DayTm[5],1);
    RTC_HsetBCD(buf+8,DayTm[4],1);
    d = DayTm[3] & 0x0F;
    i2cOLED_HstrX(0,0,buf);
    i2cOLED_ZchrX(92,0,J_Week[d],0);
    i2cOLED_HchrX(112,0,')');
    RTC_2ZprtBCD(0,3,4,DayTm[2],1);
    i2cOLED_HchrX(40,3,0xA5);    i2cOLED_HchrX(40,5,0xA5);
    RTC_2ZprtBCD(50,3,4,DayTm[1],0);
    RTC_ZprtBCD(90,5,0,DayTm[0],0); 
}
/***** コマンド処理 *********************/
//---- I(read_tIme)コマンド(テスト用)	"I"
void i2cRTC_cmd_I(){
    char buf[20];
    RTC_readAll(DayTm,0);
    strcpy(buf,"2000/01/01(   )");
    RTC_HsetBCD(buf+2,DayTm[6],0);
    RTC_HsetBCD(buf+5,DayTm[5],0);
    RTC_HsetBCD(buf+8,DayTm[4],0);
    buf[12] = 0x30 + (DayTm[3]& 0x0F);
    puts(buf);  i2cOLED_HstrX(0,0,buf);
    strcpy(buf," 00:00:00     ");
    RTC_HsetBCD(buf+1,DayTm[2],0);
    RTC_HsetBCD(buf+4,DayTm[1],0);
    RTC_HsetBCD(buf+7,DayTm[0],0);
    puts(buf);i2cOLED_HstrX(0,2,buf);
}
//---- Jコマンド (OLED表示切り替え))	"J"
void cmd_J(){
    ClockMd ^= 1;
    i2cOLED_Clr(0,7,0);
}
//---- Y(Year)コマンド(日付設定用)		"Yyy/MM/dd/w"
void i2cRTC_cmd_Y(char *str){
    uint8_t n;
    n = get_NumRev(DayTm+6, str+1, "/");
    if((n > 0)&&(n < 5)){
        RTC_writePrt(DayTm, 3, 4);
    }
}
//---- T(Time)コマンド(時刻設定用)	"Thh:mm:ss"
void i2cRTC_cmd_T(char *str){
    uint8_t n;
    n = get_NumRev(DayTm+2, str+1, ":");
    if((n > 0)&&(n < 4)){
        RTC_writePrt(DayTm, 0, 3);
    }
}
//---- 時刻を読出しOLEDに表示 
void OLED_Clock(){
    uint8_t t;
    RTC_readAll(DayTm,1);
    t = DayTm[0];
    if(Sec != t){		//  表示は秒単位
        if(ClockMd) RTC_prtOLED();
        Sec = t;
        IO_RA4_Toggle();
    }  
}
 
 |