Cライブラリ「WiringPi」を用いて、Raspberry PIでRTC-8564NBのアラーム機能とタイマー機能を持つプログラム作成を作成しました。RTC-8564NBの時計機能とクロック出力機能は「Raspberry PIでRTC-8564NBの時計プログラムの作成 」に示します。
RTC-8564NBが持つ機能のうち、アラーム機能とタイマー機能を実装します。これらの機能は,RTC-8564NBに内蔵されているレジスタを設定することにより実現可能です。このRTC-8564NBはI2Cで制御するので、Cライブラリ「WiringPi」のI2Cを使用します。
アラーム機能は、時間になると通知する機能で、プログラムでは、現在のカレンダ時刻から一分後にアラームを通知するように作成しました。アラーム通知は、RTC-8564NBのレジスタに割り当てられているAlarmFlagが「1」になることにより知ることができます。
タイマー機能は、一定時間になると通知する機能で、プログラムでは、1秒ごとに通知するように作成しました。通知は、RTC-8564NBのレジスタに割り当てられているTimerFlagが「1」になることにより知ることができます。
rtc_int.c
#include <stdio.h>
#include <wiringPi.h>
#include <wiringPiI2C.h>
// I2C Address
#define RTCS8564_I2C_ADDRESS 0x51
// Registers
#define RTC8564_CONTROL1 0x00
#define RTC8564_CONTROL2 0x01
#define RTC8564_SECONDS 0x02
#define RTC8564_MINUTES 0x03
#define RTC8564_HOURS 0x04
#define RTC8564_DAYS 0x05
#define RTC8564_WEEKDAYS 0x06
#define RTC8564_MONTH_CENTURY 0x07
#define RTC8564_YEARS 0x08
#define RTC8564_MINUTE_ALARM 0x09
#define RTC8564_HOUR_ALARM 0x0a
#define RTC8564_DAY_ALARM 0x0b
#define RTC8564_WEEKDAY_ALARM 0x0c
#define RTC8564_CLKOUT_FREQUENCY 0x0d
#define RTC8564_TIMER_CONTROL 0x0e
#define RTC8564_TIMER 0x0f
// Control1 register
#define RTC8564_STOP_BIT 0x20
// Control2 register
#define RTC8564_TIE_BIT 0x01
#define RTC8564_AIE_BIT 0x02
#define RTC8564_TF_BIT 0x04
#define RTC8564_AF_BIT 0x08
#define RTC8564_TITP_BIT 0x10
// Calendar registers
#define RTCS8564_CAL_VL 0x80
#define RTCS8564_CAL_CENTURY 0x80
// Alarm register
#define RTC8564_AE_NONE 0x00
#define RTC8564_AE_MINUTE 0x01
#define RTC8564_AE_HOUR 0x02
#define RTC8564_AE_DAY 0x04
#define RTC8564_AE_WEEKDAY 0x08
#define RTC8564_AE_ALL (RTC8564_AE_MINUTE | RTC8564_AE_HOUR | RTC8564_AE_DAY | RTC8564_AE_WEEKDAY)
#define RTC8564_AE_BIT 0x80
// Timer control register
#define RTC8564_CLK_244US 0x00
#define RTC8564_CLK_15MS 0x01
#define RTC8564_CLK_1SEC 0x02
#define RTC8564_CLK_1MIN 0x03
#define RTC8564_TE_BIT 0x80
// Clkout frequency register
#define RTC8564_CLKOUT_32768HZ 0x00
#define RTC8564_CLKOUT_1024HZ 0x01
#define RTC8564_CLKOUT_32HZ 0x02
#define RTC8564_CLKOUT_1HZ 0x03
#define RTCS8564_FE_BIT 0x80
// date and time
struct dateTime {
char second; // 0-59
char minute; // 0-59
char hour; // 0-23
char day; // 1-31
char month; // 1-12
char year; // 00-199
char weekday; // 0(Sun)-6(Sat)
};
// alarm
struct alarmTime {
char minute; // 0-59
char hour; // 0-23
char day; // 1-31
char weekday; // 0(Sun)-6(Sat)
};
static int dev;
static int init_dev(void)
{
if ((dev = wiringPiI2CSetup(RTCS8564_I2C_ADDRESS)) == -1)
{
return 1 ;
}
return 0;
}
void setRegisters(char address, int numData, char *data) {
char adr;
int i;
adr = address;
for (i = 0; i < numData; i++) {
wiringPiI2CWriteReg8 (dev, adr, *data);
// printf("Write adr:%x data:%x \n",adr,*data);
adr ++;
data ++;
}
}
void getRegisters(char address, int numData, char *data) {
char adr;
int i;
adr = address;
for (i = 0; i < numData; i++) {
*data = wiringPiI2CReadReg8 (dev, adr);
// printf("Read adr:%x data:%x \n",adr,*data);
adr ++;
data ++;
}
}
int decimalToBCD(int decimal) {
return (((decimal / 10) << 4) | (decimal % 10));
}
int BCDToDecimal(int bcd) {
return ((bcd >> 4) * 10 + (bcd & 0x0f));
}
void setAlarm(char enableFlags, struct alarmTime *at, char interruptEnable) {
char control2;
char data[4];
// Read Control2 register
getRegisters(RTC8564_CONTROL2, 1, &control2);
control2 &= (~RTC8564_AIE_BIT);
setRegisters(RTC8564_CONTROL2, 1, &control2);
data[0] = (enableFlags & RTC8564_AE_MINUTE) ? decimalToBCD(at->minute) : RTC8564_AE_BIT;
data[1] = (enableFlags & RTC8564_AE_HOUR) ? decimalToBCD(at->hour) : RTC8564_AE_BIT;
data[2] = (enableFlags & RTC8564_AE_DAY) ? decimalToBCD(at->day) : RTC8564_AE_BIT;
data[3] = (enableFlags & RTC8564_AE_WEEKDAY) ? decimalToBCD(at->weekday) : RTC8564_AE_BIT;
setRegisters(RTC8564_MINUTE_ALARM, 4, data);
if (interruptEnable) {
control2 |= RTC8564_AIE_BIT;
} else {
control2 &= ~RTC8564_AIE_BIT;
}
setRegisters(RTC8564_CONTROL2, 1, &control2);
}
void getAlarm(char *enableFlags, struct alarmTime *at) {
char data[4];
int i;
getRegisters(RTC8564_MINUTE_ALARM, 4, data);
at->minute = BCDToDecimal(data[0] & 0x7f);
at->hour = BCDToDecimal(data[1] & 0x3f);
at->day = BCDToDecimal(data[2] & 0x3f);
at->weekday = BCDToDecimal(data[3] & 0x07);
*enableFlags = 0;
for (i = 0; i < 4; i++) {
if (!(data[i] & RTC8564_AE_BIT)) {
*enableFlags |= (1 << i);
}
}
}
int getAlarmFlag() {
char control2;
getRegisters(RTC8564_CONTROL2, 1, &control2);
return (control2 & RTC8564_AF_BIT) ? 1 : 0;
}
void clearAlarmFlag() {
char control2;
getRegisters(RTC8564_CONTROL2, 1, &control2);
control2 &= ~RTC8564_AF_BIT;
setRegisters(RTC8564_CONTROL2, 1, &control2);
}
void setTimer(char enableFlag, char repeatMode, char clockMode, char counter, char interruptEnable) {
char control2;
char data[4];
data[0] = 0;
setRegisters(RTC8564_TIMER_CONTROL, 1, data);
if (enableFlag) {
getRegisters(RTC8564_CONTROL2, 1, &control2);
control2 &= ~(RTC8564_TITP_BIT | RTC8564_TF_BIT | RTC8564_TIE_BIT);
setRegisters(RTC8564_CONTROL2, 1, &control2);
if (repeatMode) {
control2 |= RTC8564_TITP_BIT;
}
if (interruptEnable) {
control2 |= RTC8564_TIE_BIT;
}
setRegisters(RTC8564_CONTROL2, 1, &control2);
setRegisters(RTC8564_TIMER, 1, &counter);
clockMode |= RTC8564_TE_BIT;
setRegisters(RTC8564_TIMER_CONTROL, 1, &clockMode);
}
}
int getTimerFlag() {
char control2;
getRegisters(RTC8564_CONTROL2, 1, &control2);
return (control2 & RTC8564_TF_BIT) ? 1 : 0;
}
void clearTimerFlag() {
char control2;
getRegisters(RTC8564_CONTROL2, 1, &control2);
control2 &= ~RTC8564_TF_BIT;
setRegisters(RTC8564_CONTROL2, 1, &control2);
}
int main(int argc, char **argv) {
char control[2];
char data[2];
struct alarmTime set = {1, 0, 0, 0}; // Alarm : 1 minite
struct alarmTime get ;
char enableFlags;
int count ;
char control2;
if(init_dev()==1) return 1;
control[0] = RTC8564_STOP_BIT;
control[1] = 0x00;
sleep(1);
setRegisters(RTC8564_CONTROL1, 2, control);
control[0] = 0x00;
setRegisters(RTC8564_CONTROL1, 1, control);
getRegisters(RTC8564_MINUTES, 1, data);
set.minute = BCDToDecimal(data[0] & 0x7f) + 1;
setAlarm(RTC8564_AE_MINUTE, &set, 0); // Setup alarm 1 minite
count = 5;
while(count){
count--;
getAlarm(&enableFlags, &get);
printf("Alarm minute:%d hour:%d day:%d weekday:%d enableFlags:%x getAlarmFlag:%x\n",
get.minute, get.hour,get.day,get.weekday,enableFlags,getAlarmFlag());
sleep(20);
}
setTimer(1, 1, RTC8564_CLK_1SEC, 5, 1); // Setup timer interrupt.5 sec
count = 5;
while(count--){
printf("Timer getTimerFlag:%x\n", getTimerFlag());
sleep(2);
}
return 0;
}
コンパイル・リンクは次のコマンドで実行します。
# gcc -o rtc_int rtc_int.c -lwiringPi
出来上がったプログラムを次のコマンドで実行します。
# sudo ./rtc_int
実行結果を次に示します。アラームは、時間が経過するとAlarmFlagが設定されていることが確認できます。タイマーも同様に時間が経過するとTimerFlagが設定されていることが確認できます。
# ./rtc_int Alarm minute:40 hour:0 day:0 weekday:0 enableFlags:1 getAlarmFlag:0 Alarm minute:40 hour:0 day:0 weekday:0 enableFlags:1 getAlarmFlag:0 Alarm minute:40 hour:0 day:0 weekday:0 enableFlags:1 getAlarmFlag:0 Alarm minute:40 hour:0 day:0 weekday:0 enableFlags:1 getAlarmFlag:1 Alarm minute:40 hour:0 day:0 weekday:0 enableFlags:1 getAlarmFlag:1 Timer getTimerFlag:0 Timer getTimerFlag:0 Timer getTimerFlag:0 Timer getTimerFlag:1 Timer getTimerFlag:1