电子说
TICNT
RTC计时器是一个递增计数器,并引发计时中断。TICNT寄存器包含32位目标计数值,并且CURTICCNT寄存器包含32位当前计时计数。如果当前滴答数达到TICNT中指定的目标值时,计时中断发生。
一秒钟计数的次数,由RTCCON[7:4]即TICCKSEL位决定:
TICCKSEL
因为我们的晶振频率也是32768,为方便计数,所以我们设置RTCCON[7:4]为0,开启滴答计时器需要设置RTCCON[8]位1:
TICEN
代码如下:
RTCCON = RTCCON & (~(0xf << 4)) | (1 << 8);
TICCNT = 32768;
RTCALM寄存器控制报警功能的启用和报警时间。请注意,RTCALM寄存器在断电模式下将同时生成ALARM_INT和ALARM_WK信号,但在正常模式下仅生成ALARM_INT信号。设置ALMEN[6]为1以产生ALARM_INT和ALARM_WK信号。
「举例:」
比如我们想每个小时的25分58秒产生一个中断信号,那我们需要设置RTCALM[1]、RTCALM[0]为1,同时设置RTCALM[6]为1以开启alarm功能,然后将BCD格式的时间设置到寄存器ALMSEC、ALMMIN。
代码如下:
RTCALM.ALM = (1 << 6)|(1 << 0)|(1 << 1);//使能bite:MINEN、SECEN
RTCALM.SEC = 0x58;
RTCALM.MIN = 0x25; //每小时25:58产生一次中断
alarm功能设置闹钟时间寄存器如下:
寄存器操作,采用BCD格式。
滴答计时器和alarm闹钟会产生内部中断信号,所以我们必须给这两个中断信号进行中断相关的初始化,并在中断处理函数中增加相应的处理代码。
参考datasheet 9.2.2 GIC Interrupt Table
rtc中断号
关于中断的初始化的寄存器配置,我们可以参考《11. 从0开始学ARM-基于Exynos4412中断详解、key程序编写》
区别是,key连接在了第一级中断控制器,而rtc的这两个中断则没有。清中断需要设置的寄存器如下:
「滴答计时器清中断:」
RTCINTP = RTCINTP | (1 << 0);
//清GIC中断标志位
ICDICPR.ICDICPR2 = ICDICPR.ICDICPR2 | (0x1 << 13);
//清cpu中断标志位
CPU0.ICCEOIR = CPU0.ICCEOIR&(~(0x3ff))|irq_num;
「alarm计时器清中断:」
RTCINTP = RTCINTP | (1 << 1);
//清GIC中断标志位
ICDICPR.ICDICPR2 = ICDICPR.ICDICPR2 | (0x1 << 12);
//清cpu中断标志位
CPU0.ICCEOIR = CPU0.ICCEOIR&(~(0x3ff))|irq_num;
「滴答计时器中断初始化:」
void rtc_tic(void)
{
RTCCON = RTCCON & (~(0xf << 4)) | (1 << 8);
TICCNT = 32768;
ICDDCR = 1; //使能分配器
ICDISER.ICDISER2 = ICDISER.ICDISER2 | (0x1 << 13); //使能相应中断到分配器
ICDIPTR.ICDIPTR19 = ICDIPTR.ICDIPTR19 & (~(0xff << 8))|(0x1 << 8); //选择CPU接口
CPU0.ICCPMR = 255; //中断屏蔽优先级
CPU0.ICCICR = 1; //使能中断到CPU
}
「alarm初始化」
void rtc_alarm(void)
{
RTCALM.ALM = (1 << 6)|(1 << 0)|(1 << 1);
RTCALM.SEC = 0x58;
RTCALM.MIN = 0x25; //每小时25:58产生一次中断
ICDDCR = 1; //使能分配器
//使能相应中断到分配器
ICDISER.ICDISER2 = ICDISER.ICDISER2 | (0x1 << 12);
//选择CPU接口
ICDIPTR.ICDIPTR19 = ICDIPTR.ICDIPTR19 & (~(0xff << 0))|(0x1 << 0);
CPU0.ICCPMR = 255; //中断屏蔽优先级
CPU0.ICCICR = 1; //使能中断到CPU
}
「中断处理函数」
void do_irq(void)
{
static int a = 1;
int irq_num;
irq_num = CPU0.ICCIAR&0x3ff; //获取中断号
switch(irq_num)
{
case 57: //按键key
printf("in the irq_handler\\n");
//清GPIO中断标志位
EXT_INT41_PEND = EXT_INT41_PEND |((0x1 << 1));
//清GIC中断标志位
ICDICPR.ICDICPR1 = ICDICPR.ICDICPR1 | (0x1 << 25);
break;
case 76:
printf("in the alarm interrupt!\\n");
RTCINTP = RTCINTP | (1 << 1);
//清GIC中断标志位
ICDICPR.ICDICPR2 = ICDICPR.ICDICPR2 | (0x1 << 12);
break;
case 77:
printf("in the tic interrupt!\\n");
RTCINTP = RTCINTP | (1 << 0);
//清GIC中断标志位
ICDICPR.ICDICPR2 = ICDICPR.ICDICPR2 | (0x1 << 13);
break;
}
//清cpu中断标志位
CPU0.ICCEOIR = CPU0.ICCEOIR&(~(0x3ff))|irq_num;
}
「其他代码:」
void rtc_init(void)
{
RTCCON = 1;//使能RTC控制写功能
RTC.BCDYEAR = 0x20;// 2020年11月11日, 15:24:50.以BCD码格式写入
RTC.BCDMON = 0x11;
RTC.BCDDAY = 0x11;
RTC.BCDHOUR = 0x15;
RTC.BCDMIN = 0x24;
RTC.BCDSEC = 0x50;
RTCCON = 0;//关闭RTC控制写功能
}
int main (void)
{ rtc_init();
rtc_alarm();
rtc_tic();
//每隔一秒打印以下当前时间
while(1)
{
printf("%x-%x-%x %x:%x:%x\\n",RTC.BCDYEAR,
RTC.BCDMON,
RTC.BCDDAY,
RTC.BCDHOUR,
RTC.BCDMIN,RTC.BCDSEC);
delay_ms(1000);
}
}
全部0条评论
快来发表一下你的评论吧 !