0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

GD32開(kāi)發(fā)實(shí)戰(zhàn)指南(基礎(chǔ)篇) 第16章 RTC

嵌入式大雜燴 ? 來(lái)源:嵌入式大雜燴 ? 作者:嵌入式大雜燴 ? 2023-05-18 22:14 ? 次閱讀

開(kāi)發(fā)環(huán)境:

MDK:Keil 5.30

開(kāi)發(fā)板:GD32F207I-EVAL

MCU:GD32F207IK

1 RTC工作原理

1.1 RTC簡(jiǎn)介

GD32 的 RTC 外設(shè),實(shí)質(zhì)是一個(gè)掉電后還繼續(xù)運(yùn)行的定時(shí)器。從定時(shí)器的角度來(lái)說(shuō),相對(duì)于通用定時(shí)器 TIMER 外設(shè),它十分簡(jiǎn)單,只有很純粹的計(jì)時(shí)功能(當(dāng)然,可以觸發(fā)中斷);但從掉電還繼續(xù)運(yùn)行的角度來(lái)說(shuō),它卻是 GD32中唯一一個(gè)具有如此強(qiáng)大功能的外設(shè)。所以 RTC 外設(shè)的復(fù)雜之處并不在于它的定時(shí)功能,而在于它掉電還繼續(xù)運(yùn)行的特性。

以上所說(shuō)的掉電, 是指主電源 VDD斷開(kāi)的情況,為了 RTC 外設(shè)掉電繼續(xù)運(yùn)行,必須給GD32芯片通過(guò) VBAT引腳接上鋰電池 。當(dāng)主電源 VDD有效時(shí),由 VDD給 RTC 外設(shè)供電。當(dāng) VDD掉電后,由 VBAT給 RTC 外設(shè)供電。但無(wú)論由什么電源供電,RTC 中的數(shù)據(jù)都保存在屬于 RTC 的備份域中, 若主電源 VDD和 VBAT都掉電,那么備份域中保存的所有數(shù)據(jù)將丟失 。備份域除了 RTC 模塊的寄存器,還有 42 個(gè) 16 位的寄存器可以在 VDD掉電的情況下保存用戶(hù)程序的數(shù)據(jù),系統(tǒng)復(fù)位或電源復(fù)位時(shí),這些數(shù)據(jù)也不會(huì)被復(fù)位。

從 RTC 的定時(shí)器特性來(lái)說(shuō), 它是一個(gè) 32 位的計(jì)數(shù)器,只能向上計(jì)數(shù) 。它使用的時(shí)鐘源有三種,分別為高速外部時(shí)鐘的 128 分頻:HXTAL/128;低速內(nèi)部時(shí)鐘IRC40K;使 HXTAL分頻時(shí)鐘或IRC40K的話(huà),在主電源 VDD掉電的情況下,這兩個(gè)時(shí)鐘來(lái)源都會(huì)受到影響,因此沒(méi)法保證 RTC 正常工作。因此 RTC 一般使用低速外部時(shí)鐘LXTAL,頻率為實(shí)時(shí)時(shí)鐘模塊中常用的 32.768KHz,這是因?yàn)?32768 = 215,分頻容易實(shí)現(xiàn),所以它被廣泛應(yīng)用到 RTC 模塊。在主電源 VDD有效的情況下(待機(jī)),RTC 還可以配置鬧鐘事件使 GD32退出待機(jī)模式。

RTC模塊在相應(yīng)軟件配置下,可提供時(shí)鐘日歷的功能。修改計(jì)數(shù)器的值可以重新設(shè)置系統(tǒng)當(dāng)前的時(shí)間和日期。RTC模塊和時(shí)鐘配置系統(tǒng)處于后備區(qū)域,即在系統(tǒng)復(fù)位或從待機(jī)模式喚醒后,RTC的設(shè)置和時(shí)間維持不變。

1.2主要特性

  • 編程的預(yù)分頻系數(shù):分頻系數(shù)最高為2^20
  • 32位的可編程計(jì)數(shù)器,可用于較長(zhǎng)時(shí)間段的測(cè)量。
  • 2個(gè)分離的時(shí)鐘:用于APB1接口的PCLK1和RTC時(shí)鐘(RTC時(shí)鐘的頻率必須小于PCLK1時(shí)鐘頻率的四分之一以上)。
  • 可以選擇以下三種RTC的時(shí)鐘源:

A) HXTAL 時(shí)鐘除以 128

B) LXTAL 振蕩電路時(shí)鐘

C) IRC40K 振蕩電路時(shí)鐘

  • 2個(gè)獨(dú)立的復(fù)位類(lèi)型:

A) APB1接口由系統(tǒng)復(fù)位;

B) RTC核心(預(yù)分頻器、鬧鐘、計(jì)數(shù)器和分頻只能由后備域復(fù)位

  • 3個(gè)專(zhuān)門(mén)的可屏蔽中斷:

A) 鬧鐘中斷,用來(lái)產(chǎn)生一個(gè)軟件可編程的鬧鐘中斷。

