上一篇:STM32-(26):RCC内部結構與原理分析 | 下一篇:STM32-(28):ADC模數轉換(理論分析) |
---|
實時時鐘的縮寫是RTC(Real_Time Clock)
實時時鐘是一個獨立的定時器。RTC子產品擁有一組連續計數的計數器,在相應軟體配置下,可提供時鐘月曆的功能。修改計數器的值可以重新設定系統目前的時間和日期
RTC由兩個主要部分組成。第一部分(APB1接口)用來和APB1總線相連。此單元還包含一組16位寄存器,可通過APB1總線對其進行讀寫操作。APB1接口以APB1總線時鐘為時鐘。
另一部分(RTC核)由一系列可程式設計計數器組成,分成兩個主要子產品:
第一個子產品是RTC的預分頻子產品,它可程式設計産生最長為1秒的RTC時間基準TR_CLK,RTC的預分頻子產品包含了一個20位的可程式設計分頻器(RTC預芬頻器)。在每個TR_CLK周期中,如果在RTC_CR寄存器中設定了相應允許位,則RTC盧生一個中斷(秒中斷)。
第二個子產品是一個32位的可程式設計的計數器,它可以被初始化為目前的系統時間。系統時間以TR_CLK速度增長并與存儲在RTC_ALR寄存器中的可程式設計的時間相比較,如果RTC_CR控制寄存器設定了相應允許位則比較比對時将産生一個鬧鐘中斷。
分析
RTCCLK 外部低速時鐘信号進來,先進入 RTC_DIV(分頻器),RTC_PRL是裝載器,然後得到一個 TR_CLK的信号,這個信号嚴格來說是 1s來一次,産生精确的秒信号,秒信号一路可以通過 RTC_Second,産生一個 RTC_CR 的标志位 SECF,當 SECIE 打開了(這個相當于一個開關,這個信号燈額中斷允許位,表示允許秒信号輸入),(SECF和SECIE是與的關系)就會産生一個中斷;秒信号也可以輸入到後面的 RTC_CNT計數器,這個計數器可以進行32位(2的32次方)的程式設計控制,當計數器寄存器的值達到設定的值就會産生 RTC_Overflow 信号,後面的 OWIE 如果打開,也會産生中斷;如果設定的 RTC_ALR的值(報警),當計數器寄存器的值等于報警相關寄存器設定值,就會産生鬧鐘信号 RTC_Alarm,同時 ALRIE 打開,就會産生中斷。這三種信号産生的中斷就會進入下方的 NVIC INTERRUPT CONTRCLLER(中斷控制器),相當于強制讓CPU處理這個中斷信号。 RTC_Alarm 和 WKUP_pin是或的關系,有任何一個信号,就會産生中斷或者 進入 EXIT FROM ,就是從 常置狀态跳出 ,喚醒CPU的意思;上方一整個灰色陰影區域表示這塊區域的工作不是由VCC電源直接供電的(當然也可以由VCC供電),當VCC電源無效的時候或者說CPU沒有工作的時候,是由後備電池供電的,這個區域稱為“後備區”,系統在斷電複位的情況下,不會影響後備區。比如手機電腦關機開機後,時間顯示總是正确的。
主要特性
**可程式設計的預分頻系數:**分頻系數最髙為220
32位的可程式設計計數器,可用于較長命間段的測量。
2個單獨的時鐘,用于APB1接口的PCLK1和RTC時鐘(此時的RTC時鐘必須小于PCLK1時鐘的四分之一以上)
2種獨立的複位類型:
APB1接口由系統複位
RTC隻能由後備域複位
3個專門的可屏蔽中斷 :
鬧鐘中斷,用來産生一個軟體可程式設計的鬧鐘中斷。
秒中斷,用來産生一個可程式設計的周期性中斷信号
溢出中斷,檢測内部可程式設計計數器溢出并回轉為0的狀态。
RTC 的一些設定是儲存在後備域中的: RTC_PRL,RTC_ALR,RTC_CNT 和 RTC_DIV 寄存器。
這些寄存器器僅能通過備份域複位信号複位,不受系統複位或電源複位的影響。
備份域複位
當以下事件中之一發生時,産生備份區域複位。
- 軟體複位,備份區域複位可由設定備份區域控制寄存器 RCC _ BDCR 中的 BDRST 位産生。
- 在 VDD 和 VBAT 兩者掉電的前提下, VDD 或 VBAT 上電将引發備份區域複位。
對相關寄存器操作流程
要對 RTC_PRL . RTC_CNT . RTC_ALR 寄存器進行寫操作, RTC 必須進入配置模式。通過對 RTC_CRL寄存器中的 CNF 位置位使 RTC 進入配置模式。另外,對 RTC 的任何寄存器的寫操作都必須在前一次寫操作結束以後進行。要使用軟體來查詢目前的狀态,同可通過查詢 RTC_CR 寄存器中的 RTOFF狀态位來判斷 RTC 寄存器是否處于更新中,僅當 RTOFF 狀态位是“1”時,RTC 寄存器可以寫入新的值。
配置過程:
- 查詢 RTOFF 位,直到 RTOFF 的值變為“ 1 ”
- 置 CNF 值 為1 , 進入配置模式
- 對一個或多個 RTC 寄存器進行寫操作
- 清除 CNF 标志位,退出配置模式
- 查詢 RTOFF,直至RTOFF位變為“1”以确認寫操作已經完成。
僅當 CNF 紅志位被清除時.寫操作才能進行,這個過程至少需要3個 RTCCLK 周期
RTC相關寄存器
RTC_CRH
OWIE:允許溢出中斷位
0:屏蔽(不允許)溢出中斷
1:允許溢出中斷
ALRIE:允許鬧鐘中斷
0:屏蔽(不允許)鬧鐘中斷
1:允許鬧鐘中斷
SECIE:允許秒中斷
0:屏蔽(不允許)秒中斷
1:允許秒中斷
RTC_CRL
RTOFF: RTC操作關閉
RTC子產品利用這位來訓示對其寄存器進行的最後一次操作的狀态,訓示操作是否完成。若此位為0,則無法對任何的RTC寄存器進行寫操作。此位為隻讀位。
0:上一次對RTC寄存器的寫操作仍在進行;
1:上一次對RTC寄存器的寫操作已經完成。
CNF:配置标志
此位必須由軟體置1以進入配置模式,進而允許向RTC_CNT、RTC_ALR或RTC_PRL寄存器寫入資料。隻有當此位在被置1後,并重新由軟體清0後,才會執行寫操作。
0:退出配置模式(開始更新RTC寄存器);
1:進入配置模式。
RSF:寄存器同步标志
每當RTC_CNT寄存器和RTC_DIV寄存器由軟體重新整理或清0時,此位由硬體置1。在APB1複位後,或APB1時鐘停止後,此位必須由軟體清0。要進行任何的讀操作之前,使用者程式必須等待這位被硬體置1,以確定RTC_CNT、RTC_ALR或RTC_PRL已經被同步。
0:寄存器尚未被同步;
1:寄存器已經被同步。
OWF:溢出标志
當32位可程式設計計數器溢出時,此位由硬體置1。如果RTC_CRH寄存器中OWIE=1,則産生中斷。此位隻能由軟體清0。對此位寫1是無效的。
0:無溢出;
1:32位可程式設計計數器溢出。
ALRF:鬧鐘标志
當32位可程式設計計數器達到RTC_ALR寄存器所設定的門限值,此位由硬體置1。如果RTC_CRH寄存器中ALRIE=1,則産生中斷。此位隻能由軟體清0。對此位寫1是無效的。
0:無鬧鐘;
1:有鬧鐘。
SECF:秒标志
當32位可程式設計預分頻器溢出時,此位由硬體置1,RTC計數器遞增。是以,此标志為分辨率可程式設計的RTC計數器提供一個周期性的信号(通常為1秒)。如果RTC_CRH寄存器中SECIE=1,則産生中斷。此位隻能由軟體清除。對此位寫“1”是無效的。
0:秒标志條件不成立;
1:秒标志條件成立。
RTC 計數器寄存器 (RTC_CNTH / RTC_CNTL)
RTC核有一個32位可程式設計的計數器,可通過兩個16位的寄存器通路。計數器以預分頻器産生的TR_CLK時間基準為參考進行計數。RTC_CNT寄存器用來存放計數器的計數值。他們被RTC_CR上的位RTOFF寫保護,并且如果RTOFF值是1的話,允許寫操作。在高或低寄存器(RTC_CNTH或RTC_CNTL)上的寫操作,能夠直接裝載到相應的可程式設計計數器,并且重新裝載RTC預分頻器。當進行讀操作時,直接傳回計數器内的計數值(系統時間)。
RTC 鬧鐘寄存器(RTC_ALRH/RTC_ALRL )
當可程式設計計數器的值與RTC_ALR中的32位值相等時,即觸發一個鬧鐘事件,并且産生RTC鬧鐘中斷。此寄存器被RTC_CR寄存器裡的RTOFF位寫保護,如果RTOFF值是1時,允許寫操作。
相關庫函數
代碼塊
main.c
/*Includes----------------------------------*/
#include"stm32f10x_lib.h" //包含所用的頭檔案
#include<stdio.h>
//----------------外部函數的聲明------------------------------
extern void SMG_Init(void);
extern void SMG_Display(u32 data,u8 dot); //數位管函數的聲明(包含SPI函數的聲明)
extern void RTC_Configuration(void);
//---------------------函數的聲明---------------------------
void Delay_Ms(u16 time);
void RCC_Configuration(void);
void NVIC_Configuration(void);
extern vu8 Count;
/* Private functions ---------------------------------------------------------*/
/*******************************************************************************
* Function Name : main
* Description : Main program.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
int main(void)
{
#ifdef DEBUG
debug();
#endif
RCC_Configuration();
RTC_Configuration();
SMG_Init();
NVIC_Configuration();
while(1)
{
SMG_Display(Count,3);
}
}
/*******************************************************************************
* Function Name : Delay_Ms
* Description : delay 1 ms.
* Input : time (ms)
* Output : None
* Return : None
*******************************************************************************/
void Delay_Ms(u16 time) //延時函數
{
u16 i,j;
for(i=0;i<time;i++)
for(j=10000;j>0;j--);
}
/*******************************************************************************
* Function Name : RCC_Configuration
* Description : Configures the different system clocks.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void RCC_Configuration(void)
{
//-----------使用外部RC晶振-----------------
RCC_DeInit(); //初始化為預設值狀态
RCC_HSEConfig(RCC_HSE_ON);
while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
FLASH_SetLatency(FLASH_Latency_2);
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK2Config(RCC_HCLK_Div1);
RCC_PCLK1Config(RCC_HCLK_Div2);
RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);
RCC_PLLCmd(ENABLE);
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
while(RCC_GetSYSCLKSource()!=0x08);
}
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
#ifdef VECT_TAB_RAM
NVIC_SetVectorTable(NVIC_VectTab_RAM,0x0);
#else
NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x0);
#endif
//Configure one bit for preemption priority
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQChannel; //設定RTC中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //設定先優先級為 1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //設定亞優先級為0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //中斷使能
NVIC_Init(&NVIC_InitStructure); //初始化
}
RTC.c
/********************************************************************
* 檔案 :RTC.c
* 描述 : 實時時鐘RTC子產品的配置
********************************************************************/
#include"stm32f10x_lib.h"
/*************************************************************************************
**名稱 ;void RTC_Configuration(void)
**功能 ;RTC實時時鐘的配置
**入口參數 ;無
**出口參數 ;無
*************************************************************************************/
void RTC_Configuration(void)
{
/* Enable PWR and BKP clocks */ //使能APB1外設PWR and BKP 的時鐘 (打開電源與後備電源)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP,ENABLE);
/* Allow access to BKP Domain*/ //允許RTC 和後備寄存器的通路
PWR_BackupAccessCmd(ENABLE);
/* Reset Backup Domain*/ //将外設BKP的全部 寄存器重設為預設值
BKP_DeInit();
/* Enable LSE */ //設定外部低速時鐘
RCC_LSEConfig(RCC_LSE_ON);
/* Wait till LSE is ready */ //等待外部低速時鐘準備好
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
/* Select LSE as RTC Clock Source */ //設定LSE為RTC時鐘
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
/* Enable RTC Clock */ //使能RT時鐘
RCC_RTCCLKCmd(ENABLE);
/* Wait for RTC registers synchronization *///等待RTC寄存器(RTC_CNT,RTC_ALR and RTC_PRL)與RTC的APB時鐘同步
RTC_WaitForSynchro();
/* Wait untill last write operation on RTC register has finised *///等待最近一次對RTC的寫操作完成
RTC_WaitForLastTask();
/* Enable the RTC Second interrup */ //使能RTC的秒中斷
RTC_ITConfig(RTC_IT_SEC,ENABLE);
/* Wait untill last write operation on RTC register has finised *///等待最近一次對RTC的寫操作完成
RTC_WaitForLastTask();
/* Set RTC prescaler : set RTC period to 1 sec*/ //設定RTC預分頻的值 為32767,則計數頻率 = (32.768 KHz)/(32767+1) = 1Hz(~1s)
RTC_SetPrescaler(32767);
/* Wait untill last write operation on RTC register has finised *///等待最近一次對RTC的寫操作完成
RTC_WaitForLastTask();
}
上一篇:STM32-(26):RCC内部結構與原理分析 | 下一篇:STM32-(28):ADC模數轉換(理論分析) |
---|