RTCCを試してみる

投稿日 2013/07/05

PICのRTCC(リアルタイムクロック)を動かしてみました。

 

PICのいくつかのモデルにはRTCCが内蔵されています。

 

I2Cなどでインターフェースする外付けのRTCCも入手できますが、CPUチップに内蔵されていると配線不要で便利です。

 

32,768KHzのXTALを付ければ使用可能です。

 

今回は手を抜いてmicrochip社のDM240415 Accessory Development Starter Kit for Androidを使用しました。

 

日時の表示にはI2CのLCD AQM0802Aを使いました。

 

32,768KHzのXTALはSOSCにつなぎますので、SOSCをアクティブにする必要があります。

 

また、RTCC内のデータは書き込みロックがかかっているので、アンロックしてから日時を設定する必要があります。

 

日時の設定値はBCDですので、日時の数値をそのまま設定できて便利です。

RTCC_1.jpg

右側の温度センサーは関係ありません

 

アラームは、年から秒まで設定できますが、そのうちどこまでをアラームに使うのかはマスクで設定できるようになっています。秒、10秒、分、10分、時間、日、曜日、月、年ごとという形で設定できます。

 

これはアラームの設定日時のうち、どこまでを監視するかということです。

 

時間から年をマスクすると、10分毎にアラームが発生します。

 

すべてマスクしない場合は、1年に一回アラームが発生することになります。

 

アラームが発生すると割り込みが発生させることができます。

 

進み/遅れの調整も可能です。

RTCC_2.jpg

小型のI2C LCD AQM0802Aはちょうど8ケタなので便利です

 

以下はソースコードです。
lcd表示や、タイマの設定などの部分は省略しています。
rttc.cの内部はmicrochip社のソースを一部流用しています。
日時の設定は"2013/12/31 23:59:50"にしています。10秒後に年が改まります。
アラームは"0000/00/00 00:00:00"にし、1日毎のアラームになっています。
つまり、毎日0:0:0になるとアラームが発生します。
アラーム発生時割り込みがかかり、LED2を反転させます。
すこし進み気味なので RCFGCALbits.CALを-5にしてあります。

RTCC_3.jpg

使用したDM240415 CPUはPIC24FJ256GB110

 

関連記事:オンボード I2C 8x2 キャラクタLCD AQM0802A 

 

main.c
#include <p24fj256gb110>

 

_CONFIG2(FNOSC_PRIPLL & POSCMOD_HS & PLL_96MHZ_ON & PLLDIV_DIV2)
_CONFIG1(JTAGEN_OFF & FWDTEN_OFF & ICS_PGx2)

 

unsigned int date_time[4];

 

char date[] = "xx/xx/xx";
char time[] = "xx:xx:xx";

 

int main(void){

AD1PCFGL = 0xFFFF;

AD1PCFGH = 0xFFFF;

PMD1 = 0xFFFF;
PMD2 = 0xFFFF;
PMD3 = 0xFFFF;
PMD4 = 0xFFFF;
PMD5 = 0xFFFF;
PMD6 = 0xFFFF;

_I2C1MD = 0; //I2C1 on
_T1MD = 0; //Timer1 on

LATA = 0;

LATB = 0;
LATC = 0;
LATD = 0;
LATE = 0;

TRISA = 0;
TRISB = 0;

TRISC = 0;
TRISD = 0;
TRISE = 0;

LED1 = 0;
LED2 = 0;

I2C1BRG = 157; //100KHz I2C
I2C1CON = 0x8000; //enable I2C1

InitRTCC();
date_time[0] = 0x0013;
date_time[1] = 0x1231;
date_time[2] = 0x0223;
date_time[3] = 0x5950;
UpdateRTCC();

ALCFGRPTbits.ALRMPTR = 2;
ALRMVAL = 0x0000;
ALRMVAL = 0x0000;
ALRMVAL = 0x0000; //Alarm seting 0:0:0
ALCFGRPTbits.AMASK = 6; //Every Day
ALCFGRPTbits.ALRMPTR = 0;
ALCFGRPTbits.ARPT = 0;
ALCFGRPTbits.CHIME = 1;
ALCFGRPTbits.ALRMEN = 1; //Enable Alarm

lcd_init();

 

while(1){

Delay_ms(950);

LED1 = 1;
Delay_ms(50);
LED1 = 0;

ReadRTCC();
date[0] = ((date_time[0] >> 4) & 0x0F) + 0x30;
date[1] = (date_time[0] & 0x0F) + 0x30;
date[3] = ((date_time[1] >> 12) & 0x0F) + 0x30;
date[4] = ((date_time[1] >> 8) & 0x0F) + 0x30;
date[6] = ((date_time[1] >> 4) & 0x0F) + 0x30;
date[7] = (date_time[1] & 0x0F) + 0x30;

time[0] = ((date_time[2] >> 4) & 0x0F) + 0x30;
time[1] = (date_time[2] & 0x0F) + 0x30;
time[3] = ((date_time[3] >> 12) & 0x0F) + 0x30;
time[4] = ((date_time[3] >> 8) & 0x0F) + 0x30;
time[6] = ((date_time[3] >> 4) & 0x0F) + 0x30;
time[7] = (date_time[3] & 0x0F) + 0x30;
lcd_write(0, 0, date);
lcd_write(0, 1, time);

}
}

 

rtcc.c
#include <p24fj256gb110>

 

#define EnableSOSC() __builtin_write_OSCCONL(0X02)
#define SetRTCWREN() __builtin_write_RTCWEN()

 

void ReadRTCC(void);
void UpdateRTCC(void);
void InitRTCC(void);

 

extern unsigned int date_time[];

 

void InitRTCC(void){

_RTCCMD = 0;
EnableSOSC(); //Enable 32khz OSC
SetRTCWREN (); //Enable RTCC value registers write

 

//RTCC CONFIGURATION

RCFGCALbits.RTCOE = 0; //RTCC output disabled
RCFGCALbits.CAL=0b11111011; //RTCC Calibration -5
RCFGCALbits.RTCEN = 1; //RTCC Enabled
RCFGCALbits.RTCWREN = 0; //Disabled RTCC value write

PADCFG1bits.RTSECSEL = 0b11; //RTCC Seconds Clock is not selected for the RTCC pin

//Interrupt configuration
IFS3bits.RTCIF = 0; //Clear RTCC Alarm interrupt flag
IEC3bits.RTCIE = 1; //RTCC Alarm interrupt Enabled
IPC15bits.RTCIP = 4; //Set the interrupt priority 1

}

 

void UpdateRTCC(void){

SetRTCWREN(); //Enable RTCC register write

RCFGCALbits.RTCPTR = 0x3;
RTCVAL=date_time[0]; //update year
RTCVAL=date_time[1]; //update month,day
RTCVAL=date_time[2]; //update hour,day of week
RTCVAL=date_time[3]; //update the min,sec

RCFGCALbits.RTCWREN = 0; //Disabled RTCC value write

}

 

void ReadRTCC(void){

RCFGCALbits.RTCPTR = 0b11; //Setup pointer to RTCVAL
date_time[0]=RTCVAL; //read year
date_time[1]=RTCVAL; //read month,day
date_time[2]=RTCVAL; //read hour,day of week
date_time[3]=RTCVAL; //read min,sec

}

 

void attribute((interrupt, shadow,auto_psv)) _RTCCInterrupt(void) {

IFS3bits.RTCIF = 0; 
LED2 = !LED2;

}

 

(JF1VRR)