B) 秒中斷,用來(lái)產(chǎn)生一個(gè)可編程的周期性中斷信號(hào) (最長(zhǎng)可達(dá)1秒)。

C) 溢出中斷,指示內(nèi)部可編程計(jì)數(shù)器溢出并回轉(zhuǎn)為的狀態(tài)。

1.3 RTC架構(gòu)

RTC的架構(gòu)如下圖所示。

1684418636974719k5ryolu

RTC 由兩個(gè)主要部分組成, 第一部分(APB1 接口)用來(lái)和 APB1 總線(xiàn)相連。此單元還包含一組 16 位寄存器,可通過(guò) APB1 總線(xiàn)對(duì)其進(jìn)行讀寫(xiě)操作。 APB1 接口由 APB1 總線(xiàn)時(shí)鐘驅(qū)動(dòng),用來(lái)與 APB1 總線(xiàn)連接。

另一部分(RTC 核心)由一組可編程計(jì)數(shù)器組成,RTC內(nèi)核包含兩個(gè)主要模塊。一個(gè)是RTC預(yù)分頻模塊,用來(lái)產(chǎn)生RTC時(shí)間基準(zhǔn)時(shí)鐘SC_CLK。RTC預(yù)分頻模塊包含一個(gè)20位可編程分頻器(RTC預(yù)分頻器) ,該分頻器可以通過(guò)對(duì)RTC時(shí)鐘源分頻產(chǎn)生SC_CLK。如果對(duì)RTC_INTEN寄存器中的秒中斷標(biāo)志位被使能, RTC會(huì)在每個(gè)SC_CLK上升沿產(chǎn)生一個(gè)秒中斷。 另外一個(gè)模塊是一個(gè)32 位可編程計(jì)數(shù)器,其數(shù)值可以被初始化為當(dāng)前系統(tǒng)時(shí)間。如果對(duì)RTC_INTEN 寄存器的鬧鐘中斷標(biāo)志位被使能, RTC會(huì)在系統(tǒng)時(shí)間等于鬧鐘時(shí)間(存儲(chǔ)于RTC_ALRMH/L 寄存器)時(shí)產(chǎn)生一個(gè)鬧鐘中斷。

2 RTC寄存器分析

2.1 RTC寄存器描述

RTC 總共有 2 個(gè)控制寄存器RTC_INTEN和 RTC_CTL。

RTC_INTEN寄存器用來(lái)控制中斷的,我們本章將要用到秒鐘中斷,所以在該寄存器必須設(shè)置最低位為 1,以允許秒鐘中斷。

1684418637451werpj2as2y

RTC_CTL的第 0 位是秒鐘標(biāo)志位,我們?cè)谶M(jìn)入鬧鐘中斷的時(shí)候,通過(guò)判斷這位來(lái)決定是不是發(fā)生了秒鐘中斷。然后必須通過(guò)軟件將該位清零(寫(xiě)0)。第 3 位為寄存器同步標(biāo)志位,我們?cè)谛薷目刂萍拇嫫髦?,必須先判斷該位,是否已?jīng)同步了,如果沒(méi)有則等待同步,在沒(méi)同步的情況下修改RTC_INTEN/RTC_CTL的值是不行的。第4位為配置標(biāo)位,在軟件修改 RTC_CNTx/RTC_ALRMx/RTC_PSCx的值的時(shí)候,必須先軟件置位該位,以允許進(jìn)入配置模式。第 5 位為 RTC 操作位,該位由硬件操作,軟件只讀。通過(guò)該位可以判斷上次對(duì) RTC 寄存器的操作是否完成,如果沒(méi)有,我們必須等待上一次操作結(jié)束才能開(kāi)始下一次操作。

1684418637779s9lm26192n

【注意】

  • 任何標(biāo)志位都將保持掛起狀態(tài),直到適當(dāng)?shù)腞TC_CTL請(qǐng)求位被軟件復(fù)位,表示所請(qǐng)求的中斷已經(jīng)被接受。
  • 在復(fù)位時(shí)禁止所有中斷,無(wú)掛起的中斷請(qǐng)求,可以對(duì)RTC寄存器進(jìn)行寫(xiě)操作。
  • 當(dāng)APB1時(shí)鐘不運(yùn)行時(shí),SCIF、ALRMIF、OVIF和RSYNF位不被更新。
  • SCIF、ALRMIF、OVIF和RSYNF位只能由硬件置位,由軟件來(lái)清零。
  • 若ALRMIF =1且ALRMIE =1,則允許產(chǎn)生RTC全局中斷。如果在EXTI控制器中允許產(chǎn)生EXTI線(xiàn) 17中斷,則允許產(chǎn)生RTC全局中斷和RTC鬧鐘中斷。
  • 若ALRMIF =1,如果在EXTI控制器中設(shè)置了EXTI線(xiàn) 17的中斷模式,則允許產(chǎn)生RTC鬧鐘中斷;如果在EXTI控制器中設(shè)置了EXTI線(xiàn) 17的事件模式,則這條線(xiàn)上會(huì)產(chǎn)生一個(gè)脈沖(不會(huì)產(chǎn)生RTC鬧鐘中斷)。

