1. RTC 基本介绍
RTC(Real Time Clock) 即实时时钟,它是一个可以为系统提供精确的时间基准的元器件,RTC一般采用精度较高的晶振作为时钟源,有些RTC为了在主电源掉电时还可以工作,需要外加电池供电
2. RTC 控制器
2.1 RTC的特点是:
-
RTC中存储的时间信息,都是以BCD码的形式存储的(用四位二进制表示一位十进制) 支持秒、分、小时、星期、星期、月、年。
-
支持闰年生成器
-
支持告警功能,即告警中断或下电唤醒。下电模式有:空闲、深度空闲、停止、深度停止和休眠。
-
支持计时计数器功能,即从下电模式(空闲、深度空闲、停止、深度停止和睡眠)中进行计时中断或唤醒。
-
支持独立电源引脚(RTCVDD)
-
支持毫秒滴答时定时器中断,支持RTOS工作。
2.2 RTC内部工作逻辑
2.3 RTC时钟频率
36.728khz
3. 实验:读取RTC 时间
注意我们的4412芯片RTC是没有独立电源的,所以读取RTC之前需要校验时钟
3.1 寄存器
3.2 配置寄存器
RTCCON RTC控制寄存器
[0] 使能RTC控制 =1 使能 =0 不使能
BCDYEAR 年
注意存储是以BCD吗存储的
[11:8] 百位
[7:4] 十位
[3:0] 个位
比如2023年 BCD码表示就是 0000 0010 0011 可以看到千位没有,其实千位几乎不用动,我们默认为 2 就行了
BCDMON 月
[4] 十位 注意这里只用了一bit表示十位的数 因为 01 02 03.....09 10 11 12 可以看到月的十位不是0就是1 所以1 bit足够了
[3:0] 个位
BCDDAY 日
[5:4] 十位 注意十位 只用了2bit 因为 十位上的数 不是 0 1 2 3 所以2bit足够了
[3:0] 个位
红色****警告 三星的这个芯片手册把星期和日的这个地址写反了 注意
BCDDAYWEEK 星期
[2:0] 个位 用了3bit 1 2 3 4 5 6 7 3bit足够了
BCDHOUR 小时
[5:4] 十位 注意 小时取 0 1 2 所以2bit够用了
[3:0] 个位
BCDMIN 分钟
[6:4] 十位 分钟的十位取值 0 1 2 3 4 5 3bit足够了
[3:0] 个位
BCDSEC 秒
[6:4] 十位 秒的十位取值 0 1 2 3 4 5 3bit足够了
[3:0] 个位
3.3 写代码
rtc_test----main.c
cpp
#include"exynos_4412.h"
#include"uart.h"
//读取RTC实时时钟
//延时
void delay(unsigned int msec)
{
unsigned int i,j;
while(msec --)
{
for(i=0;i<5;i++)
for(j=0;j<512;j++);
}
}
//初始化RTC
void rtc_init(unsigned int bcdyear,unsigned char bcdmon,
unsigned char bcdday,unsigned char bcdhour,
unsigned char bcdmin,unsigned char bcdsec,
unsigned char bcdweek){
//使能RTC控制器
RTCCON |= 0x1;
//设置年月日,时分秒
RTC.BCDSEC = bcdsec;
RTC.BCDMIN = bcdmin;
RTC.BCDHOUR = bcdhour;
//注意芯片手册的星期和地址是反的,它写错了,所以我们只好反着写
RTC.BCDWEEK = bcdday; //设置日
RTC.BCDDAY = bcdweek;//设置星期
RTC.BCDMON = bcdmon;
RTC.BCDYEAR = bcdyear;
RTCCON &= ~(1);// 关闭RTC控制器使能
}
typedef struct
{ //均是用BCD码表示
unsigned int bcdyear; // 3位十进制数有效
unsigned char bcdmon; // 1-12
unsigned char bcdday; // 1-31
unsigned char bcdhour; // 0-23
unsigned char bcdmin; // 0-59
unsigned char bcdsec; // 0-59
unsigned char bcdweek; // 1-7
}bcd_time_struct;
//读取RTC 时钟
void rtc_get_time(bcd_time_struct *bcd_struct)
{
if(bcd_struct != (void *)0)
{
bcd_struct->bcdyear = RTC.BCDYEAR;
bcd_struct->bcdmon = RTC.BCDMON;
bcd_struct->bcdday = RTC.BCDWEEK;//这里读出来的是日
bcd_struct->bcdhour = RTC.BCDHOUR;
bcd_struct->bcdmin = RTC.BCDMIN;
bcd_struct->bcdsec = RTC.BCDSEC;
bcd_struct->bcdweek = RTC.BCDDAY; //这里读出来的是星期
}
}
int main()
{
int a = 100;
uart_init();
printf("hello!a=%d\r\n",a);
//初始化RTC时钟
rtc_init(0x0233,0x12,0x13,0x18,0x34,0x12,0x3);
bcd_time_struct tm;
while(1){
rtc_get_time(&tm);
//打印实时时钟
//%03x 保留3位 如果不足三位用0来补充
printf("time:2%03x/%x/%x,%x:%x:%x,week:%x \r\n",tm.bcdyear,tm.bcdmon,
tm.bcdday,tm.bcdhour,tm.bcdmin,tm.bcdsec,tm.bcdweek);
delay(1000);
}
return 0;
}