簡單初始化STM32的RTC
要使用 RTC,一般來說也順帶地使用上后備寄存器—這是因為RTC 是一個簡單的秒中斷
定時器,年月日時分秒的信息必須要找個地方能掉電保存才有意義.STM32 的備份寄存器(BKP)是42個16位的寄存器,可用來存儲84個字節的用戶應用程序數據。他們處在備份域里,當VDD電源被切斷,他們仍然由VBAT維持供電。當系統在待機模式下被喚醒,或系統復位或電源復位時,他們也不會被復位。 此外,BKP控制寄存器用來管理侵入檢測和RTC校準功能。 復位后,對備份寄存器和RTC的訪問被禁止,并且備份域被保護以防止可能存在的意外的寫操作它是用后備電池供電的,只要配置好后,即使系統關電,32768 的
晶振和后備寄存器的數據也會得以維持.而且RTC的計數器是會繼續秒遞增的.那么要配
置RTC,就必須開放以下東西:
#include "stm32f10x_bkp.h" 這個是后備寄存器
#include "stm32f10x_pwr.h" 電源管理
#include "stm32f10x_rtc.h" RTC庫

開始吧.....先是中斷
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);
}
然后設置 RTC
#include "STM32Lib\stm32f10x.h"
#include "hal.h"
static u8 RTC_Blank=0;
/***********************************
**函數名:RTC_Configuration
**功能:RTC設置
**注意事項:要根據是否是第一次設置,才進入下面的RTC設定
判斷是否第一次設置,只需要判斷RTC后備寄存器1的值是否為事先寫入的0XA5A5,如果不是,則
RTC是第一次上電,需要初始化RTC,并把實際時間轉化為RTC計數值,這里沒有設置實際時間,只是簡單地初始化了RTC
************************************/
void RTC_Configuration(void)
{
/*PWR時鐘(電源控制)與BKP時鐘(RTC后備寄存器)使能*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
/*使能RTC和后備寄存器訪問*/
PWR_BackupAccessCmd(ENABLE);
/*從指定的后備寄存器(BKP_DR1)中讀出數據*/
if(BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5)
{
/* 將外設BKP的全部寄存器重設為缺省值 */
BKP_DeInit();
/*啟用 LSE(外部低速晶振)*/
RCC_LSEConfig(RCC_LSE_ON);
/*等待外部晶振震蕩 需要等待比較長的時間*/
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
/*使用外部晶振32.768K作為RTC時鐘*/
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
//允許RTC
RCC_RTCCLKCmd(ENABLE);
//等待RTC寄存器同步 原因下文說明
RTC_WaitForSynchro();
//等待最近一次對RTC寄存器的寫操作完成
RTC_WaitForLastTask();
//允許RTC的秒中斷(還有鬧鐘中斷和溢出中斷可設置)
RTC_ITConfig(RTC_IT_SEC, ENABLE);
//又是等待上一次對RTC寄存器的寫操作完成
RTC_WaitForLastTask();
//32768晶振預分頻值是32767,不過一般來說晶振都不那么準
RTC_SetPrescaler(32776);//如果需要校準晶振,可修改此分頻值
RTC_WaitForLastTask();
//寫入RTC后備寄存器1 0xa5a5
BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);
RTC_Blank=1;/*這個標志代表RTC是沒有預設的(或者說是沒有上紐扣電池) 用串口呀啥的輸出來。*/
}
//如果RTC已經設置
else
{
//等待RTC與APB同步
RTC_WaitForSynchro();
RTC_WaitForLastTask();
//使能秒中斷
RTC_ITConfig(RTC_IT_SEC, ENABLE);//這句可以放到前面嗎?
RTC_WaitForLastTask();//又等....
}
//清除標志
RCC_ClearFlag();
}
為啥要不停的等呢??
RTC核完全獨立于RTC APB1接口。 軟件通過APB1接口訪問RTC的預分頻值、計數器值和鬧鐘值。但是,相關的可讀寄存器只在與RTC APB1時鐘進行重新同步的RTC時鐘的上升沿被更新。RTC標志也是如此的。 這意味著,如果APB1接口曾經被關閉,而讀操作又是在剛剛重新開啟APB1之后,則在第一次的內部寄存器更新之前,從APB1上讀出的RTC寄存器數值可能被破壞了(通常讀到0)。
因此,若在讀取RTC寄存器時,RTC的APB1接口曾經處于禁止狀態,則軟件首先必須等待RTC_CRL寄存器中的RSF位(寄存器同步標志)被硬件置’1’。
注:RTC的 APB1接口不受WFI和WFE等低功耗模式的影響。
/*******************************************************************************
* Function Name : RTC_IRQHandler RTC中斷
* Description :
* Input : None
* Output : None
* Return : None
*******************************************************************************/
extern volatile bool Sec;//1S標志
void RTC_IRQHandler(void)
{
if(RTC_GetITStatus(RTC_IT_SEC) != RESET)//RTC發生了秒中斷(也有可能是溢出或者鬧鐘中斷)
/*RTC_IT_OW溢出中斷/RTC_IT_ALR鬧鐘中斷/RTC_IT_SEC秒中斷*/
{
RTC_ClearITPendingBit(RTC_IT_SEC);
Sec=TRUE;
//以免RTC計數溢出,這里限制了RTC計數值的大小.0x0001517f實際就是一天的秒數
if(RTC_GetCounter() >= 0x0001517f)
{
RTC_SetCounter(0x0);
RTC_WaitForLastTask();
}
}
}
#include"STM32Lib\stm32f10x.h"
#include"hal.h"
volatilebool Sec=FALSE;
int main(void)
{
ChipHalInit();//片內硬件初始化
ChipOutHalInit();//片外硬件初始化
TestRtc();//測試RTC
for(;;)
{
if(Sec==TRUE)
{
Sec=FALSE;
GPIOA->ODR^=GPIO_Pin_8;//閃燈
}
}
}
最簡單 最基層的CRT寫好了..........其實還有好多很酷的功能 比如是否掉電重啟 是否是SeSET 復位 等 應該在CRT前 都檢測好........


評論