RTC 預(yù)分頻裝載寄存器,也有 2 個(gè)寄存器組成,RTC_PSCH和RTC_PSCL。這兩個(gè)寄存器用來(lái)配置 RTC 時(shí)鐘的分頻數(shù)的,比如我們使用外部 32.768K 的晶振作為時(shí)鐘的輸入頻率,那么我們要設(shè)置這兩個(gè)寄存器的值為 32767,以得到一秒鐘的計(jì)數(shù)頻率。RTC_PSCH的各位描述如下圖所示。

1684418638063v2mz9i4yke

從上圖可以看出,RTC_PSCH只有低四位有效,用來(lái)存儲(chǔ)PSC的 19~16 位。而PSC的前 16 位,存放在RTC_PSCL里面,寄存器RTC_PSCL的各位描述如下圖所示。

16844186384035m4fqoh48o

【注】如果輸入時(shí)鐘頻率是32.768kHz(RTCCLK),這個(gè)寄存器中寫(xiě)入7FFFh可獲得周期為1秒鐘的信號(hào)。

RTC 預(yù)分頻器寄存器也有 2 個(gè)寄存器組成 RTC_DIVH 和 RTC_DIVL,這兩個(gè)寄存器的作用就是用來(lái)獲得比秒鐘更為準(zhǔn)確的時(shí)鐘,比如可以得到 0.1 秒,或者 0.01 秒等。該寄存器的值自減的,用于保存還需要多少時(shí)鐘周期獲得一個(gè)秒信號(hào)。在一次秒鐘更新后,由硬件重新裝載。這兩個(gè)寄存器和 RTC 預(yù)分頻裝載寄存器的各位是一樣的,這里我們就不列出來(lái)了。

接著要介紹的是 RTC 最重要的寄存器, RTC 計(jì)數(shù)器寄存器 RTC_CNT。該寄存器由 2 個(gè) 16位的寄存器組成 RTC_CNTH 和 RTC_CNTL,總共 32 位,用來(lái)記錄秒鐘值(一般情況下)。此兩個(gè)計(jì)數(shù)器也比較簡(jiǎn)單,我們也不多說(shuō)了。注意一點(diǎn),在修改這個(gè)寄存器的時(shí)候要先進(jìn)入配置模式。

最后我們介紹 RTC 部分的最后一個(gè)寄存器, RTC 鬧鐘寄存器,該寄存器也是由 2 個(gè) 16 為的寄存器組成 RTC_ALRH 和 RTC_ALRL??偣惨彩?32 位,用來(lái)標(biāo)記鬧鐘產(chǎn)生的時(shí)間(以秒為單位),如果 RTC_CNT 的值與 RTC_ALR 的值相等,并使能了中斷的話(huà),會(huì)產(chǎn)生一個(gè)鬧鐘中斷。該寄存器的修改也要進(jìn)入配置模式才能進(jìn)行。

因?yàn)槲覀兪褂玫絺浞菁拇嫫鱽?lái)存儲(chǔ) RTC 的相關(guān)信息(我們這里主要用來(lái)標(biāo)記時(shí)鐘是否已經(jīng)經(jīng)過(guò)了配置)。

2.2 讀RTC寄存器

RTC完全獨(dú)立于RTC APB1接口。

軟件通過(guò)APB1接口訪(fǎng)問(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) 。下述幾種情況下能夠發(fā)生這種情形:

  • 發(fā)生系統(tǒng)復(fù)位或電源復(fù)位
  • 系統(tǒng)剛從待機(jī)模式喚醒
  • 系統(tǒng)剛從停機(jī)模式喚醒

所有以上情況中,APB1接口被禁止時(shí)(復(fù)位、無(wú)時(shí)鐘或斷電)RTC核仍保持運(yùn)行狀態(tài)。

因此,若在讀取RTC寄存器時(shí),RTC 的APB1 接口曾經(jīng)處于禁止?fàn)顟B(tài),則軟件首先必須等待RTC_CTL寄存器中的RSYNF位(寄存器同步標(biāo)志)被硬件置’1’。

2.3 配置RTC寄存器

必須設(shè)置RTC_CTL寄存器中的CMF位,使 RTC進(jìn)入配置模式后,才能寫(xiě)入 RTC_PSC、RTC_CNT、RTC_ALRM寄存器。

另外,對(duì)RTC任何寄存器的寫(xiě)操作,都必須在前一次寫(xiě)操作結(jié)束后進(jìn)行。可以通過(guò)查詢(xún)RTC_CTL寄存器中的LWOFF狀態(tài)位,判斷RTC寄存器是否處于更新中。僅當(dāng)LWOFF狀態(tài)位是’1’時(shí),才可以寫(xiě)入RTC寄存器。

配置過(guò)程:

1.查詢(xún)LWOFF位,直到LWOFF的值變?yōu)椤?’

2.置CMF值為1,進(jìn)入配置模式

3.對(duì)一個(gè)或多個(gè)RTC寄存器進(jìn)行寫(xiě)操作

4.清除CMF標(biāo)志位,退出配置模式

