本帖最后由 Elric_QZH 于 2015-8-30 09:11 编辑
最近学习GD32F105的板子,发现论坛例程不多,找了点例程分享
GD32 105R_STAR的后备寄存器(10个16位的寄存器)可以用于在关闭VDD时,保存20个字节的用户应用数据。RTC和后备寄存器不会被系统或电源复位源复位;当从待机模式唤醒时,也不会被复位。 楼主在本次试验中,采用的后备寄存器的BKP_DR1进行标志位的存储,供应用程序查询判断。如果标志位被更改,则进行RTC的初始化设置,否则跳过,代码如下: - /*****************************************************************************
- *函数名称:void RtcInit(uint16 *time)
- *函数功能: 按照默认值初始化实时时钟,秒值增加一次后产生中断.
- *入口参数:time:初始化时间指针
- *出口参数:
- *日期:2015 4 6
- *版本:V1.0
- *作者:yrj
- *****************************************************************************/
- void RtcInit(uint16 *time)
- {
- if(BKP_ReadBackupRegister(BKP_DR1)!=0xAAAA) /*未设置过,开始初始化*/
- {
- RTC_Configuration(); /*初始化RTC*/
- RTC_Set(time);/*默认时间 */
- BKP_WriteBackupRegister(BKP_DR1,0xAAAA );
- }
- else /*系统继续计时*/
- {
- if(RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET) /*电复位*/
- {}
- else if(RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET) /*管脚复位*/
- {}
- RCC_RTCCLKCmd(ENABLE); //开启备份寄存器时钟
- RTC_WaitForSynchro(); //
- RTC_WaitForLastTask(); //等待RTC寄存器操作完成
- RTC_ITConfig(RTC_IT_SEC,ENABLE); /*允许秒中断*/
- RTC_WaitForLastTask(); /*等待RTC寄存器操作完成*/
- }
- }
- 根据当前的实际时钟,对RTC的初始化设置,并使其产生1秒的周期定时,RTC初始化代码如下:
- /*
- ****************************************************************************
- *函数名称:u8 RTC_Set(uint16 *tim )
- *函数功能: 设置时钟,以1970年1月1日为基准//1970~2099年为合法年份
- *入口参数:
- *出口参数:
- *日期:2015 4 6
- *版本:V1.0
- *作者:yrj
- ****************************************************************************
- */
- /*平年的月份日期表*/
- const uint8 mon_table[12]={31,28,31,30,31,30,31,31,30,31,30,31};
- u8 RTC_Set(uint16 *tim )
- {
- uint16 syear=tim[0],smon=tim[1],sday=tim[2],hour=tim[3],min=tim[4],sec=tim[5];
- u16 t;
- u32 seccount=0;
- if(syear<2000||syear>2099)return 1;/*syear范围1970-2099,此处设置范围为2000-2099 */
- for(t=1970;t<syear;t++) /*把所有年份的秒钟相加*/
- {
- if(Is_Leap_Year(t))seccount+=31622400;/*闰年的秒钟数*/
- else seccount+=31536000; /*平年的秒钟数*/
- }
- smon-=1;
- for(t=0;t<smon;t++) /*把前面月份的秒钟数相加*/
- {
- seccount+=(u32)mon_table[t]*86400;/*月份秒钟数相加*/
- if(Is_Leap_Year(syear)&&t==1) seccount+=86400;/*闰年2月份增加一天的秒钟数*/
- }
- seccount+=(u32)(sday-1)*86400;/*把前面日期的秒钟数相加 */
- seccount+=(u32)hour*3600;/*小时秒钟数*/
- seccount+=(u32)min*60; /*分钟秒钟数*/
- seccount+=sec;/*最后的秒钟加上去*/
- /*设置时钟*/
- PWR_BackupAccessCmd(ENABLE); //使能后备寄存器
- RTC_WaitForLastTask();
- RTC_SetCounter(seccount); /*设置时钟*/
- RTC_WaitForLastTask();
- return 0;
- }
- 关于闰年平年的计算:
- /*
- ****************************************************************************
- *函数名称:u8 Is_Leap_Year(u16 year)
- *函数功能: //判断是否是闰年函数
- *入口参数:
- *出口参数:
- *日期:2015 4 6
- *版本:V1.0
- *作者:yrj
- ****************************************************************************
- */
- u8 Is_Leap_Year(u16 year)
- {
- if(year%4==0) /*必须能被4整除*/
- {
- if(year%100==0)
- {
- if(year%400==0) {return 1;}/*如果以00结尾,还要能被400整除*/
- else {return 0;}
- }
- else
- { return 1; }
- }
- else{ return 0; }
- }
- 在RTC的秒中断服务函数中,对年月日时分秒进行提取,用于万年历的显示,另外还可以根据具体的实际项目需要,进行设计开发,如每天0时定时开启风机等。。。
- /*
- ****************************************************************************
- *函数名称:void RtcException(void)
- *函数功能: RTC中断服务函数 在函数中刷新实时日期时间,并发送消息邮箱
- *入口参数:无
- *出口参数:无
- *日期:2015 4 6
- *版本:V1.0
- *作者:yrj
- ****************************************************************************
- */
- void RtcException(void)
- {
- if(RTC_GetITStatus(RTC_IT_SEC)==SET)
- {
- RTC_WaitForLastTask();
- RTC_ClearITPendingBit(RTC_IT_SEC);
- RTC_WaitForLastTask();
- /*读取当前时分秒*/
- RTC_Get(); /* 刷新当前时间 提取 年、月、日、时、分、秒*/
- if((0==timer.hour)&&(0==timer.min)&&(0==timer.sec))
- {
- //启动排风,或是设置闹钟。。。自由发挥喽
- }
- }
- }
- 在GD32 105R 的RTC中断中,对于RTC计数值中年月日时分秒的提取:
- /*
- ****************************************************************************
- *函数名称:u8 RTC_Get(void)
- *函数功能: 得到当前的时间 ,RTC2Timer
- *入口参数:
- *出口参数:
- *日期:2015 4 6
- *版本:V1.0
- *作者:yrj
- ****************************************************************************
- */
- 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++;
- }
- timer.w_year=temp1; /*得到年份*/
- temp1=0;
- while(temp>=28) /*超过了一个月*/
- {
- if(Is_Leap_Year(timer.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++;
- }
- timer.w_month=temp1+1; //得到月份
- timer.w_date=temp+1; //得到日期
- }
- temp=timecount%86400; //得到秒钟数
- timer.hour=temp/3600; //小时
- timer.min=(temp%3600)/60; //分钟
- timer.sec=(temp%3600)%60; //秒钟
- timer.week=RTC_Get_Week(timer.w_year,timer.w_month,timer.w_date); /*获取星期*/
-
- timer.year=timer.w_year-2000; //专为显示用年 14 7 22
- return 0;
- }
- 对于星期的判断:
- /*
- ****************************************************************************
- *函数名称:RTC_Get_Week(u16 year,u8 month,u8 day)
- *函数功能: 获得现在是星期几,输入公历日期得到星期(只允许1901-2099年)
- *入口参数:公历年月日
- *出口参数:星期号
- *日期:2015 4 6
- *版本:V1.0
- *作者:yrj
- ****************************************************************************
- */
- u8 const table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; /*月修正数据表*/
- u8 RTC_Get_Week(u16 year,u8 month,u8 day)
- {
- u16 temp2;
- u8 yearH,yearL;
- yearH=year/100; yearL=year%100;
- /*如果为21世纪,年份数加100 */
- if (yearH>19)yearL+=100;
- /* 所过闰年数只算1900年之后的 */
- temp2=yearL+yearL/4;
- temp2=temp2%7;
- temp2=temp2+day+table_week[month-1];
- if (yearL%4==0&&month<3)temp2--;
- return(temp2%7);
- }
|