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();
}