5.查詢(xún)LWOFF,直至LWOFF位變?yōu)椤?’ 以確認(rèn)寫(xiě)操作已經(jīng)完成。

6.僅當(dāng)CMF標(biāo)志位被清除時(shí),寫(xiě)操作才能進(jìn)行,這個(gè)過(guò)程至少需要3個(gè)RTCCLK周期。

3 RTC具體代碼實(shí)現(xiàn)

RTC 正常工作的一般配置步驟如下:

1)使能電源時(shí)鐘和備份區(qū)域時(shí)鐘。

前面已經(jīng)介紹了,我們要訪(fǎng)問(wèn) RTC 和備份區(qū)域就必須先使能電源時(shí)鐘和備份區(qū)域時(shí)鐘。

rcu_periph_clock_enable(RCU_BKPI);
rcu_periph_clock_enable(RCU_PMU);

2)取消備份區(qū)寫(xiě)保護(hù)。

要向備份區(qū)域?qū)懭霐?shù)據(jù),就要先取消備份區(qū)域?qū)懕Wo(hù)(寫(xiě)保護(hù)在每次硬復(fù)位之后被使能),否則是無(wú)法向備份區(qū)域?qū)懭霐?shù)據(jù)的。我們需要用到向備份區(qū)域?qū)懭胍粋€(gè)字節(jié),來(lái)標(biāo)記時(shí)鐘已經(jīng)配置過(guò)了,這樣避免每次復(fù)位之后重新配置時(shí)鐘。 取消備份區(qū)域?qū)懕Wo(hù)的庫(kù)函數(shù)實(shí)現(xiàn)方法是:

pmu_backup_write_enable(); //使能 RTC 和后備寄存器訪(fǎng)問(wèn)

3)復(fù)位備份區(qū)域,開(kāi)啟外部低速振蕩器。

在取消備份區(qū)域?qū)懕Wo(hù)之后,我們可以先對(duì)這個(gè)區(qū)域復(fù)位,以清除前面的設(shè)置,當(dāng)然這個(gè)操作不要每次都執(zhí)行,因?yàn)閭浞輩^(qū)域的復(fù)位將導(dǎo)致之前存在的數(shù)據(jù)丟失,所以要不要復(fù)位,要看情況而定。然后我們使能外部低速振蕩器,注意這里一般要先判斷 RCC_BDCR 的 LSERDY位來(lái)確定低速振蕩器已經(jīng)就緒了才開(kāi)始下面的操作。

備份區(qū)域復(fù)位的函數(shù)是:


開(kāi)啟外部低速振蕩器的函數(shù)是:

rcu_osci_on(RCU_LXTAL);// 開(kāi)啟外部低速振蕩器

4)選擇 RTC 時(shí)鐘,并使能。

庫(kù)函數(shù)中,選擇 RTC 時(shí)鐘的函數(shù)是:

rcu_rtc_clock_config(RCU_RTCSRC_LXTAL); //選擇LXTAL作為 RTC 時(shí)鐘

對(duì)于 RTC 時(shí)鐘的選擇使能 RTC 時(shí)鐘的函數(shù)是:

rcu_periph_clock_enable(RCU_RTC); //使能 RTC 時(shí)鐘

5)設(shè)置 RTC 的分頻,以及配置 RTC 時(shí)鐘。

在開(kāi)啟了 RTC 時(shí)鐘之后,我們要做的就是設(shè)置 RTC 時(shí)鐘的分頻數(shù),通過(guò) RTC_PSCH 和RTC_PSCL 來(lái)設(shè)置,然后等待 RTC 寄存器操作完成,并同步之后,設(shè)置秒鐘中斷。然后設(shè)置RTC 的允許配置位( RTC_CTL的 CMF 位),設(shè)置時(shí)間(其實(shí)就是設(shè)置 RTC_CNTH 和 RTC_CNTL兩個(gè)寄存器)。

下面我們一一這些步驟用到的庫(kù)函數(shù):

在進(jìn)行 RTC 配置之前首先要打開(kāi)允許配置位(CMF),庫(kù)函數(shù)是:

rtc_configuration_mode_enter ();/// 允許配置

在配置完成之后,千萬(wàn)別忘記更新配置同時(shí)退出配置模式,函數(shù)是:

rtc_configuration_mode_exit ();//退出配置模式,更新配置

設(shè)置 RTC 時(shí)鐘分頻數(shù), 庫(kù)函數(shù)是:

void rtc_prescaler_set(uint32_t psc)

這個(gè)函數(shù)只有一個(gè)入口參數(shù),就是 RTC 時(shí)鐘的分頻數(shù),很好理解。

然后是設(shè)置秒中斷允許,RTC 使能中斷的函數(shù)是:

void rtc_interrupt_enable(uint32_t interrupt)

這個(gè)函數(shù)的第一個(gè)參數(shù)是設(shè)置秒中斷類(lèi)型,這些通過(guò)宏定義定義的。 對(duì)于使能秒中斷方法是:

rtc_interrupt_enable(RTC_INT_SECOND); //使能 RTC 秒中斷

