S3C2440的RTC解析
S3C2440拥有一个实时时钟模块, 可以在当系统电源关闭后通过备用电池工作。RTC可以通过使用STRB/LDRB ARM操作发送8位二-十进制交换码(BCD)值数据给CPU。这些数据包括年、月、日、星期、时、分和秒的时间信息。RTC单元工作在外部32.768kHz晶振并且可以执行闹钟功能
实时时钟模块保存的数据是DCD码形式.
框图如下
可以看到,要使用实时时钟依靠以下几个寄存器
包含时钟使能和时钟复位(还有两个寄存器是测试模式,我们用不到)
关联着时钟节拍中断,也就是每增加1S发生一次中断
时钟中断,时钟的时分秒年月日都是可以进行使能的
接下来是时分秒年月日闹钟点设置
有六个就不一一列举了,意思是当到达这个时间点时发生中断,比如我设置23秒发生中断,那么每一分钟的23秒都会中断一次
还要注意,因为使用的是BCD计数,所以对时钟的读取,写入都要进行BCD码的转换,否则数据不对哦
详细查看代码
#include "rtc.h" char *week_num[7]={ "SUN","MON", "TUES", "WED", "THURS","FRI", "SAT" }; RTC_TIMER rtcTimer ; ALARM_TIMER alarmTimer ; /******************************** * * TICK中断 * *********************************/ void __irq RTC_tickHandler(void) { rSRCPND |= BIT_TICK;//清除源挂起 rINTPND |= BIT_TICK;//清除中断挂起 RTCGetValue(); printf("current year %d mouth %d day %d hour %d minute %d sec %d\r\n",rtcTimer.year,\ rtcTimer.month,rtcTimer.day,rtcTimer.hour,rtcTimer.minute,rtcTimer.second); } /******************************** * * alarm闹钟中断 * *********************************/ void __irq RTC_alarmHandler(void) { rSRCPND |= BIT_RTC;//清除源挂起 rINTPND |= BIT_RTC;//清除中断挂起 printf("alarm int happend\r\n"); } //rtc获取时间 void RTCGetValue(void) { u8 temp = 0,cover = 0; rRTCCON |= 0x01; //RTC读写使能,BCD时钟、计数器、无复位 temp = rBCDYEAR; temp = ((temp/16)*10)+(temp%16); rtcTimer.year = temp+YEAR_BASE; temp = rBCDMON; temp = ((temp/16)*10)+(temp%16); rtcTimer.month = temp; temp = rBCDDATE; temp = ((temp/16)*10)+(temp%16); rtcTimer.day = temp; temp = rBCDDAY; temp = ((temp/16)*10)+(temp%16); rtcTimer.weekDay = temp; temp = rBCDHOUR; temp = ((temp/16)*10)+(temp%16); rtcTimer.hour = temp; temp = rBCDMIN; temp = ((temp/16)*10)+(temp%16); rtcTimer.minute = temp; temp = rBCDSEC; temp = ((temp/16)*10)+(temp%16); rtcTimer.second = temp; rRTCCON &= ~(1<<0); //RTC读写禁止,BCD时钟、计数器、无复位 } void RTCSetValue(void) { u8 temp; rRTCCON |= 0x01; //RTC读写使能,BCD时钟、计数器、无复位 temp = rtcTimer.year - YEAR_BASE; temp = ((temp/10)*16)+(temp%10); rBCDYEAR = temp; temp = rtcTimer.month; temp = ((temp/10)*16)+(temp%10); rBCDMON = temp; temp = rtcTimer.day; temp = ((temp/10)*16)+(temp%10); rBCDDATE = temp; temp = rtcTimer.weekDay; temp = ((temp/10)*16)+(temp%10); rBCDDAY = temp; temp = rtcTimer.hour; temp = ((temp/10)*16)+(temp%10); rBCDHOUR = temp; temp = rtcTimer.minute; temp = ((temp/10)*16)+(temp%10); rBCDMIN = temp; temp = rtcTimer.second; temp = ((temp/10)*16)+(temp%10); rBCDSEC = temp; rRTCCON &= ~(1<<0); //RTC读写禁止,BCD时钟、计数器、无复位 } void RtcSetAlarm(void) { u8 temp; rRTCCON |= 0x01; //RTC读写使能,BCD时钟、计数器、无复位 temp = alarmTimer.year - YEAR_BASE; temp = ((temp/10)*16)+(temp%10); rALMYEAR = temp; temp = alarmTimer.month; temp = ((temp/10)*16)+(temp%10); rALMMON = temp; temp = alarmTimer.day; temp = ((temp/10)*16)+(temp%10); rALMDATE = temp; temp = alarmTimer.hour; temp = ((temp/10)*16)+(temp%10); rALMHOUR = temp; temp = alarmTimer.minute; temp = ((temp/10)*16)+(temp%10); rALMMIN = temp; temp = alarmTimer.second; temp = ((temp/10)*16)+(temp%10); rALMSEC = temp; rRTCALM = 0x41; //RTC闹钟控制寄存器,启动秒中断和总中断 rRTCCON &= ~(1<<0); //RTC读写禁止,BCD时钟、计数器、无复位 } void RtcInit(u8 tick) { rtcTimer.year = 2014; rtcTimer.month = 10; rtcTimer.day = 10; rtcTimer.weekDay = 5; rtcTimer.hour = 16; rtcTimer.minute = 34; rtcTimer.second = 52; alarmTimer.year = 2014; alarmTimer.month = 10; alarmTimer.day = 10; alarmTimer.weekDay = 5; alarmTimer.hour = 16; alarmTimer.minute = 34; alarmTimer.second = 52; rRTCCON = 0x01; rTICNT=(tick&0x7f)|0x80; //使能中断 RTCSetValue();//设置时间 RtcSetAlarm();//设置闹钟 //开启中断 pISR_RTC = (unsigned)RTC_alarmHandler; pISR_TICK=(unsigned)RTC_tickHandler; //中断函数入口地址 rSRCPND |= BIT_RTC;//清除源挂起 rINTPND |= BIT_RTC;//清除中断挂起 rINTMOD &= ~BIT_RTC;//设置中断模式为IRQ模式 rSRCPND |= BIT_TICK;//清除源挂起 rINTPND |= BIT_TICK;//清除中断挂起 rINTMOD &= ~BIT_TICK;//设置中断模式为IRQ模式 rINTMSK &= ~BIT_RTC; //开中断 rINTMSK &= ~BIT_TICK; //开中断 }
#ifndef __RTC_H #define __RTC_H #include "2440addr.h" #include "def.h" #include "uart0.h" #define YEAR_BASE 2000 typedef struct RTC_TIMER { u16 year; u8 month; u8 day; u8 weekDay; u8 hour; u8 minute; u8 second; }RTC_TIMER; typedef struct ALARM_TIMER { u16 year; u8 month; u8 day; u8 weekDay; u8 hour; u8 minute; u8 second; }ALARM_TIMER; extern struct RTC_TIMER rtcTimer; void RTCGetValue(void); void RTCSetValue(void); void RtcSetAlarm(void); void RtcInit(u8 tick); #endif