一、RTC實時時鐘特征與原理
RTC (Real Time Clock):實時時鐘 實時時鐘是一個獨立的定時器。 RTC模塊擁有一組連續計數的計數器,在相應軟件配置下,可提供時鐘日歷的功能。修改計數器的值可以重新設置系統當前的時間和日期。 RTC模塊和時鐘配置系統(RCC_BDCR寄存器)處于后備區域,即在系統復位或從待機模式喚醒后, RTC的設置和時間維持不變。 系統復位后,對后備寄存器和RTC的訪問被禁止,這是為了防止對后備區域(BKP)的意外寫操作。執行以下操作將使能對后備寄存器和RTC的訪問: ● 設置寄存器RCC_APB1ENR的PWREN和BKPEN位,使能電源和后備接口時鐘 ● 設置寄存器PWR_CR的DBP位,使能對后備寄存器和RTC的訪問。
RTC特征 可編程的預分頻系數:分頻系數最高為220。 ● 32位的可編程計數器,可用于較長時間段的測量。 ● 2個分離的時鐘:用于APB1接口的PCLK1和RTC時鐘(RTC時鐘的頻率必須小于PCLK1時鐘 頻率的四分之一以上)。 ● 可以選擇以下三種RTC的時鐘源: ─ HSE時鐘除以128; ─ LSE振蕩器時鐘; ─ LSI振蕩器時鐘(詳見6.2.8節RTC時鐘)。 ● 2個獨立的復位類型: ─ APB1接口由系統復位; ─ RTC核心(預分頻器、鬧鐘、計數器和分頻器)只能由后備域復位(詳見6.1.3節)。 ● 3個專門的可屏蔽中斷: ─ 鬧鐘中斷,用來產生一個軟件可編程的鬧鐘中斷。 ─ 秒中斷,用來產生一個可編程的周期性中斷信號(最長可達1秒)。 ─ 溢出中斷,指示內部可編程計數器溢出并回轉為0的狀態。
二、RTC由兩部分組成 APB1接口: 用來和APB1總線相連。通過APB1接口可以訪問RTC的相關寄存器(預分頻值,計數器值,鬧鐘值)。 RTC核心: 由一組可編程計數器組成。分兩個主要模塊。 第一個是RTC預分頻模塊,它可以編程產生最長1秒的RTC時間基TR_CLK。如果設置了秒中斷允許位,可以產生秒中斷。 第二個是32位的可編程計數器,可被初始化為當前時間。系統時間按TR_CLK周期累加并與存儲在RTC_ALR寄存器中的可編程時間相比,當匹配時候如果設置了鬧鐘中斷允許位,可以產生鬧鐘中斷。
RTC內核完全獨立于APB1接口,軟件通過APB1接口對RTC相關寄存器訪問。但是相關寄存器只在RTC APB1時鐘進行重新同步的RTC時鐘的上升沿被更新。所以軟件必須先等待寄存器同步標志位(RTC_CRL的RSF位)被硬件置1才讀。
三、RTC時鐘源 首先講一下時鐘源:
三種不同的時鐘源可被用來驅動系統時鐘(SYSCLK): ● HSI振蕩器時鐘 ● HSE振蕩器時鐘 ● PLL時鐘 這些設備有以下2種二級時鐘源: ● 40kHz低速內部RC,可以用于驅動獨立看門狗和通過程序選擇驅動RTC。 RTC用于從停機/待機模式下自動喚醒系統。 ● 32.768kHz低速外部晶體也可用來通過程序選擇驅動RTC(RTCCLK)。
當不被使用時,任一個時鐘源都可被獨立地啟動或關閉,由此優化系統功耗。 用戶可通過多個預分頻器配置AHB、高速APB(APB2)和低速APB(APB1)域的頻率。 AHB和APB2域的最大頻率是72MHz。 APB1域的最大允許頻率是36MHz。 SDIO接口的時鐘頻率固定為HCLK/2。 RCC通過AHB時鐘(HCLK)8分頻后作為Cortex系統定時器(SysTick)的外部時鐘。通過對SysTick控制與狀態寄存器的設置,可選擇上述時鐘或Cortex(HCLK)時鐘作為SysTick時鐘。 ADC時鐘由高速APB2時鐘經2、 4、 6或8分頻后獲得。 定時器時鐘頻率分配由硬件按以下2種情況自動設置:
如果相應的APB預分頻系數是1,定時器的時鐘頻率與所在APB總線頻率一致。 否則,定時器的時鐘頻率被設為與其相連的APB總線頻率的2倍。 如上圖,有五個時鐘源,為HSI、HSE、LSI、LSE、PLL。 接下來我們一一看一下:
HSE時鐘
**高速外部時鐘信號(HSE)**由以下兩種時鐘源產生: ● HSE外部晶體/陶瓷諧振器 ● HSE用戶外部時鐘 為了減少時鐘輸出的失真和縮短啟動穩定時間,晶體/陶瓷諧振器和負載電容器必須盡可能地靠 近振蕩器引腳。負載電容值必須根據所選擇的振蕩器來調整。
外部時鐘源(HSE旁路) 在這個模式里,必須提供外部時鐘。它的頻率最高可達25MHz。用戶可通過設置在時鐘控制寄存器中的HSEBYP和HSEON位來選擇這一模式。外部時鐘信號(50%占空比的方波、正弦波或三角波)必須連到SOC_IN引腳,同時保證OSC_OUT引腳懸空。見圖9。 外部晶體/陶瓷諧振器(HSE晶體) **4~16Mz外部振蕩器可為系統提供更為精確的主時鐘。**相關的硬件配置可參考圖9,進一步信息可參考數據手冊的電氣特性部分。 在時鐘控制寄存器RCC_CR中的HSERDY位用來指示高速外部振蕩器是否穩定。在啟動時,直到這一位被硬件置’1’,時鐘才被釋放出來。如果在時鐘中斷寄存器RCC_CIR中允許產生中斷,將會產生相應中斷。 HSE晶體可以通過設置時鐘控制寄存器里RCC_CR中的HSEON位被啟動和關閉。
HSI時鐘
HSI時鐘信號由內部8MHz的RC振蕩器產生,可直接作為系統時鐘或在2分頻后作為PLL輸入。 HSI RC振蕩器能夠在不需要任何外部器件的條件下提供系統時鐘。它的啟動時間比HSE晶體振蕩器短。然而,即使在校準之后它的時鐘頻率精度仍較差。 校準 制造工藝決定了不同芯片的RC振蕩器頻率會不同,這就是為什么每個芯片的HSI時鐘頻率在出廠前已經被ST校準到1%(25°C)的原因。系統復位時,工廠校準值被裝載到時鐘控制寄存器的HSICAL[7:0]位。 如果用戶的應用基于不同的電壓或環境溫度,這將會影響RC振蕩器的精度。可以通過時鐘控制寄存器里的HSITRIM[4:0]位來調整HSI頻率。 時鐘控制寄存器中的HSIRDY位用來指示HSI RC振蕩器是否穩定。在時鐘啟動過程中,直到這一位被硬件置’1’, HSI RC輸出時鐘才被釋放。 HSI RC可由時鐘控制寄存器中的HSION位來啟動和關閉。 如果HSE晶體振蕩器失效, HSI時鐘會被作為備用時鐘源。
PLL
內部PLL可以用來倍頻HSI RC的輸出時鐘或HSE晶體輸出時鐘。 PLL的設置(選擇HIS振蕩器除2或HSE振蕩器為PLL的輸入時鐘,和選擇倍頻因子)必須在其被激活前完成。一旦PLL被激活,這些參數就不能被改動。 如果PLL中斷在時鐘中斷寄存器里被允許,當PLL準備就緒時,可產生中斷申請。 如果需要在應用中使用USB接口, PLL必須被設置為輸出48或72MHZ時鐘,用于提供48MHz的USBCLK時鐘。
LSE時鐘
**LSE晶體是一個32.768kHz的低速外部晶體或陶瓷諧振器。**它為實時時鐘或者其他定時功能提供一個低功耗且精確的時鐘源。 LSE晶體通過在備份域控制寄存器(RCC_BDCR)里的LSEON位啟動和關閉。 在備份域控制寄存器(RCC_BDCR)里的LSERDY指示LSE晶體振蕩是否穩定。在啟動階段,直到這個位被硬件置’1’后, LSE時鐘信號才被釋放出來。如果在時鐘中斷寄存器里被允許,可產生中斷申請。 外部時鐘源(LSE旁路) 在這個模式里必須提供一個32.768kHz頻率的外部時鐘源。你可以通過設置在備份域控制寄存器(RCC_BDCR)里的LSEBYP和LSEON位來選擇這個模式。具有50%占空比的外部時鐘信號(方波、正弦波或三角波)必須連到OSC32_IN引腳,同時保證OSC32_OUT引腳懸空,見圖9。
LSI時鐘
LSI RC擔當一個低功耗時鐘源的角色,它可以在停機和待機模式下保持運行,為獨立看門狗和自動喚醒單元提供時鐘。 **LSI時鐘頻率大約40kHz(在30kHz和60kHz之間)。**進一步信息請參考數據手冊中有關電氣特性部分。 LSI RC可以通過控制/狀態寄存器(RCC_CSR)里的LSION位來啟動或關閉。 在控制/狀態寄存器(RCC_CSR)里的LSIRDY位指示低速內部振蕩器是否穩定。在啟動階段,直到這個位被硬件設置為’1’后,此時鐘才被釋放。如果在時鐘中斷寄存器(RCC_CIR)里被允許,將產生LSI中斷申請。 注意: 只有大容量和互聯型產品可以進行LSI校準
LSI校準 可以通過校準內部低速振蕩器LSI來補償其頻率偏移,從而獲得精度可接受的RTC時間基數,以及獨立看門狗(IWDG)的超時時間(當這些外設以LSI為時鐘源)。 **校準可以通過使用TIM5的輸入時鐘(TIM5_CLK)測量LSI時鐘頻率實現。**測量以HSE的精度為保證,軟件可以通過調整RTC的20位預分頻器來獲得精確的RTC時鐘基數,以及通過計算得到精確的獨立看門狗(IWDG)的超時時間。 LSI校準步驟如下:
打開TIM5,設置通道4為輸入捕獲模式; 設置AFIO_MAPR的TIM5_CH4_IREMAP位為’1’,在內部把LSI連接到TIM5的通道4; 通過TIM5的捕獲/比較4事件或者中斷來測量LSI時鐘頻率; 根據測量結果和期望的RTC時間基數和獨立看門狗的超時時間,設置20位預分頻器。 四、RTC時鐘 **通 過 設 置 備 份 域 控 制 寄 存 器 (RCC_BDCR) 里 的 RTCSEL[1:0] 位 , RTCCLK 時鐘源可以由HSE/128、LSE或LSI時鐘提供。**除非備份域復位,此選擇不能被改變。 LSE時鐘在備份域里,但HSE和LSI時鐘不是。因此: ● 如果LSE被選為RTC時鐘: ─ 只要VBAT維持供電,盡管VDD供電被切斷, RTC仍繼續工作。 ● 如果LSI被選為自動喚醒單元(AWU)時鐘: ─ 如果VDD供電被切斷, AWU狀態不能被保證。有關LSI校準,詳見6.2.5節LSI時鐘。 ● 如果HSE時鐘128分頻后作為RTC時鐘: ─ 如果VDD供電被切斷或內部電壓調壓器被關閉(1.8V域的供電被切斷),則RTC狀態不確定。 ─ 必須設置電源控制寄存器(見4.4.1節)的DPB位(取消后備區域的寫保護)為’1’。
五、RTC寄存器 上面都是從STM32中文手冊里摘取的。大概了解一下RTC和時鐘。 不過講的有點扯,里面有多好寄存器,不知道是干啥的。接下來重點看一下這些寄存器。
RTC控制寄存器高位(RTC_CRH)
RTC控制寄存器低位(RTC_CRL)
①修改CRH/CRL寄存器,必須先判斷RSF位,確定已經同步。 ②修改CNT,ALR,PRL的時候,必須先配置CNF位進入配置模式,修改完之后,設置CNF位為0退出配置模式 ③同時在對RTC相關寄存器寫操作之前,必須判斷上一次寫操作已經結束,也就是判斷RTOFF位是否置位。
RTC預分頻裝載寄存器(RTC_PRLH/RTC_PRLL) 預分頻裝載寄存器用來保存RTC預分頻器的周期計數值。它們受RTC_CR寄存器的RTOFF位保護,僅當RTOFF值為’1’時允許進行寫操作。
RTC預分頻器余數寄存器(RTC_DIVH / RTC_DIVL)
RTC計數器寄存器 (RTC_CNTH / RTC_CNTL)
RTC鬧鐘寄存器(RTC_ALRH/RTC_ALRL)
配置RTC寄存器 必須設置RTC_CRL 寄 存 器 中 的CNF位 , 使RTC進入配置模式后 , 才能寫 入RTC_PRL、RTC_CNT、 RTC_ALR寄存器。 另外,對RTC任何寄存器的寫操作,都必須在前一次寫操作結束后進行。可以通過查詢RTC_CR寄存器中的RTOFF狀態位,判斷RTC寄存器是否處于更新中。僅當RTOFF狀態位是’1’時,才可以寫入RTC寄存器。 配置過程:
查詢RTOFF位,直到RTOFF的值變為’1’ 置CNF值為1,進入配置模式 對一個或多個RTC寄存器進行寫操作 清除CNF標志位,退出配置模式 查詢RTOFF,直至RTOFF位變為’1’以確認寫操作已經完成。 僅當CNF標志位被清除時,寫操作才能進行,這個過程至少需要3個RTCCLK周期。 讀RTC寄存器 RTC核完全獨立于RTC APB1接口。 軟件通過APB1接口訪問RTC的預分頻值、 計數器值和鬧鐘值。但是,相關的可讀寄存器只在與RTC APB1時鐘進行重新同步的RTC時鐘的上升沿被更新。 RTC標志也是如此的。 這意味著,如果APB1接口曾經被關閉,而讀操作又是在剛剛重新開啟APB1之后,則在第一次的內部寄存器更新之前,從APB1上讀出的RTC寄存器數值可能被破壞了(通常讀到0)。下述幾種 情況下能夠發生這種情形: ● 發生系統復位或電源復位 ● 系統剛從待機模式喚醒(參見第4.3節: 低功耗模式)。 ● 系統剛從停機模式喚醒(參見第4.3節: 低功耗模式)。 所有以上情況中, APB1接口被禁止時(復位、無時鐘或斷電)RTC核仍保持運行狀態。 因此,若在讀取RTC寄存器時, RTC的APB1接口曾經處于禁止狀態,則軟件首先必須等待RTC_CRL寄存器中的RSF位(寄存器同步標志)被硬件置’1’。 注: RTC的 APB1接口不受WFI和WFE等低功耗模式的影響
六、RTC相關庫函數講解 庫函數所在文件:stm32f10x_rtc.c / stm32f10x_rtc.h
RTC時鐘源和時鐘操作函數: void RCC_RTCCLKConfig(uint32_t CLKSource);//時鐘源選擇 void RCC_RTCCLKCmd(FunctionalState NewState)//時鐘使能
RTC配置函數(預分頻,計數值: void RTC_SetPrescaler(uint32_t PrescalerValue);//預分頻配置:PRLH/PRLL void RTC_SetCounter(uint32_t CounterValue);//設置計數器值:CNTH/CNTL void RTC_SetAlarm(uint32_t AlarmValue);//鬧鐘設置:ALRH/ALRL
RTC中斷設置函數: void RTC_ITConfig(uint16_t RTC_IT, FunctionalState NewState);//CRH RTC允許配置和退出配置函數: void RTC_EnterConfigMode(void);//允許RTC配置 :CRL位 CNF void RTC_ExitConfigMode(void);//退出配置模式:CRL位 CNF
同步函數: void RTC_WaitForLastTask(void);//等待上次操作完成:CRL位RTOFF void RTC_WaitForSynchro(void);//等待時鐘同步:CRL位RSF
相關狀態位獲取清除函數: FlagStatus RTC_GetFlagStatus(uint16_t RTC_FLAG); void RTC_ClearFlag(uint16_t RTC_FLAG); ITStatus RTC_GetITStatus(uint16_t RTC_IT); void RTC_ClearITPendingBit(uint16_t RTC_IT);
其他相關函數(BKP等) PWR_BackupAccessCmd();//BKP后備區域訪問使能 RCC_APB1PeriphClockCmd();//使能PWR和BKP時鐘 RCC_LSEConfig();//開啟LSE,RTC選擇LSE作為時鐘源 PWR_BackupAccessCmd();//BKP后備區域訪問使能 uint16_t BKP_ReadBackupRegister(uint16_t BKP_DR);//讀BKP寄存器 void BKP_WriteBackupRegister(uint16_t BKP_DR, uint16_t Data);//寫BKP
七、RTC配置一般步驟 1) 使能電源時鐘和備份區域時鐘。 前面已經介紹了,我們要訪問 RTC 和備份區域就必須先使能電源時鐘和備份區域時鐘。
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); 2) 取消備份區寫保護。 要向備份區域寫入數據,就要先取消備份區域寫保護(寫保護在每次硬復位之后被使能),否則是無法向備份區域寫入數據的。我們需要用到向備份區域寫入一個字節,來標記時鐘已經配置過了,這樣避免每次復位之后重新配置時鐘。 取消備份區域寫保護的庫函數實現方法是:
PWR_BackupAccessCmd(ENABLE); //使能 RTC 和后備寄存器訪問 3) 復位備份區域,開啟外部低速振蕩器。 在取消備份區域寫保護之后,我們可以先對這個區域復位,以清除前面的設置,當然這個操作不要每次都執行,因為備份區域的復位將導致之前存在的數據丟失,所以要不要復位,要看情況而定。然后我們使能外部低速振蕩器,注意這里一般要先判斷 RCC_BDCR 的 LSERDY位來確定低速振蕩器已經就緒了才開始下面的操作。 備份區域復位的函數是:
BKP_DeInit();//復位備份區域 開啟外部低速振蕩器的函數是:
RCC_LSEConfig(RCC_LSE_ON);// 開啟外部低速振蕩器 4) 選擇 RTC 時鐘,并使能。 這里我們將通過 RCC_BDCR 的 RTCSEL 來選擇選擇外部 LSI 作為 RTC 的時鐘。然后通過RTCEN 位使能 RTC 時鐘。庫函數中,選擇 RTC 時鐘的函數是:
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //選擇 LSE 作為 RTC 時鐘 對于 RTC 時鐘的選擇,還有 RCC_RTCCLKSource_LSI 和RCC_RTCCLKSource_HSE_Div128 這兩個,顧名思義,前者為 LSI,后者為 HSE 的 128 分頻,這在時鐘系統章節有講解過。 使能 RTC 時鐘的函數是:
RCC_RTCCLKCmd(ENABLE); //使能 RTC 時鐘 5) 設置 RTC 的分頻,以及配置 RTC 時鐘。 在開啟了 RTC 時鐘之后,我們要做的就是設置 RTC 時鐘的分頻數,通過 RTC_PRLH 和RTC_PRLL 來設置,然后等待 RTC 寄存器操作完成,并同步之后,設置秒鐘中斷。然后設置RTC 的允許配置位(RTC_CRH 的 CNF 位),設置時間(其實就是設置 RTC_CNTH 和 RTC_CNTL兩個寄存器)。 下面我們一一這些步驟用到的庫函數:在進行 RTC 配置之前首先要打開允許配置位(CNF),庫函數是:
RTC_EnterConfigMode();/// 允許配置 在配置完成之后,千萬別忘記更新配置同時退出配置模式,函數是:
RTC_ExitConfigMode();//退出配置模式, 更新配置 設置 RTC 時鐘分頻數, 庫函數是:
void RTC_SetPrescaler(uint32_t PrescalerValue); 這個函數只有一個入口參數,就是 RTC 時鐘的分頻數,很好理解。 然后是設置秒中斷允許, RTC 使能中斷的函數是:
void RTC_ITConfig(uint16_t RTC_IT, FunctionalState NewState); 這個函數的第一個參數是設置秒中斷類型,這些通過宏定義定義的。 對于使能秒中斷方法是: RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能 RTC 秒中斷
八、RTC程序 這篇文章復制粘貼了這么多,感覺不到一絲有用的東西。算了,還是看一下,程序是怎么寫的吧。
RTC_Init
RTC_Set
RTC_Get
-
計數器
+關注
關注
32文章
2256瀏覽量
94477 -
時鐘
+關注
關注
10文章
1733瀏覽量
131447 -
RTC
+關注
關注
2文章
538瀏覽量
66463
原文標題:STM32開發 -- RTC詳解
文章出處:【微信號:mcu168,微信公眾號:硬件攻城獅】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論