下一步便是設(shè)置時(shí)間了,設(shè)置時(shí)間實(shí)際上就是設(shè)置 RTC 的計(jì)數(shù)值,時(shí)間與計(jì)數(shù)值之間是需要換算的,當(dāng)然也可先不設(shè)置。庫(kù)函數(shù)中設(shè)置 RTC 計(jì)數(shù)值的方法是:

void rtc_counter_set(uint32_t cnt)

通過(guò)這個(gè)函數(shù)直接設(shè)置 RTC 計(jì)數(shù)值。

6)更新配置,設(shè)置 RTC 中斷分組。

在設(shè)置完時(shí)鐘之后,我們將配置更新同時(shí)退出配置模式,這里還是通過(guò) RTC_CTL的CMF來(lái)實(shí)現(xiàn)。庫(kù)函數(shù)的方法是:

rtc_configuration_mode_exit ();//退出配置模式,更新配置

在退出配置模式更新配置之后我們?cè)趥浞輩^(qū)域 BKP_DATA0中寫(xiě)入 0xA5A5代表我們已經(jīng)初始化過(guò)時(shí)鐘了,下次開(kāi)機(jī)(或復(fù)位)的時(shí)候,先讀取 BKP_DATA0的值,然后判斷是否是 0xA5A5來(lái)決定是不是要配置。接著我們配置 RTC 的秒鐘中斷,并進(jìn)行分組。

往備份區(qū)域?qū)懹脩?hù)數(shù)據(jù)的函數(shù)是:

void bkp_data_write(bkp_data_register_enum register_number, uint16_t data)

這個(gè)函數(shù)的第一個(gè)參數(shù)就是寄存器的標(biāo)號(hào)了,這個(gè)是通過(guò)宏定義定義的。 比如我們要往BKP_DATA0 寫(xiě)入 0xA5A5,方法是:

bkp_data_write(BKP_DATA_0, 0xA5A5);

同時(shí),有寫(xiě)便有讀,讀取備份區(qū)域指定寄存器的用戶(hù)數(shù)據(jù)的函數(shù)是:

uint16_t bkp_data_read(bkp_data_register_enum register_number)

這個(gè)函數(shù)就很好理解了,這里不做過(guò)多講解。

設(shè)置中斷分組的方法之前已經(jīng)詳細(xì)講解過(guò),這里不做重復(fù)講解。

7)編寫(xiě)中斷服務(wù)函數(shù)。

最后,我們要編寫(xiě)中斷服務(wù)函數(shù),在秒鐘中斷產(chǎn)生的時(shí)候,讀取當(dāng)前的時(shí)間值。

/**
  * @brief  This function handles RTC exception.
  * @param  None
  * @retval None
  */
void RTC_IRQHandler(void)
{
   if(rtc_flag_get(RTC_FLAG_SECOND)!=RESET)//讀取中斷標(biāo)志
   {
        rtc_flag_clear(RTC_FLAG_SECOND);//清楚中斷標(biāo)志
        tim_bz=1;//秒中斷標(biāo)志
   }
}

完成的配如下:

/**
  * @brief  RTC配置
  * @param  None
  * @retval None
  */
void rtc_configuration(void)
{
    /* enable PMU and BKPI clocks 使能電源時(shí)鐘和備份區(qū)域時(shí)鐘*/
    rcu_periph_clock_enable(RCU_BKPI);
    rcu_periph_clock_enable(RCU_PMU);

    /* allow access to BKP domain 允許訪(fǎng)問(wèn)BKP區(qū)域*/
    pmu_backup_write_enable();

    //復(fù)位備份區(qū)域,開(kāi)啟外部低速振蕩器
    /* reset backup domain */
    bkp_deinit();

    /* enable LXTAL 使能外部低速晶振 32.768K */
    rcu_osci_on(RCU_LXTAL);
    /* wait till LXTAL is ready */
    rcu_osci_stab_wait(RCU_LXTAL);

    //選擇 RTC 時(shí)鐘,并使能
    /* select RCU_LXTAL as RTC clock source */
    rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);

    /* enable RTC Clock 使能RTC時(shí)鐘	 */
    rcu_periph_clock_enable(RCU_RTC);

    rtc_configuration_mode_enter();

    /* wait for RTC registers synchronization */
    rtc_register_sync_wait();

    /* wait until last write operation on RTC registers has finished 等待寫(xiě)RTC寄存器完成*/
    rtc_lwoff_wait();

    /* enable the RTC second interrupt 使能RTC秒中斷*/
    rtc_interrupt_enable(RTC_INT_SECOND);

    /* wait until last write operation on RTC registers has finished 等待寫(xiě)RTC寄存器完成*/
    rtc_lwoff_wait();

    /* set RTC prescaler: set RTC period to 1s 設(shè)置預(yù)分頻*/
    rtc_prescaler_set(32767);

    /* wait until last write operation on RTC registers has finished 等待寫(xiě)RTC寄存器完成*/
    rtc_lwoff_wait();

    nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);
    nvic_irq_enable(RTC_IRQn, 1, 0);
}

/**
  * @brief  RTC時(shí)鐘初始化
  * @param  None
  * @retval None
  */
