5. 程序?qū)崿F(xiàn)
5.1 初始化
u8 RTC_Init(void)
{
u8 temp=0;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); //使能PWR和BKP外設(shè)時鐘
PWR_BackupAccessCmd(ENABLE); //使能后備寄存器訪問
if (BKP_ReadBackupRegister(BKP_DR1) != 0x5050) //從指定的后備寄存器中讀出數(shù)據(jù):讀出了與寫入的指定數(shù)據(jù)不相乎
{
BKP_DeInit(); //復(fù)位備份區(qū)域
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;//初始化時鐘失敗,晶振有問題
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //設(shè)置RTC時鐘(RTCCLK),選擇LSE作為RTC時鐘
RCC_RTCCLKCmd(ENABLE); //使能RTC時鐘
RTC_WaitForLastTask(); //等待最近一次對RTC寄存器的寫操作完成
RTC_WaitForSynchro(); //等待RTC寄存器同步
RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能RTC秒中斷
RTC_WaitForLastTask(); //等待最近一次對RTC寄存器的寫操作完成
RTC_EnterConfigMode();/// 允許配置
RTC_SetPrescaler(32767); //設(shè)置RTC預(yù)分頻的值
RTC_WaitForLastTask(); //等待最近一次對RTC寄存器的寫操作完成
RTC_Set(1972,1,2,1,1,1); //設(shè)置時間
RTC_ExitConfigMode(); //退出配置模式
BKP_WriteBackupRegister(BKP_DR1, 0X5050); //向指定的后備寄存器中寫入用戶程序數(shù)據(jù)
}
else//系統(tǒng)繼續(xù)計時
{
RTC_WaitForSynchro(); //等待最近一次對RTC寄存器的寫操作完成
RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能RTC秒中斷
RTC_WaitForLastTask(); //等待最近一次對RTC寄存器的寫操作完成
}
RTC_NVIC_Config();//RCT中斷分組設(shè)置
RTC_Get();//更新時間
return 0; //ok
}
static void RTC_NVICConfig(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn; //RTC全局中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占優(yōu)先級1位,從優(yōu)先級3位
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //先占優(yōu)先級0位,從優(yōu)先級4位
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能該通道中斷
NVIC_Init(&NVIC_InitStructure); //根據(jù)NVIC_InitStruct中指定的參數(shù)初始化外設(shè)NVIC寄存器
}
中斷服務(wù)函數(shù):
void RTC_IRQHandler(void)
{
if (RTC_GetITStatus(RTC_IT_SEC) != RESET)//秒鐘中斷
{
RTC_Get();//更新時間
}
if(RTC_GetITStatus(RTC_IT_ALR)!= RESET)//鬧鐘中斷
{
RTC_ClearITPendingBit(RTC_IT_ALR); //清鬧鐘中斷
}
RTC_ClearITPendingBit(RTC_IT_SEC|RTC_IT_OW); //清鬧鐘中斷
RTC_WaitForLastTask();
}
5.2 RTC部分實現(xiàn)
閏年判斷:
//判斷是否是閏年函數(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è)置時鐘
//把輸入的時鐘轉(zhuǎn)換為秒鐘
//以1970年1月1日為基準(zhǔn)
//1970~2099年為合法年份
//返回值:0,成功;其他:錯誤代碼.
//月份數(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
得到當(dāng)前時間:
//得到當(dāng)前的時間
//返回值:0,成功;其他:錯誤代碼.
u8 RTC_Get(void)
{
static u16 daycnt=0;
u32 timecount=0;
u32 temp=0;
u16 temp1=0;
timecount = RTC_GetCounter();
//timecount = 86400*4+88;
temp = timecount / 86400; //得到天數(shù)(秒鐘數(shù)對應(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; //減去一平年 ,還剩下的天數(shù)
temp1 ++;
}
calendar.w_year = temp1;//得到年份
temp1=0;
while(temp>=28)//28天,超過了最小的一個月
{
if(Is_Leap_Year(calendar.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++;
}
calendar.w_month = temp1+1; //得到月份
calendar.w_date = temp+1; //得到日期
}
temp = timecount%86400; //得到秒鐘數(shù)
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;
}
得到星期幾:
//獲得現(xiàn)在是星期幾
//功能描述:輸入公歷日期得到星期(只允許1901-2099年)
//輸入?yún)?shù):公歷年月日
//返回值:星期號
u8 RTC_GetWeek(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);
}
6. 附錄:
STM32 時鐘樹:
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。
舉報投訴
-
寄存器
+關(guān)注
關(guān)注
31文章
5294瀏覽量
119814 -
STM32
+關(guān)注
關(guān)注
2264文章
10854瀏覽量
354289 -
計數(shù)器
+關(guān)注
關(guān)注
32文章
2253瀏覽量
94278 -
RTC
+關(guān)注
關(guān)注
2文章
522瀏覽量
66227
發(fā)布評論請先 登錄
相關(guān)推薦
RTC是什么?RTC實時時鐘實驗
文章目錄前言一、RTC是什么?二、RTC實時時鐘實驗1.引入庫2.讀入數(shù)據(jù)總結(jié)前言前面我們說了OLED實驗,是一個比較好的顯示測試代碼的方法。現(xiàn)在我們
發(fā)表于 01-13 07:19
STM32CubeMX | 40 - 實時時鐘RTC的使用(日歷和鬧鐘)
STM32CubeMX | 40 - 實時時鐘RTC的使用(日歷和鬧鐘)
發(fā)表于 11-23 18:06
?19次下載
stm32f4 RTC實時時鐘解析
應(yīng)用最為廣泛的消費類電子產(chǎn)品之一。它為人們提供精確的實時時間,或者為電子系統(tǒng)提供精確的時間基準(zhǔn),目前實時時鐘芯片大多采用精度較高的晶體振蕩器作為時鐘源。對于STM32F的
發(fā)表于 12-04 18:06
?19次下載
STM32CubeMX學(xué)習(xí)筆記(14)——RTC實時時鐘使用
一、RTC簡介實時時鐘(RTC) 是一個獨立的 BCD 定時器/計數(shù)器。 RTC 提供具有可編程鬧鐘中斷功能的日歷時鐘/日歷。
發(fā)表于 12-05 21:06
?13次下載
STM32CubeMX系列|RTC實時時鐘
RTC實時時鐘1. RTC實時時鐘簡介2. 硬件設(shè)計3. 軟件設(shè)計3.1 STM32CubeMX
發(fā)表于 12-24 19:15
?16次下載
STM32學(xué)習(xí)筆記之RTC實時時鐘1
STM32 的實時時鐘(RTC)是一個獨立的定時器。 STM32 的 RTC 模塊擁有一組連續(xù)計數(shù)的計數(shù)器,在相應(yīng)軟件配置下,可提供
評論