访问 RTC 模块的寄存器,首先要设RTCCON 的bit0 为1,CPU 通过读取RTC 模块中寄存器BCDSEC、BCDMIN、BCDHOUR、BCDDAY、BCDMON 和BCDYEAR 的值,得到当前的相应时间值,然而,由于多个寄存器依次读出,所以有可能产生错误。例如:用户依次读取年(1989)、月(12)、日(31)、时(23)、分(59)、秒(59)。当秒数为1 到59 时没有任何问题,但是当秒数为0 时,但前时间和日期就变成了1990 年1 月1 日0 时0 分。这种情况下(秒数为0),用户应该重新读取年份到分钟的值。
RTC 要由外部晶振提供32.768kHZ 的外部时钟。RTC 也可以提供闹钟定时的功能。RTC 单元可以使用后备电池通过管脚RTCVDD 供电。当系统关闭电源以后,CPU 和RTC 的接口电路被阻断,后备电池驱动晶体和BCD 计数器,从而达到最小的功耗。
中断周期按照下列公式计算:
Period=(n+1)/128 second
10.1 设置闹钟时间
void setRTCalm(U8 almyear,U8 almmon,U8 almdate,
U8 almhour,U8 almmin,U8 almsec)//年、月、日、时、分、秒
{ rRTCCON=0x0001;//RTCCON――实时时钟控制寄存器,RTCEN 位置1
// RTCEN 位,这一位用来使能RTC 模块时间寄存器的读写,在对RTC 的寄存器操作之前一定要把这一位置1
//在系统电源关闭的时候这一位要置0,用来防止对寄存器的误操作。
rALMYEAR = almyear;//ALMYEAR――闹钟年份数据寄存器
rALMMON = almmon;//ALMMON――闹钟月份寄存器
rALMDATE = almdate;//ALMDATE――闹钟日数据寄存器
rALMHOUR = almhour;//ALMHOUR――闹钟小时数据寄存器
rALMMIN = almmin;//ALMMIN――闹钟分钟数据寄存器
rALMSEC = almsec;//ALMSEC――闹钟秒数据寄存器
rRTCCON = 0; //disable RTC write
}
10.2 设置时钟时间
void setRTCtime(U8 wRTCyear,U8 wRTCmon,U8 wRTCdate,
U8 wRTCday,U8 wRTChour,U8 wRTCmin,U8 wRTCsec)//年、月、日、星期、时、分、秒
{
rRTCCON=0x01;
rBCDYEAR = wRTCyear;//BCDYEAR――BCD 年数据寄存器
rBCDMON = wRTCmon;//BCDMON――BCD 月数据寄存器
rBCDDATE = wRTCdate;//BCDDATE――BCD 日数据寄存器
rBCDDAY = wRTCday;//BCDDAY――BCD 星期数据寄存器
rBCDHOUR = wRTChour;//BCDGOUR――BCD 小时数据寄存器
rBCDMIN = wRTCmon;//BCDMIN――BCD 分数据寄存器
rBCDSEC = wRTCsec;//BCDSEC――BCD 秒数据寄存器
rRTCCON = 0x00; //disable RTC write
}
10.3 时钟和闹钟的开关操作
//开实时时钟
void OpenRtc(void)
{
pISR_TICK=(unsigned)Tick_Isr;
rTICNT=0xFF;//TICNT ――Tick 时钟计数寄存器,Tick time interrupt enable;Tick time count value=127,Period=(n+1)/128 second
EnableIrq(BIT_TICK);//open RTC TICK INTERRUPT
}
//关实时时钟
void CloseRtc(void)
{
rTICNT &= ~(1<<7);
DisableIrq(BIT_TICK);
}
//开闹钟函数
void OpenAlarm()
{
pISR_RTC = (unsigned)IsrAlarm;
ClearPending(BIT_RTC);//ClearPending(BIT_EINT0);//清零源中断挂起寄存器和中断挂起寄存器
rRTCALM = (0x7f); //RTCALM ――RTC 定时控制寄存器,enable alarm
EnableIrq(BIT_RTC);
}
//关闹钟函数
void CloseAlarm(void)
{
rRTCALM = 0; //disable alarm
DisableIrq(BIT_RTC);
}
10.4 利用实时时钟中断,显示当前时间
void __irq Tick_Isr(void)
{
Get_Rtc();
Uart_Printf("RTC TIME : %4x-%02x-%02x - %s –%02x:%02x:%02x\n",year,month,date,week[weekday],hour,min,sec);
ClearPending(BIT_TICK);
}
void Get_Rtc(void)
{
rRTCCON = 0x01; //RTC 读写使能,选择BCD 时钟、计数器,无复位,1/32768
if (rBCDYEAR == 0x99)
year = 0x1999;
else
year = 0x2000 + rBCDYEAR;
month=rBCDMON;
date=rBCDDATE;
weekday=rBCDDAY;
hour=rBCDHOUR;
min=rBCDMIN;
sec=rBCDSEC;
rRTCCON = 0x0; //RTC 读写禁止,选择BCD 时钟、计数器,无复位,1/32768
}
10.5 实时时钟闹钟中断
void __irq IsrAlarm(void)
{
ClearPending(BIT_RTC);
Uart_Printf("s3c244A RTCALM oucer \n");
enable_beep = 0;
CloseAlarm();
}
10.6 主程序
void xmain(void)
{
ChangeClockDivider(3,1);
ChangeMPllValue(127,2,1); //405MHZ
Isr_Init();
Uart_Init(0, 115200);
Uart_Select(0);
Uart_Printf("the main is running\n");
setRTCalm(06,04,15,1,5,1);//年、月、日、时、分、秒
setRTCtime(06,04,15,2,1,4,29);//年、月、日、星期、时、分、秒
OpenAlarm();
OpenRtc();
while(1);
}