void clock_init(void)
{
    if(0xA5A5 != bkp_data_read(BKP_DATA_0))
    {
        //第一次運(yùn)行  初始化設(shè)置
        rtc_configuration();//RTC初始化
        /* wait until last write operation on RTC registers has finished */
        rtc_lwoff_wait();
        /* change the current time */
        rtc_counter_set(0);
        /* wait until last write operation on RTC registers has finished */
        rtc_lwoff_wait();
        rtc_lwoff_wait();//等待寫(xiě)RTC寄存器完成	  
        rtc_lwoff_wait();//等待寫(xiě)RTC寄存器完成
        bkp_data_write(BKP_DATA_0, 0xA5A5);//寫(xiě)配置標(biāo)志
    }
    else
    {
        /* check if the power on reset flag is set */
        if(rcu_flag_get(RCU_FLAG_PORRST) != RESET)
        {
            printf("\\r\\n\\n Power On Reset occurred....");
        }
        else if(rcu_flag_get(RCU_FLAG_SWRST) != RESET)
        {
            /* check if the pin reset flag is set */
            printf("\\r\\n\\n External Reset occurred....");
        }
        printf("\\r\\n No need to configure RTC....");
        rtc_register_sync_wait();//等待RTC寄存器同步
        rtc_interrupt_enable(RTC_INT_SECOND);//使能RTC秒中斷
        rtc_lwoff_wait();//等待寫(xiě)RTC寄存器完成
    }
    rtc_configuration_mode_exit();//退出配置模式, 更新配置
    rcu_all_reset_flag_clear();//清除復(fù)位標(biāo)志;
}

主函數(shù)代碼如下:

/*
    brief      main function
    param[in]  none
    param[out] none
    retval     none
*/
int main(void)
{
    uint32_t TimeData=0,hh=0,mm=0,ss=0;

    //usart init 115200 8-N-1
    com_init(COM1, 115200, 0, 1);

    rtc_configuration();
    clock_init();

    while(1)
    {
        if(tim_bz==1)
        {
            tim_bz=0;
            TimeData=rtc_counter_get();
            hh=	TimeData/3600;
            mm = (TimeData%3600)/60;
            ss = TimeData%60;
            printf("Time: %0.2d:%0.2d:%0.2d\\r\\n",hh,mm,ss);  
        }
    }
}

4 實(shí)驗(yàn)現(xiàn)象

打開(kāi)串口助手,打印信息如下:

1684418638740f10vcepb8y

