(2)创建rtc.c文件并输入以下代码。
#include "rtc.h"
/***************************************************
Name :RTC_Init
Fuction :RTC初始化
Parameter :None
Return :None
***************************************************/
void RTC_Init()
{
if( BKP->DR1!=0x5050 )
{
RCC->APB1ENR |= 1<<28 ; //使能PWR时钟
RCC->APB1ENR |= 1<<27 ; //使能BKP时钟,RTC校准在BKP相关寄存器中
PWR->CR |= 1<<8 ; //取消BKP相关寄存器写保护
RCC->BDCR |= 1<<16 ; //备份区域软复位
RCC->BDCR &= ~( 1<<16 ) ; //备份区域软复位结束
RCC->BDCR |= 1<<0 ; //开启外部低速振荡器
while( ( RCC->BDCR&0x02 )!=0x02 ) ; //等待外部时钟就绪
RCC->BDCR |= 1<<8 ; //LSI作为RTC时钟
RCC->BDCR |= 1<<15 ; //RTC时钟使能
while( !( RTC->CRL&( 1<<5 ) ) ) ; //等待RTC寄存器最后一次操作完成
while( !( RTC->CRL&( 1<<3 ) ) ) ; //等待RTC寄存器同步完成
RTC->CRH &= ~( 7<<0 ) ; //不允许中断,CRH寄存器低三位有效
while( !( RTC->CRL&( 1<<5 ) ) ) ; //等待RTC寄存器最后一次操作完成
RTC->CRL |= 1<<4 ; //进入配置模式
RTC->PRLH = 0 ;
RTC->PRLL = 32767 ; //设定分频值
RTC->CRL &= ~( 1<<4 ) ; //退出配置模式
while( !( RTC->CRL&( 1<<5 ) ) ) ; //等待RTC寄存器最后一次操作完成
BKP->DR1 = 0x5050 ;
}
else
{
while( !( RTC->CRL&( 1<<3 ) ) ) ; //等待RTC寄存器同步
while( !( RTC->CRL&( 1<<5 ) ) ) ; //等待RTC寄存器操作完成
}
}
/***************************************************
Name :Is_Leap_Year
Function :闰年判定
Parameter :
year:年份
Return :闰年
***************************************************/
u8 Is_Leap_Year( u16 year )
{
//必须能被4整除
if( year%4==0 )
{
if( year%100==0 )
{
if( year%400==0 )
return 1 ;
else
return 0 ;
}
else
return 1 ;
}
else
return 0;
}
/***************************************************
Name :RTC_Set_Time
Fuction :设置时间
Parameter :
year:年
month:月
date:日
hour:时
minute:分
second:秒
Return :None
***************************************************/
u8 mon_table[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } ;
void RTC_Set_Time( u8 year, u8 month, u8 date, u8 hour, u8 minute, u8 second )
{
u16 t ;
u32 seccount = 0 ;
//把所有年份的秒钟相加
for( t=1970; t2000; t++ )
{
if( Is_Leap_Year( t ) )
seccount += 31622400 ; //闰年的秒钟数
else
seccount += 31536000 ; //平年的秒钟数
}
month -= 1 ;
for( t=0; t//把前面月份的秒钟数相加
{
seccount += ( u32 )mon_table[ t ]*86400 ; //月份秒钟数相加
if( Is_Leap_Year( year+2000 )&&( t==1 ) )
seccount += 86400 ; //闰年2月份增加一天的秒钟数
}
seccount += ( date-1 )*86400 ; //把前面日期的秒钟数相加
seccount += hour*3600 ; //小时秒钟数
seccount += minute*60 ; //分钟秒钟数
seccount += second ; //最后的秒钟加上去
//设置时钟
RCC->APB1ENR |= 1<<28 ; //使能电源时钟
RCC->APB1ENR |= 1<<27 ; //使能备份时钟
PWR->CR |= 1<<8 ; //取消备份区写保护
RTC->CRL |= 1<<4 ; //允许配置
RTC->CNTL = seccount&0xFFFF ;
RTC->CNTH = seccount>>16 ;
RTC->CRL &= ~( 1<<4 ) ; //配置更新
while( ( RTC->CRL&0x20 )!=0x20 ) ; //等待RTC寄存器操作完成
RTC_Get_Time() ; //设置完之后更新一下数据
}
/***************************************************
Name :RTC_Get_Time
Fuction :获取时间
Parameter :None
Return :None
***************************************************/
RTC_Data RTC_Time;
void RTC_Get_Time()
{
u16 daycnt=0;
u32 timecount=0;
u32 temp=0;
u16 temp1=0;
//得到计数器中的值
timecount = RTC->CNTH ;
timecount <<= 16 ;
timecount += RTC->CNTL ;
//得到天数
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
break ;
}
else
temp -= 365; //平年
temp1 ++ ;
}
RTC_Time.year = temp1-2000 ; //得到年份
temp1 = 0 ;
//超过了一个月
while( temp>=28 )