RTC是什么鬼?
RTC ---- REAL Time Clock----->实时时钟(年、月、日、星期、时、分、秒)
RTC的使用:
1)设置当前的时间
2)RTC可以自动的工作(嵌入式平台中,RTC也会不准)--->获取网络时间校正 --->GPS和北斗校时
3)可以设置闹钟时间,产生闹钟中断。
ARM中的RTC模块
ARM的电源原理图
既有电源供电,也有电池供电,但没电时就像电子表一样纽扣电池供电
S5PV210中RTC的特点
1、Supports BCD Number, that is Second, Minute, Hour, Day of the week, Day, Month, and Year.
BCD码(压缩型的BCD码)---> 32秒 --->second寄存器的内容 0x32
压缩型的BCD码是8位的,高4位是十位,第4位是各位。
2、Supports Leap Year Generator 支持闰年
3、Supports Alarm Function, that is ,Alarm-Interrupt or Wake-up from power down modes (idle, deep idle, stop,deep stop, and sleep) 支持闹钟功能,闹钟中断
4、Supports Tick Counter Function, that is Tick-Interrupt or Wake-up from power down modes (idle, deep idle,stop, deep stop, and sleep) 支持滴答功能,也就是每秒产生一次中断
5、Supports Independent Power Pin (RTCVDD) 支持独立电源,就是纽扣电池供电
6、Supports millisecond tick time interrupt for RTOS kernel time tick .
RTC的TICK时钟,可以提供给实时操作系统的内核,作为实时操作系统内核时钟。
RTC的寄存器
配置寄存器
闹钟的设置寄存器
RTC时间设置和读取的寄存器
1、中断判断寄存器---INTP
1、RTC的控制寄存器----RTCCON
1、滴答时钟计数器寄存器----TICCNT
例:设置tick timer的周期是500ms,则频率2Hz。
1)设置tick timer的clock频率:
RTCCON &= ~(0xf<<4); //tick timer的基准频率32768Hz
2)设置tick timer的计数值
TICNT = 32768/2; //tick timer的工作频率2Hz
基准频率/计数值 = 工作频率
基准频率/工作频率=计数值
4、RTC的闹钟寄存器---RTCALM
设置闹钟的比较时间。
四、RTC的程序
#include "main.h" #include "stdio.h" #include "int.h" extern unsigned int m; #define RTC_BASE (0xE2800000) #define rINTP (*((volatile unsigned long *)(RTC_BASE + 0x30))) #define rRTCCON (*((volatile unsigned long *)(RTC_BASE + 0x40))) #define rTICCNT (*((volatile unsigned long *)(RTC_BASE + 0x44))) #define rRTCALM (*((volatile unsigned long *)(RTC_BASE + 0x50))) #define rALMSEC (*((volatile unsigned long *)(RTC_BASE + 0x54))) #define rALMMIN (*((volatile unsigned long *)(RTC_BASE + 0x58))) #define rALMHOUR (*((volatile unsigned long *)(RTC_BASE + 0x5c))) #define rALMDATE (*((volatile unsigned long *)(RTC_BASE + 0x60))) #define rALMMON (*((volatile unsigned long *)(RTC_BASE + 0x64))) #define rALMYEAR (*((volatile unsigned long *)(RTC_BASE + 0x68))) #define rRTCRST (*((volatile unsigned long *)(RTC_BASE + 0x6c))) #define rBCDSEC (*((volatile unsigned long *)(RTC_BASE + 0x70))) #define rBCDMIN (*((volatile unsigned long *)(RTC_BASE + 0x74))) #define rBCDHOUR (*((volatile unsigned long *)(RTC_BASE + 0x78))) #define rBCDDATE (*((volatile unsigned long *)(RTC_BASE + 0x7c))) #define rBCDDAY (*((volatile unsigned long *)(RTC_BASE + 0x80))) #define rBCDMON (*((volatile unsigned long *)(RTC_BASE + 0x84))) #define rBCDYEAR (*((volatile unsigned long *)(RTC_BASE + 0x88))) #define rCURTICCNT (*((volatile unsigned long *)(RTC_BASE + 0x90))) #define rRTCLVD (*((volatile unsigned long *)(RTC_BASE + 0x94))) unsigned int alarm_flag = 1; //1---alarm没有工作; // 函数功能:把十进制num转成bcd码,譬如把56转成0x56,num-->dec static unsigned int num_2_bcd(unsigned int num) { // 第一步,把56拆分成5和6 // 第二步,把5和6组合成0x56 return (((num / 10)<<4) | (num % 10)); } #if 1 // 函数功能:把bcd码bcd转成十进制,譬如把0x56转成56 static unsigned int bcd_2_num(unsigned int bcd) { // 第一步,把0x56拆分成5和6 // 第二步,把5和6组合成56 return (((bcd & 0xf0)>>4)*10 + (bcd & (0x0f))); } #endif void rtc_alarm_init(void) { rALMMIN = num_2_bcd(1); //闹钟的分是1 rRTCALM |= 1<<1;//分钟匹配成功,产生闹钟中断 rRTCALM |= 1<<6; //打开闹钟中断功能 } void isr_rtc_alarm(void) //闹钟的ISR<--当RTC的分和ALARM分一致 { static int i = -1; printf("rtc alarm, i = %d...\r\n", i++); //debug GPD0DAT |= (1<<0); //beep 响 alarm_flag = 0; rINTP |= (1<<1); //清中断 intc_clearvectaddr(); } void rtc_tick_init(void) { rRTCCON &= ~(0xf<<4); //clock = 32768 rTICCNT = 26214;//32768/(1.25); printf("---rtc write time test 2016-9-13 2 15:59:03 ---\n\r"); struct rtc_time tWrite = { .year = 2016, .month = 9, .date = 13, .hour = 15, .minute = 59, .second = 3, .day = 2, }; rtc_set_time(&tWrite); rRTCCON |= (1<<8); //enable tick timer } void rtc_set_time(const struct rtc_time *p) { // 第一步,打开RTC读写开关 rRTCCON |= (1<<0); // 第二步,写RTC时间寄存器 rBCDYEAR = num_2_bcd(p->year - 2000); rBCDMON = num_2_bcd(p->month); rBCDDATE = num_2_bcd(p->date); rBCDHOUR = num_2_bcd(p->hour); rBCDMIN = num_2_bcd(p->minute); rBCDSEC = num_2_bcd(p->second); rBCDDAY = num_2_bcd(p->day); // 最后一步,关上RTC的读写开关 rRTCCON &= ~(1<<0); } void rtc_get_time(struct rtc_time *p) { // 第一步,打开RTC读写开关 rRTCCON |= (1<<0); // 第二步,读RTC时间寄存器 p->year = bcd_2_num(rBCDYEAR) + 2000; p->month = bcd_2_num(rBCDMON); p->date = bcd_2_num(rBCDDATE); p->hour = bcd_2_num(rBCDHOUR); p->minute = bcd_2_num(rBCDMIN); p->second = bcd_2_num(rBCDSEC); p->day = bcd_2_num(rBCDDAY); // 最后一步,关上RTC的读写开关 rRTCCON &= ~(1<<0); } void isr_rtc_tick(void) //Tick timer 的ISR (800ms) { if(alarm_flag == 0) m++; //每800ms 加一次1 if(m == 12) //10s { GPD0DAT &= ~(1<<0); //beep不响 m = 0; alarm_flag = 1; } struct rtc_time tRead; rtc_get_time(&tRead); printf("The time read is: %d:%d:%d:%d:%d:%d:%d.\r\n", tRead.year, tRead.month, tRead.date, tRead.hour, tRead.minute, tRead.second, tRead.day); rINTP |= (1<<0); //清中断 intc_clearvectaddr(); }