スパイス  組み込み制御装置の受注製作

自社標準仕様の製作
平成27年11月27日

 汎用の高速シリアル通信機能(19)  RTCの動作検証

 またしばらく更新が出来ませんでした。C++の言語機能習得と平行して基板の検証をしているので、どうしても脇道にそれる事が多くなります。
しかし新しい言語を覚えるのには試行錯誤がつきものです。目先の結果を求めるのではなく、正しい理解を求めることが最終的には近道になります。

 基板に実装したRTCは二種類あります。今回はバス接続型のRTC-4543を検証します。
RTC-4543は独自仕様のシリアルバスでCPUと通信を行います。特徴としては
 このRTCを実際の製品に使用するときには、RTCとCPUの間にPLDを挟んで、CPUからはSPIインタフェースで読み書きすることを考えています。
これでRTCによる追加のピンはCSとWRの二本で済みます。反面、プログラムはそれなりに面倒になります。通信の前後でデータのビット配置を上下で逆転する必要があり、また4ビット長のデータが含まれるため、データ途中からデータのバウンダリーを変更する必要があります。
今回はそこまでは行わず、通常のIOポートに接続した状態での操作を行います。

 プログラムは下記になります。C++での記述です。Cではコンパイルできません。以下の3つの関数で読み書きを行います。
 void init_4543();
 void read_4543(uint8_t* buf);
 void write_4543(const uint8_t* buf):
    注意:
 実際の接続によってIOポートの設定や初期化の初期値は変更が必要です。
 プログラム中のDELAYは1usだけ時間待ちするマクロです。リストには含まれていません。
私はハードウェアタイマを使って実装してありますが、面倒ならNop命令を使ったソフトウェアタイマで十分です。
#define RTC_DATA_OUT    LATCbits.LATC1
#define RTC_DATA_IN     PORTCbits.RC1

#define RTC_CLK         LATCbits.LATC2
#define RTC_WR          LATCbits.LATC3
#define RTC_CE          LATCbits.LATC4

#define RTC_DATA_DIR    TRISCbits.TRISC1
#define DIR_READ        1
#define DIR_WRITE       (!DIR_READ)


void init_4543()
{
    LATC = 0x0;
    TRISC = 0xe3;    //RTC_CLK, RTC_WR, RTC_CEを出力に
}

static void readRTC(uint8_t& data, const uint8_t limit)
{
    data = 0;
    uint8_t keta = 1;
    for(uint8_t i = 0; i < limit; i++){
        DELAY;
        RTC_CLK = 1;
        DELAY;
        if(RTC_DATA_IN)
            data += keta;
        keta *= 2;
        RTC_CLK = 0;
    }
}

#define read1byte(d)    readRTC(d, 8);
#define read4bit(d)     readRTC(d, 4);

void read_4543(uint8_t* buf)
{
    RTC_WR = 0;
    RTC_DATA_DIR = DIR_READ;
    DELAY;      //CEに対するセットアップ時間を確保
    RTC_CE = 1;
    read1byte(*buf++);      //秒
    read1byte(*buf++);      //分
    read1byte(*buf++);      //時
    read4bit(*buf++);       //曜日
    read1byte(*buf++);      //日
    read1byte(*buf++);      //月
    read1byte(*buf++);      //年
    RTC_CE = 0;
}

static void writeRTC(uint8_t data, uint8_t limit)
{
    for(uint8_t i = 0; i < limit; i++){
        RTC_DATA_OUT = (data & 0x01);
        data /= 2;
        DELAY;
        RTC_CLK = 1;
        DELAY;
        RTC_CLK = 0;
    }
}

#define write1byte(d)   writeRTC(d, 8);
#define write4bit(d)    writeRTC(d, 4);

void write_4543(const uint8_t* buf)
{
    RTC_WR = 1;
    RTC_DATA_DIR = DIR_WRITE;
    DELAY;      //CEに対するセットアップ時間を確保
    RTC_CE = 1;
    write1byte(*buf++);     //秒
    write1byte(*buf++);     //分
    write1byte(*buf++);     //時
    write4bit(*buf++);      //曜日
    write1byte(*buf++);     //日
    write1byte(*buf++);     //月
    write1byte(*buf++);     //年
    RTC_CE = 0;
}

目次へ  前へ  次へ