time.h 以外の日時フォーマット:BCD (RTC)

RTC (Real Time Clock) でよく使用されるBCDデータと、time.h でおなじみの tm 構造体データを相互変換するサンプルコードです。

RTCとは

一言でいうと時計用のICです。
最初に設定した日時から、1秒周期で時間を刻んでいきます。
単に日時を読みだせるだけでなく、一般的にはタイマーやアラーム機能を内包しており、一定周期や指定した日時にシステムを起動するといった使い方を行ったりもします。

なお、物にもよりますが一般的にはあまり高精度ではありません。温度変化の影響も受けますし。
このため、より高精度に時間管理したい場合は別途GPSモジュールを用意して、GPS衛星からの日時情報で補正することなどを考える必要があります。

事前知識

BCD (bcd.h) については以下を参照ください。
suimin-busoku.hateblo.jp


サンプルコードにでてくる utime.h については、以下を参照ください。
suimin-busoku.hateblo.jp

bcdtime.h

#ifndef BCDTIMEH
#define BCDTIMEH

//------------------------------------------------------------------------------
// include
//------------------------------------------------------------------------------
#include <stdbool.h>
#include <stdint.h>
#include <time.h>

//------------------------------------------------------------------------------
// BCDフォーマット
//    uint8_t bcdtime[BCD_SIZE];
//
//    bcdtime[BCD_YEAR] = 年 (00~99 = 2000~2099年)
//    bcdtime[BCD_MON]  = 月 (1~12)
//    bcdtime[BCD_DAY]  = 日 (1~31)
//    bcdtime[BCD_WEEK] = 曜日 (※1)
//    bcdtime[BCD_HOUR] = 時 (0~23)
//    bcdtime[BCD_MIN]  = 分 (0~59)
//    bcdtime[BCD_SEC]  = 秒 (0~59)
//
//    ※1:RTCのメーカーで変わります
//          EPSON : 01h=日 / 02h=月 / 04h=火 / 08h=水 / 10h=木 / 20h=金 / 40h=土
//          RICHO : 0~6 = ユーザー定義
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// define
//------------------------------------------------------------------------------
enum
{
    BCD_SEC,
    BCD_MIN,
    BCD_HOUR,
    BCD_WDAY,    // なぜか間にあるお邪魔な曜日
    BCD_DAY,
    BCD_MON,
    BCD_YEAR,
    BCD_SIZE
};

//------------------------------------------------------------------------------
// function
//------------------------------------------------------------------------------
bool     Check_Bcdtime( const char bcdtime[] );
uint8_t *TmToBcdtime( const tm *tp );
tm      *BcdtimeToTm( const uint8_t bcdtime[] );

#endif

bcdtime.c

//******************************************************************************
// BCD日時処理
//******************************************************************************

//------------------------------------------------------------------------------
// include
//------------------------------------------------------------------------------
#include <stdbool.h>
#include <stdint.h>
#include <time.h>

#include "bcd.h"
#include "bcdtime.h"
#include "utime.h"

//******************************************************************************
// 日時が正しいかを確認
//
// input  : bcdtime[] = [in] BCD型
// return : true  = OK
//          false = NG
//******************************************************************************
bool Check_Bcdtime( const uint8_t bcdtime[] )
{
    bool result;
    tm  *tp;

    // フォーマットごとに処理を実装していくのは不具合の基になるので、
    // tm型の関数を流用する
    tp     = BcdtimeToTm( bcdtime );
    result = Check_Tm( tp );

    return result;
}
//******************************************************************************
// tm型をBCD型に変換
//
// input  : *tp = [in] tm型
// return : BCD型
//******************************************************************************
uint8_t *TmToBcdtime( const tm *tp )
{
    static uint8_t bcdtime[BCD_SIZE];

    bcdtime[BCD_YEAR] = BinToBcd1( tp->tm_year - 100 );
    bcdtime[BCD_MON]  = BinToBcd1( tp->tm_mon + 1 );
    bcdtime[BCD_DAY]  = BinToBcd1( tp->tm_mday );
    bcdtime[BCD_HOUR] = BinToBcd1( tp->tm_hour );
    bcdtime[BCD_MIN]  = BinToBcd1( tp->tm_min );
    bcdtime[BCD_SEC]  = BinToBcd1( tp->tm_sec );

    // RICHO系で 0=日曜日 とした場合
    bcdtime[BCD_WDAY] = tp->tm_wday;

    return bcdtime;
}
//******************************************************************************
// BCD型をtm型に変換
//
// input  : bcdtime[] = [in] BCD型
// return : *tm型
//******************************************************************************
tm *BcdtimeToTm( const uint8_t bcdtime[] )
{
    static tm t;

    t.tm_year = BcdToBin1( bcdtime[BCD_YEAR] ) + 100;
    t.tm_mon  = BcdToBin1( bcdtime[BCD_MON] ) - 1;
    t.tm_mday = BcdToBin1( bcdtime[BCD_DAY] );
    t.tm_hour = BcdToBin1( bcdtime[BCD_HOUR] );
    t.tm_min  = BcdToBin1( bcdtime[BCD_MIN] );
    t.tm_sec  = BcdToBin1( bcdtime[BCD_SEC] );

    // RICHO系で 0=日曜日 とした場合
    t.tm_wday = bcdtime[BCD_WDAY];

    return &t;
}