calendar获取年月日_STM32实例RTC实时时钟实验获取RTC时间函数与中断服务函数

获取 RTC时间函数

    我们设置好 RTC 的初始时间,接着就需要获取 RTC 时间,具体代码如下:

//得到当前的时间//返回值:0,成功;其他:错误代码.u8 RTC_Get(void){static u16 daycnt=0;u32 timecount=0;u32 temp=0;u16 temp1=0;timecount=RTC_GetCounter();temp=timecount/86400; //得到天数(秒钟数对应的)if(daycnt!=temp)//超过一天了{daycnt=temp;temp1=1970; //从1970 年开始while(temp>=365){if(Is_Leap_Year(temp1))//是闰年{if(temp>=366)temp-=366;//闰年的秒钟数else {temp1++;break;}}else temp-=365; //平年temp1++;}calendar.w_year=temp1;//得到年份temp1=0;while(temp>=28)//超过了一个月{if(Is_Leap_Year(calendar.w_year)&&temp1==1)//当年是不是闰年/2月份{if(temp>=29)temp-=29;//闰年的秒钟数else break;}else{if(temp>=mon_table[temp1])temp-=mon_table[temp1];//平年else break;}temp1++;}calendar.w_month=temp1+1; //得到月份calendar.w_date=temp+1; //得到日期}temp=timecount%86400; //得到秒钟数calendar.hour=temp/3600; //小时calendar.min=(temp%3600)/60; //分钟calendar.sec=(temp%3600)%60; //秒钟calendar.week=RTC_Get_Week(calendar.w_year,calendar.w_month,calendar.w_date);//获取星期return 0;}

    该函数其实就是将存储在秒钟寄存器 RTC->CNTH 和 RTC->CNTL 中的秒钟数据(通过函数 RTC_SetCounter 设置)转换为真正的时间和日期。该代码还用到了一个 calendar 的结构体, calendar 是我们在 rtc.h 里面将要定义的一个时间结构体,用来存放时钟的年月日时分秒等信息。因为 STM32 的 RTC 只有秒钟计数器,而年月日时分秒这些需要我们自己软件计算。我们把计算好的值保存在calendar 里面,方便其他程序调用。

RTC中断服务函数

    在RTC 初始化的时候使能的是秒中断,所以需要编写一个秒中断函数,在中断函数中需要更新 RTC 时间并打印输出。代码如下:

void RTC_IRQHandler(void){if (RTC_GetITStatus(RTC_IT_SEC) != RESET)//秒钟中断{RTC_Get();//更新时间printf("RTCTime:%d-%d-%d %d:%d:%d\n",calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);//输出闹铃时间}if(RTC_GetITStatus(RTC_IT_ALR)!= RESET)//闹钟中断{RTC_ClearITPendingBit(RTC_IT_ALR); //清闹钟中断RTC_Get(); //更新时间printf("AlarmTime:%d-%d-%d %d:%d:%d\n",calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);//输出闹铃时间}RTC_ClearITPendingBit(RTC_IT_SEC|RTC_IT_OW); //清闹钟中断RTC_WaitForLastTask();}

    此函数很简单,首先判断中断类型,然后获取 RTC 时间并打印输出。

主函数

    编写好 RTC 初始化、时间设置获取函数及相应的中断函数后,接下来就可以编写主函数了,代码如下:

/***************************************************************** 函 数 名 : main* 函数功能 : 主函数* 输 入 : 无* 输 出 : 无*****************************************************************/int main(){u8 i=0;SysTick_Init(72);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组 分2 组LED_Init();USART1_Init(9600);RTC_Init();while(1){i++;if(i%20==0){led1=!led1;}delay_ms(10);}}

    主函数实现的功能很简单,首先调用之前编写好的硬件初始化函数,包括

SysTick 系统时钟, 中断分组, LED 初始化等。然后调用我们前面编写的 RTC_Init函数,初始化 RTC,如果是第一次初始化 RTC 会进入RTC 初值设置部分,只要保证 RTC后备域有电, 就不会重新给 RTC 赋初值。每经过一秒就会触发 RTC秒中断,获取 RTC 时间并打印输出。同时D1 指示灯间隔 200ms 闪烁。

    将工程程序编译后下载到开发板内,可以看到 D1 指示灯不断闪烁,表示程序正常运行。每过 1 秒进入 RTC 秒中断,同时串口打印输出 RTC 时间和日期。如果想在串口调试助手上看到输出信息,可以打开“串口调试助手”,首先勾选下标号 1 DTR 框,然后再取消勾选。这是因为此串口助手启动时会把系统复位住,通过 DTR 状态切换下即可。然后设置好波特率等参数后,串口助手上即会收到串口发送过来的信息。(串口助手上先勾选下标号1DTR 框,然后再取消勾选)如下图所示。

c9d9900d9593b5c844175c14a1732134.png

//实验说明:如果需要重新修改 RTC 初值时间,可以把“!”改成“=”RTC_Init 的 if(RTC_ReadBackupRegister(RTC_BKP_DR0)!=0xA0A0)

    这样就可以进入if 内的初始化语句,从而修改初值时间,修改完后要记得把符号改回来,否则下次复位又得重新设置初值。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值