這里沒(méi)有設(shè)置初始時(shí)間,時(shí)分秒是從0開(kāi)始的。

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • RTC
    RTC
    +關(guān)注

    關(guān)注

    2

    文章

    522

    瀏覽量

    66228
  • Cortex-M
    +關(guān)注

    關(guān)注

    2

    文章

    227

    瀏覽量

    29708
  • GD32
    +關(guān)注

    關(guān)注

    7

    文章

    403

    瀏覽量

    24111
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    GD32開(kāi)發(fā)實(shí)戰(zhàn)指南(基礎(chǔ)) 1 開(kāi)發(fā)環(huán)境搭建

    開(kāi)發(fā)環(huán)境: MDK:Keil 5.30 開(kāi)發(fā)板:GD32F207I-EVAL MCU:GD32F207IK 1 GD32F207I-EVAL
    的頭像 發(fā)表于 05-07 23:35 ?1.1w次閱讀
    <b class='flag-5'>GD32</b><b class='flag-5'>開(kāi)發(fā)</b><b class='flag-5'>實(shí)戰(zhàn)</b><b class='flag-5'>指南</b>(基礎(chǔ)<b class='flag-5'>篇</b>) <b class='flag-5'>第</b>1<b class='flag-5'>章</b> <b class='flag-5'>開(kāi)發(fā)</b>環(huán)境搭建

    GD32開(kāi)發(fā)實(shí)戰(zhàn)指南(基礎(chǔ)) 4 GD32啟動(dòng)流程詳解(Keil版)

    ,所有的一切都需要由開(kāi)發(fā)者來(lái)設(shè)置,這里處理器是沒(méi)有堆棧,沒(méi)有中斷,更沒(méi)有外圍設(shè)備,這些工作是需要軟件來(lái)指定的,而且不同的CPU類(lèi)型、不同大小的內(nèi)存和不同種類(lèi)的外設(shè),其初始化工作都是不同的。本文將以GD32F207IK (基于Cortex-M3)為例進(jìn)行講解。
    的頭像 發(fā)表于 05-10 09:00 ?1.6w次閱讀
    <b class='flag-5'>GD32</b><b class='flag-5'>開(kāi)發(fā)</b><b class='flag-5'>實(shí)戰(zhàn)</b><b class='flag-5'>指南</b>(基礎(chǔ)<b class='flag-5'>篇</b>) <b class='flag-5'>第</b>4<b class='flag-5'>章</b> <b class='flag-5'>GD32</b>啟動(dòng)流程詳解(Keil版)

    GD32開(kāi)發(fā)實(shí)戰(zhàn)指南(基礎(chǔ)) 7 定時(shí)器

    系統(tǒng)滴答定時(shí)器一般用來(lái)提供“心跳”作用,而GD32定時(shí)器最基本功能也是定時(shí),可以設(shè)置不同時(shí)間長(zhǎng)度的定時(shí)。定時(shí)器除了最基本的定時(shí)功能外,定時(shí)器與GPIO有掛鉤使得它可以發(fā)揮強(qiáng)大的作用,比如可以輸出
    的頭像 發(fā)表于 05-11 09:00 ?1.2w次閱讀
    <b class='flag-5'>GD32</b><b class='flag-5'>開(kāi)發(fā)</b><b class='flag-5'>實(shí)戰(zhàn)</b><b class='flag-5'>指南</b>(基礎(chǔ)<b class='flag-5'>篇</b>) <b class='flag-5'>第</b>7<b class='flag-5'>章</b> 定時(shí)器

    GD32開(kāi)發(fā)實(shí)戰(zhàn)指南(基礎(chǔ)) 8 定時(shí)器

    開(kāi)發(fā)環(huán)境: MDK:Keil 5.30 開(kāi)發(fā)板:GD32F207I-EVAL MCU:GD32F207IK 1 PWM輸出的工作原理 脈沖寬度調(diào)制(PWM) ,是英文“Pulse Wi
    的頭像 發(fā)表于 05-12 22:14 ?7789次閱讀
    <b class='flag-5'>GD32</b><b class='flag-5'>開(kāi)發(fā)</b><b class='flag-5'>實(shí)戰(zhàn)</b><b class='flag-5'>指南</b>(基礎(chǔ)<b class='flag-5'>篇</b>) <b class='flag-5'>第</b>8<b class='flag-5'>章</b> 定時(shí)器

    GD32開(kāi)發(fā)實(shí)戰(zhàn)指南(基礎(chǔ)) 9 呼吸燈

    開(kāi)發(fā)環(huán)境: MDK:Keil 5.30 開(kāi)發(fā)板:GD32F207I-EVAL MCU:GD32F207IK 1 呼吸燈的工作原理 呼吸燈,就是指燈光設(shè)備的亮度隨著時(shí)間由暗到亮逐漸增強(qiáng),
    的頭像 發(fā)表于 05-12 22:22 ?4766次閱讀
    <b class='flag-5'>GD32</b><b class='flag-5'>開(kāi)發(fā)</b><b class='flag-5'>實(shí)戰(zhàn)</b><b class='flag-5'>指南</b>(基礎(chǔ)<b class='flag-5'>篇</b>) <b class='flag-5'>第</b>9<b class='flag-5'>章</b> 呼吸燈

    GD32開(kāi)發(fā)實(shí)戰(zhàn)指南(基礎(chǔ)) 11 CPU的高級(jí)代理-DMA

    或者存儲(chǔ)器和存儲(chǔ)器之間的高速數(shù)據(jù)傳輸,因而被廣泛地使用。早在 8086 的應(yīng)用中就已經(jīng)有 Intel 的 8237 這種典型的 DMA 控制器,而 GD32的 DMA 則是以類(lèi)似外設(shè)的形式添加到 Cortex 內(nèi)核之外的??梢哉f(shuō),DMA就是CPU的高級(jí)代理,DMA大大減輕了CPU的負(fù)擔(dān)。
    的頭像 發(fā)表于 05-16 08:59 ?3793次閱讀
    <b class='flag-5'>GD32</b><b class='flag-5'>開(kāi)發(fā)</b><b class='flag-5'>實(shí)戰(zhàn)</b><b class='flag-5'>指南</b>(基礎(chǔ)<b class='flag-5'>篇</b>) <b class='flag-5'>第</b>11<b class='flag-5'>章</b> CPU的高級(jí)代理-DMA

    GD32開(kāi)發(fā)實(shí)戰(zhàn)指南(基礎(chǔ)) 12 ADC

    GD32F2系列有 3 個(gè)逐次逼近型的ADC,精度為 12 位,有18個(gè)多路復(fù)用通道,可以轉(zhuǎn)換來(lái)自16個(gè)外部通道和2個(gè)內(nèi)部通道的模擬信號(hào)。其中ADC0 和 ADC1都有 16 個(gè)外部通道, ADC2
    的頭像 發(fā)表于 05-16 09:03 ?1.1w次閱讀
    <b class='flag-5'>GD32</b><b class='flag-5'>開(kāi)發(fā)</b><b class='flag-5'>實(shí)戰(zhàn)</b><b class='flag-5'>指南</b>(基礎(chǔ)<b class='flag-5'>篇</b>) <b class='flag-5'>第</b>12<b class='flag-5'>章</b> ADC

    GD32開(kāi)發(fā)實(shí)戰(zhàn)指南(基礎(chǔ)) 14 內(nèi)部溫度傳感器

    GD32 有一個(gè)內(nèi)部的溫度傳感器,可以用來(lái)測(cè)量 CPU 及周?chē)臏囟?TA)。該溫度傳感器在內(nèi)部和 ADCx_IN16 輸入通道相連接,此通道把傳感器輸出的電壓轉(zhuǎn)換成數(shù)字值。溫度傳感器模擬輸入
    的頭像 發(fā)表于 05-17 08:58 ?5165次閱讀
    <b class='flag-5'>GD32</b><b class='flag-5'>開(kāi)發(fā)</b><b class='flag-5'>實(shí)戰(zhàn)</b><b class='flag-5'>指南</b>(基礎(chǔ)<b class='flag-5'>篇</b>) <b class='flag-5'>第</b>14<b class='flag-5'>章</b> 內(nèi)部溫度傳感器

    GD32開(kāi)發(fā)實(shí)戰(zhàn)指南(基礎(chǔ)) 15 低功耗

    GD32的工作電壓(VDD)為2.0~3.6V。通過(guò)內(nèi)置的電壓調(diào)節(jié)器提供所需的1.8V電源。當(dāng)主電源VDD掉電后,通過(guò)VBAT腳為實(shí)時(shí)時(shí)鐘(RTC)和備份寄存器提供電源。
    的頭像 發(fā)表于 05-17 08:59 ?7946次閱讀
    <b class='flag-5'>GD32</b><b class='flag-5'>開(kāi)發(fā)</b><b class='flag-5'>實(shí)戰(zhàn)</b><b class='flag-5'>指南</b>(基礎(chǔ)<b class='flag-5'>篇</b>) <b class='flag-5'>第</b>15<b class='flag-5'>章</b> 低功耗

    GD32開(kāi)發(fā)實(shí)戰(zhàn)指南(基礎(chǔ)) 17 看門(mén)狗

    開(kāi)發(fā)環(huán)境: MDK:Keil 5.30 開(kāi)發(fā)板:GD32F207I-EVAL MCU:GD32F207IK GD32 有兩個(gè)看門(mén)狗, 一個(gè)是
    的頭像 發(fā)表于 06-03 16:00 ?1.1w次閱讀
    <b class='flag-5'>GD32</b><b class='flag-5'>開(kāi)發(fā)</b><b class='flag-5'>實(shí)戰(zhàn)</b><b class='flag-5'>指南</b>(基礎(chǔ)<b class='flag-5'>篇</b>) <b class='flag-5'>第</b>17<b class='flag-5'>章</b> 看門(mén)狗

    【圖書(shū)分享】《STM32庫(kù)開(kāi)發(fā)實(shí)戰(zhàn)指南

    16 CAN控制器第三部分 庫(kù)開(kāi)發(fā)高級(jí) 17 SDIO之SD卡驅(qū)動(dòng) 
    發(fā)表于 03-13 17:01

    GD32 MCU原理及固件庫(kù)開(kāi)發(fā)指南》 + 初讀感悟

    GD32 MCU原理固件庫(kù)開(kāi)發(fā)指南這本書(shū)內(nèi)容豐富,囊括了GD32中的所有外設(shè),書(shū)中首先介紹了如何使用MDK或IAR軟件搭建GD32工程環(huán)境,讓初學(xué)者能快速基于工程上手編程。書(shū)中主要對(duì)
    發(fā)表于 03-31 22:11

    GD32 MCU原理及固件庫(kù)開(kāi)發(fā)指南》+讀后感

    2介紹GD32 MCU快速入門(mén)與開(kāi)發(fā)平臺(tái)搭建的方法,包括對(duì)軟硬件開(kāi)發(fā)平臺(tái)、調(diào)試工具、GD32
    發(fā)表于 06-06 21:52

    GD32開(kāi)發(fā)實(shí)戰(zhàn)指南(基礎(chǔ)) 19 程序加密

    GD32通過(guò)讀取芯片唯一ID號(hào)來(lái)實(shí)現(xiàn)程序的保護(hù),防止被抄襲。96位的產(chǎn)品唯一身份標(biāo)識(shí)所提供的參考號(hào)碼對(duì)任意一個(gè)GD32微控制器
    的頭像 發(fā)表于 05-20 09:10 ?4054次閱讀
    <b class='flag-5'>GD32</b><b class='flag-5'>開(kāi)發(fā)</b><b class='flag-5'>實(shí)戰(zhàn)</b><b class='flag-5'>指南</b>(基礎(chǔ)<b class='flag-5'>篇</b>) <b class='flag-5'>第</b>19<b class='flag-5'>章</b> 程序加密

    GD32 MCU 入門(mén)教程】GD32 MCU 常見(jiàn)外設(shè)介紹(14)RTC 模塊介紹

    GD32 MCU內(nèi)部提供了一個(gè)RTC(實(shí)時(shí)時(shí)鐘)模塊,通過(guò)RTC可以實(shí)現(xiàn)日歷時(shí)鐘、鬧鐘等功能。RTC也可以用于深度睡眠或待機(jī)模式的低功耗喚醒。不同系列的
    的頭像 發(fā)表于 08-23 09:18 ?356次閱讀
    【<b class='flag-5'>GD32</b> MCU 入門(mén)教程】<b class='flag-5'>GD32</b> MCU 常見(jiàn)外設(shè)介紹(14)<b class='flag-5'>RTC</b> 模塊介紹