裸机——RTC

1. 首先晓得RTC的基本知识

  RTC被划分到timer,但RTC是面向时间点的。

  如果按照定时器的思路去思考,那么应该考虑 时间周期 和 计数值。

  RTC 不是面向时间点的,所以略有不同,

  时间周期,RTC通过自己独立的晶振提供,并且晶振的频率都为 32.768KHZ

  计数值,RTC的计数值不是用来定时,而是用来计时,RTC记录 年 月 日 时 分 秒 星期。(其中年是有一个基准值,如2000)

  此外,RTC一般有独立的电池,保证掉电后继续计时。

 

  整理下思路:

  我们知道对于timer,我们需要设置时间周期和计数值,

  但是对于RTC,时间周期已经设置好了,所以只需要考虑计数值。

  

2.对RTC计数值的设置

  在数据手册可以找到这张图

  可以看出

RTC计数值分为 年 月 日 时 分 秒 星期,每个都是用独立的寄存器保存。

  所以对RTC计数值的设置就是通过 Control Register 设置那几个寄存器。

  此外还需要知道 RTC 的时间使用 BCD 码表示,所以涉及 十进制和BCD码的转换

  

  BCD码就是对数字编码,使用类似字符串的方式表示数字,如 0x56 的BCD码意义是 56.

转换方式:

static unsigned int num_2_bcd(unsigned int num)
{
    return (((num / 10)<<4) | (num % 10));
}

static unsigned int bcd_2_num(unsigned int bcd)
{
    return (((bcd & 0xf0)>>4)*10 + (bcd & (0x0f)));
}

 

  有了思路后,开始完成 读写RTC 时间的实验

 

#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)))



typedef struct rtc_time{
    unsigned int year;
    unsigned int mon;
    unsigned int day;
    unsigned int hour;
    unsigned int min;
    unsigned int sec;
    unsigned int date;
}rtc_time;


static unsigned int num_2_bcd(unsigned int num)
{
    return ((num / 10) << 4) | (num % 10);
}

static unsigned int bcd_2_num(unsigned int bcd)
{
    return ((bcd >> 4) * 10) + (bcd & 0x0f);
}

void rtc_set_time(rtc_time t)
{
    // 开启RTC设置
    rRTCCON |= 1 << 0;
    
    rBCDSEC = num_2_bcd(t.sec);
    rBCDMIN = num_2_bcd(t.min);
    rBCDHOUR = num_2_bcd(t.hour);
    rBCDDAY = num_2_bcd(t.day);
    rBCDDATE = num_2_bcd(t.date);
    rBCDMON = num_2_bcd(t.mon);
    rBCDYEAR = num_2_bcd(t.year);
    
    // 关闭RTC设置
    rRTCCON &= ~(1 << 0);
}

void rtc_get_time(rtc_time *t)
{
    // 开启RTC设置
    rRTCCON |= 1 << 0;
    
    t->sec =    bcd_2_num(rBCDSEC);
    t->min =   bcd_2_num(rBCDMIN);
    t->hour =   bcd_2_num(rBCDHOUR);
    t->day =   bcd_2_num(rBCDDAY);
    t->date =   bcd_2_num(rBCDDATE);
    t->mon =   bcd_2_num(rBCDMON);
    t->year =   bcd_2_num(rBCDYEAR);
    
    // 关闭RTC设置
    rRTCCON &= ~(1 << 0);    
}

 

从下面这张图中,还可以看出,RTC带有闹钟功能,能产生闹钟中断,现在来使用RTC闹钟功能

void rtc_sec_alarm()
{
    rALMSEC = num_2_bcd(13);  // 这样在每分钟的 13 秒都会发出ALRM中断
    
    rRTCALM |= (1 << 6) | (1 << 0);
}


void isr_rtc_sec()
{
    printf("isr_rtc_sec\n");
    
    intc_clearvectaddr();
    rINTP |= (1 << 1);
}

转载于:https://www.cnblogs.com/yangxinrui/p/9956934.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值