#申请开发板# 本帖最后由 qjp1988113 于 2020-9-26 09:45 编辑
今天做一下RTC实时时钟的实验。RTC其实本质上就是个32位计数器,我们想把预设的时间
计算成以s为单位的数量值,然后赋给RTC寄存器,就能完成时间的设定。
下面摘录官方的RTC的描述:
沁恒的数据手册也好,参考手册也好,只是重点列出了自家的一些改动过或者新增的地方。
其他的外设压根就没写,做事要做全套啊。对一些通用的外设一笔带过,甚至寄存器功能
表都不给出。
下面给出ST数据手册里面RTC的具体框图:
具体描述,让人看了一目了然:
其实,在我的经历中,在项目中一般用MCU自带的RTC真的很少。大家都喜欢用外部的独立的
RTC芯片。这里可能基于以下几点考虑:
1、有人说MCU的RTC不精准,在运行一段时间内时间会有一定的误差
2、对外部32K晶振品质依赖严重(其实这一点,对任何RTC来说都是需要的)
3、MCU整体的即便在休眠模式下,开着RTC的功耗也要比独立RTC芯片的大
这里就见仁见智了。
直接打开官方的RTC例程:
编译,下载,运行。
官方的例子,是实时每隔1S输出当前的时间。
函数还是写的挺通用的:
typedef struct
{
vu8 hour;
vu8 min;
vu8 sec;
vu16 w_year;
vu8 w_month;
vu8 w_date;
vu8 week;
}_calendar_obj;
_calendar_obj calendar;//日历结构体
u8 const table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; //月修正数据表
const u8 mon_table[12]={31,28,31,30,31,30,31,31,30,31,30,31};//平年的月份日期表
u8 AramClok**=0;//闹钟标志
/* Exported_Functions */
u8 RTC_Init(void);//初始化RTC,返回0,失败;1,成功;
u8 Is_Leap_Year(u16 year);//平年,闰年判断
u8 RTC_Alarm_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec);//设置闹钟时间
u8 RTC_Get(void);//更新时间
u8 RTC_Get_Week(u16 year,u8 month,u8 day);//获取当前第几周
u8 RTC_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec);//设置当前实际
运行结果截图:
具体的中断函数:
void RTC_IRQHandler(void)
{
// int i=0;
if (RTC_GetITStatus(RTC_IT_SEC) != RESET) /* Seconds interrupt */
{
RTC_Get();
}
if(RTC_GetITStatus(RTC_IT_ALR)!= RESET) /* Alarm clock interrupt */
{
RTC_ClearITPendingBit(RTC_IT_ALR);
printf("Alarm Time:%d-%d-%d %d:%d:%d
",calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);//输出闹铃时间
AramClok**=1;//闹钟标志置一
RTC_Get();
}
RTC_ClearITPendingBit(RTC_IT_SEC|RTC_IT_OW);
RTC_WaitForLastTask();
}
可以看到每一秒钟中断一次,中断执行了获取当前新时间。
官方屏蔽了闹钟的中断使能。我们测试一下闹钟的功能。
新增全局变量:u8 AramClok**=0;//闹钟标志
在main函数里面的RTC初始化代码后面加上,闹钟的时间并开启中断:
//RTC_Set(2019,10,8,13,58,55); //当前设定的时间
//设置闹钟
RTC_Alarm_Set(2019,10,8,13,59,55);//1分钟后闹钟
RTC_ITConfig(RTC_IT_ALR, ENABLE); //打开闹钟
中断函数的修改如上面,当发送闹钟中断,把标志:
AramClok**=1;//闹钟标志置一
设置PA0作为LED灯,模拟报警到时的闹铃响,
这里闹铃设定了响100*500ms=50s
当然你也可以一直让它响,不复位AramClok**标志,
然后通过一个外部中断(譬如按钮)来复位AramClok**标志。
然后在while循环里面查询闹钟标志执行对应的逻辑代码:
while(1){
if(AramClok**==1)
{
i=100;
while(i--)
{
if(i%2==0)
{
printf("year/month/day/week/hour/min/sec:
");
printf("%d-%d-%d %d %d:%d:%d
",calendar.w_year,calendar.w_month,calendar.w_date,
calendar.week,calendar.hour,calendar.min,calendar.sec );
}
else
{
PAout(0) ^= (1<<0);
}
Delay_Ms(500);
}
AramClok**=0;
}
else
{
Delay_Ms(1000);
printf("year/month/day/week/hour/min/sec:
");
printf("%d-%d-%d %d %d:%d:%d
",calendar.w_year,calendar.w_month,calendar.w_date,
calendar.week,calendar.hour,calendar.min,calendar.sec );
}
}
下载,断电,上电,观察串口输出:
LED闪烁50后停止。
实验到此结束!
|