?? rtc.c
字號(hào):
#include "sys.h"
#include "rtc.h"
#include "delay.h"
#include "usart.h"
tm timer;//時(shí)鐘結(jié)構(gòu)體
tm1 timer1;
//實(shí)時(shí)時(shí)鐘配置
//初始化RTC時(shí)鐘,同時(shí)檢測(cè)時(shí)鐘是否工作正常
//BKP->DR1用于保存是否第一次配置的設(shè)置
//返回0:正常
//其他:錯(cuò)誤代碼
void RTC_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn; //RTC全局中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //先占優(yōu)先級(jí)1位,從優(yōu)先級(jí)3位
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //先占優(yōu)先級(jí)0位,從優(yōu)先級(jí)4位
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能該通道中斷
NVIC_Init(&NVIC_InitStructure); //根據(jù)NVIC_InitStruct中指定的參數(shù)初始化外設(shè)NVIC寄存器
}
u8 RTC_Init(void)
{
//檢查是不是第一次配置時(shí)鐘
u8 temp=0;
RTC_NVIC_Config();
//if(BKP->DR1!=0X5050)//第一次配置
if (BKP_ReadBackupRegister(BKP_DR1) != 0x5050) //從指定的后備寄存器中讀出數(shù)據(jù):讀出了與寫入的指定數(shù)據(jù)不相乎
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); //使能PWR和BKP外設(shè)時(shí)鐘
PWR_BackupAccessCmd(ENABLE); //使能RTC和后備寄存器訪問
BKP_DeInit(); //將外設(shè)BKP的全部寄存器重設(shè)為缺省值
RCC_LSEConfig(RCC_LSE_ON); //設(shè)置外部低速晶振(LSE),使用外設(shè)低速晶振
while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) //檢查指定的RCC標(biāo)志位設(shè)置與否,等待低速晶振就緒
{
temp++;
delay_ms(10);
}
if(temp>=250)return 1;//初始化時(shí)鐘失敗,晶振有問題
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //設(shè)置RTC時(shí)鐘(RTCCLK),選擇LSE作為RTC時(shí)鐘
RCC_RTCCLKCmd(ENABLE); //使能RTC時(shí)鐘
RTC_WaitForSynchro(); //等待最近一次對(duì)RTC寄存器的寫操作完成
RTC_WaitForLastTask(); //等待最近一次對(duì)RTC寄存器的寫操作完成
RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能RTC秒中斷
RTC_WaitForLastTask(); //等待最近一次對(duì)RTC寄存器的寫操作完成
RTC_SetPrescaler(32767); //設(shè)置RTC預(yù)分頻的值
RTC_WaitForLastTask(); //等待最近一次對(duì)RTC寄存器的寫操作完成
RTC_Set(timer1.w_year1,timer1.w_month1,timer1.w_date1,timer1.hour1,timer1.min1,timer1.sec1); //設(shè)置時(shí)間
BKP_WriteBackupRegister(BKP_DR1, 0X5050); //向指定的后備寄存器中寫入用戶程序數(shù)據(jù)
}
else//系統(tǒng)繼續(xù)計(jì)時(shí)
{
RTC_WaitForSynchro(); //等待最近一次對(duì)RTC寄存器的寫操作完成
RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能RTC秒中斷
RTC_WaitForLastTask(); //等待最近一次對(duì)RTC寄存器的寫操作完成
}
RTC_Get();//更新時(shí)間
RCC_ClearFlag(); //清除RCC的復(fù)位標(biāo)志位
return 0; //ok
}
//RTC中斷服務(wù)函數(shù)
void RTC_IRQHandler(void)
{
if(RTC->CRL&0x0001)//秒鐘中斷
{
RTC_Get();//更新時(shí)間
}
if(RTC->CRL&0x0002)//鬧鐘中斷
{
RTC->CRL&=~(0x0002);//清鬧鐘中斷
//鬧鐘處理
}
RTC->CRL&=0X0FFA; //清除溢出,秒鐘中斷標(biāo)志
while(!(RTC->CRL&(1<<5)));//等待RTC寄存器操作完成
}
//判斷是否是閏年函數(shù)
//月份 1 2 3 4 5 6 7 8 9 10 11 12
//閏年 31 29 31 30 31 30 31 31 30 31 30 31
//非閏年 31 28 31 30 31 30 31 31 30 31 30 31
//輸入:年份
//輸出:該年份是不是閏年.1,是.0,不是
u8 Is_Leap_Year(u16 year)
{
if(year%4==0) //必須能被4整除
{
if(year%100==0)
{
if(year%400==0)return 1;//如果以00結(jié)尾,還要能被400整除
else return 0;
}else return 1;
}else return 0;
}
//設(shè)置時(shí)鐘
//把輸入的時(shí)鐘轉(zhuǎn)換為秒鐘
//以1970年1月1日為基準(zhǔn)
//1970~2099年為合法年份
//返回值:0,成功;其他:錯(cuò)誤代碼.
//月份數(shù)據(jù)表
u8 const table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; //月修正數(shù)據(jù)表
//平年的月份日期表
const u8 mon_table[12]={31,28,31,30,31,30,31,31,30,31,30,31};
u8 RTC_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec)
{
u16 t;
u32 seccount=0;
if(syear<1970||syear>2099)return 1;
for(t=1970;t<syear;t++) //把所有年份的秒鐘相加
{
if(Is_Leap_Year(t))seccount+=31622400;//閏年的秒鐘數(shù)
else seccount+=31536000; //平年的秒鐘數(shù)
}
smon-=1;
for(t=0;t<smon;t++) //把前面月份的秒鐘數(shù)相加
{
seccount+=(u32)mon_table[t]*86400;//月份秒鐘數(shù)相加
if(Is_Leap_Year(syear)&&t==1)seccount+=86400;//閏年2月份增加一天的秒鐘數(shù)
}
seccount+=(u32)(sday-1)*86400;//把前面日期的秒鐘數(shù)相加
seccount+=(u32)hour*3600;//小時(shí)秒鐘數(shù)
seccount+=(u32)min*60; //分鐘秒鐘數(shù)
seccount+=sec;//最后的秒鐘加上去
RTC_WaitForLastTask(); //等待最近一次對(duì)RTC寄存器的寫操作完成
RTC_SetCounter(seccount); //設(shè)置RTC計(jì)數(shù)器的值
RTC_WaitForLastTask(); //等待最近一次對(duì)RTC寄存器的寫操作完成
return 0;
}
//得到當(dāng)前的時(shí)間
//返回值:0,成功;其他:錯(cuò)誤代碼.
u8 RTC_Get(void)
{
static u16 daycnt=0;
u32 timecount=0;
u32 temp=0;
u16 temp1=0;
timecount=RTC->CNTH;//得到計(jì)數(shù)器中的值(秒鐘數(shù))
timecount<<=16;
timecount+=RTC->CNTL;
temp=timecount/86400; //得到天數(shù)(秒鐘數(shù)對(duì)應(yīng)的)
if(daycnt!=temp)//超過一天了
{
daycnt=temp;
temp1=1970; //從1970年開始
while(temp>=365)
{
if(Is_Leap_Year(temp1))//是閏年
{
if(temp>=366)temp-=366;//閏年的秒鐘數(shù)
else {temp1++;break;}
}
else temp-=365; //平年
temp1++;
}
timer.w_year=temp1;//得到年份
temp1=0;
while(temp>=28)//超過了一個(gè)月
{
if(Is_Leap_Year(timer.w_year)&&temp1==1)//當(dāng)年是不是閏年/2月份
{
if(temp>=29)temp-=29;//閏年的秒鐘數(shù)
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; //得到秒鐘數(shù)
timer.hour=temp/3600; //小時(shí)
timer.min=(temp%3600)/60; //分鐘
timer.sec=(temp%3600)%60; //秒鐘
timer.week=RTC_Get_Week(timer.w_year,timer.w_month,timer.w_date);//獲取星期
return 0;
}
//獲得現(xiàn)在是星期幾
//功能描述:輸入公歷日期得到星期(只允許1901-2099年)
//輸入?yún)?shù):公歷年月日
//返回值:星期號(hào)
u8 RTC_Get_Week(u16 year,u8 month,u8 day)
{
u16 temp2;
u8 yearH,yearL;
yearH=year/100; yearL=year%100;
// 如果為21世紀(jì),年份數(shù)加100
if (yearH>19)yearL+=100;
// 所過閏年數(shù)只算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);
}
//比較兩個(gè)字符串指定長(zhǎng)度的內(nèi)容是否相等
//參數(shù):s1,s2要比較的兩個(gè)字符串;len,比較長(zhǎng)度
//返回值:1,相等;0,不相等
u8 str_cmpx(u8*s1,u8*s2,u8 len)
{
u8 i;
for(i=0;i<len;i++)if((*s1++)!=*s2++)return 0;
return 1;
}
extern const u8 *COMPILED_DATE;//獲得編譯日期
extern const u8 *COMPILED_TIME;//獲得編譯時(shí)間
const u8 Month_Tab[12][3]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
//自動(dòng)設(shè)置時(shí)間為編譯器時(shí)間
void Auto_Time_Set(void)
{
u8 temp[3];
u8 i;
u8 mon,date;
u16 year;
u8 sec,min,hour;
for(i=0;i<3;i++)temp[i]=COMPILED_DATE[i];
for(i=0;i<12;i++)if(str_cmpx((u8*)Month_Tab[i],temp,3))break;
mon=i+1;//得到月份
if(COMPILED_DATE[4]==' ')date=COMPILED_DATE[5]-'0';
else date=10*(COMPILED_DATE[4]-'0')+COMPILED_DATE[5]-'0';
year=1000*(COMPILED_DATE[7]-'0')+100*(COMPILED_DATE[8]-'0')+10*(COMPILED_DATE[9]-'0')+COMPILED_DATE[10]-'0';
hour=10*(COMPILED_TIME[0]-'0')+COMPILED_TIME[1]-'0';
min=10*(COMPILED_TIME[3]-'0')+COMPILED_TIME[4]-'0';
sec=10*(COMPILED_TIME[6]-'0')+COMPILED_TIME[7]-'0';
RTC_Set(year,mon,date,hour,min,sec) ;
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -