簡(jiǎn)單初始化STM32的RTC
要使用 RTC,一般來(lái)說(shuō)也順帶地使用上后備寄存器—這是因?yàn)镽TC 是一個(gè)簡(jiǎn)單的秒中斷
定時(shí)器,年月日時(shí)分秒的信息必須要找個(gè)地方能掉電保存才有意義.STM32 的備份寄存器(BKP)是42個(gè)16位的寄存器,可用來(lái)存儲(chǔ)84個(gè)字節(jié)的用戶應(yīng)用程序數(shù)據(jù)。他們處在備份域里,當(dāng)VDD電源被切斷,他們?nèi)匀挥蒝BAT維持供電。當(dāng)系統(tǒng)在待機(jī)模式下被喚醒,或系統(tǒng)復(fù)位或電源復(fù)位時(shí),他們也不會(huì)被復(fù)位。 此外,BKP控制寄存器用來(lái)管理侵入檢測(cè)和RTC校準(zhǔn)功能。 復(fù)位后,對(duì)備份寄存器和RTC的訪問(wèn)被禁止,并且備份域被保護(hù)以防止可能存在的意外的寫操作它是用后備電池供電的,只要配置好后,即使系統(tǒng)關(guān)電,32768 的
晶振和后備寄存器的數(shù)據(jù)也會(huì)得以維持.而且RTC的計(jì)數(shù)器是會(huì)繼續(xù)秒遞增的.那么要配
置RTC,就必須開(kāi)放以下東西:
#include "stm32f10x_bkp.h" 這個(gè)是后備寄存器
#include "stm32f10x_pwr.h" 電源管理
#include "stm32f10x_rtc.h" RTC庫(kù)
開(kāi)始吧.....先是中斷
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure on
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/*RTC*/
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;//RTC全局中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
然后設(shè)置 RTC
#include "STM32Lib\stm32f10x.h"
#include "hal.h"
static u8 RTC_Blank=0;
/***********************************
**函數(shù)名:RTC_Configuration
**功能:RTC設(shè)置
**注意事項(xiàng):要根據(jù)是否是第一次設(shè)置,才進(jìn)入下面的RTC設(shè)定
判斷是否第一次設(shè)置,只需要判斷RTC后備寄存器1的值是否為事先寫入的0XA5A5,如果不是,則
RTC是第一次上電,需要初始化RTC,并把實(shí)際時(shí)間轉(zhuǎn)化為RTC計(jì)數(shù)值,這里沒(méi)有設(shè)置實(shí)際時(shí)間,只是簡(jiǎn)單地初始化了RTC
************************************/
void RTC_Configuration(void)
{
/*PWR時(shí)鐘(電源控制)與BKP時(shí)鐘(RTC后備寄存器)使能*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
/*使能RTC和后備寄存器訪問(wèn)*/
PWR_BackupAccessCmd(ENABLE);
/*從指定的后備寄存器(BKP_DR1)中讀出數(shù)據(jù)*/
if(BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5)
{
/* 將外設(shè)BKP的全部寄存器重設(shè)為缺省值 */
BKP_DeInit();
/*啟用 LSE(外部低速晶振)*/
RCC_LSEConfig(RCC_LSE_ON);
/*等待外部晶振震蕩 需要等待比較長(zhǎng)的時(shí)間*/
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
/*使用外部晶振32.768K作為RTC時(shí)鐘*/
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
//允許RTC
RCC_RTCCLKCmd(ENABLE);
//等待RTC寄存器同步 原因下文說(shuō)明
RTC_WaitForSynchro();
//等待最近一次對(duì)RTC寄存器的寫操作完成
RTC_WaitForLastTask();
//允許RTC的秒中斷(還有鬧鐘中斷和溢出中斷可設(shè)置)
RTC_ITConfig(RTC_IT_SEC, ENABLE);
//又是等待上一次對(duì)RTC寄存器的寫操作完成
RTC_WaitForLastTask();
//32768晶振預(yù)分頻值是32767,不過(guò)一般來(lái)說(shuō)晶振都不那么準(zhǔn)
RTC_SetPrescaler(32776);//如果需要校準(zhǔn)晶振,可修改此分頻值
RTC_WaitForLastTask();
//寫入RTC后備寄存器1 0xa5a5
BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);
RTC_Blank=1;/*這個(gè)標(biāo)志代表RTC是沒(méi)有預(yù)設(shè)的(或者說(shuō)是沒(méi)有上紐扣電池) 用串口呀啥的輸出來(lái)。*/
}
//如果RTC已經(jīng)設(shè)置
else
{
//等待RTC與APB同步
RTC_WaitForSynchro();
RTC_WaitForLastTask();
//使能秒中斷
RTC_ITConfig(RTC_IT_SEC, ENABLE);//這句可以放到前面嗎?
RTC_WaitForLastTask();//又等....
}
//清除標(biāo)志
RCC_ClearFlag();
}
為啥要不停的等呢??
RTC核完全獨(dú)立于RTC APB1接口。 軟件通過(guò)APB1接口訪問(wèn)RTC的預(yù)分頻值、計(jì)數(shù)器值和鬧鐘值。但是,相關(guān)的可讀寄存器只在與RTC APB1時(shí)鐘進(jìn)行重新同步的RTC時(shí)鐘的上升沿被更新。RTC標(biāo)志也是如此的。 這意味著,如果APB1接口曾經(jīng)被關(guān)閉,而讀操作又是在剛剛重新開(kāi)啟APB1之后,則在第一次的內(nèi)部寄存器更新之前,從APB1上讀出的RTC寄存器數(shù)值可能被破壞了(通常讀到0)。
因此,若在讀取RTC寄存器時(shí),RTC的APB1接口曾經(jīng)處于禁止?fàn)顟B(tài),則軟件首先必須等待RTC_CRL寄存器中的RSF位(寄存器同步標(biāo)志)被硬件置’1’。
注:RTC的 APB1接口不受WFI和WFE等低功耗模式的影響。
/*******************************************************************************
* Function Name : RTC_IRQHandler RTC中斷
* Description :
* Input : None
* Output : None
* Return : None
*******************************************************************************/
extern volatile bool Sec;//1S標(biāo)志
void RTC_IRQHandler(void)
{
if(RTC_GetITStatus(RTC_IT_SEC) != RESET)//RTC發(fā)生了秒中斷(也有可能是溢出或者鬧鐘中斷)
/*RTC_IT_OW溢出中斷/RTC_IT_ALR鬧鐘中斷/RTC_IT_SEC秒中斷*/
{
RTC_ClearITPendingBit(RTC_IT_SEC);
Sec=TRUE;
//以免RTC計(jì)數(shù)溢出,這里限制了RTC計(jì)數(shù)值的大小.0x0001517f實(shí)際就是一天的秒數(shù)
if(RTC_GetCounter() >= 0x0001517f)
{
RTC_SetCounter(0x0);
RTC_WaitForLastTask();
}
}
}
#include"STM32Lib\stm32f10x.h"
#include"hal.h"
volatilebool Sec=FALSE;
int main(void)
{
ChipHalInit();//片內(nèi)硬件初始化
ChipOutHalInit();//片外硬件初始化
TestRtc();//測(cè)試RTC
for(;;)
{
if(Sec==TRUE)
{
Sec=FALSE;
GPIOA->ODR^=GPIO_Pin_8;//閃燈
}
}
}
最簡(jiǎn)單 最基層的CRT寫好了..........其實(shí)還有好多很酷的功能 比如是否掉電重啟 是否是SeSET 復(fù)位 等 應(yīng)該在CRT前 都檢測(cè)好........
評(píng)論