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