一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

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

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

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

第二十八章 RTC——實(shí)時(shí)時(shí)鐘

W55MH32 ? 來源:W55MH32 ? 作者:W55MH32 ? 2025-06-20 14:08 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

單芯片解決方案,開啟全新體驗(yàn)——W55MH32 高性能以太網(wǎng)單片機(jī)

W55MH32是WIZnet重磅推出的高性能以太網(wǎng)單片機(jī),它為用戶帶來前所未有的集成化體驗(yàn)。這顆芯片將強(qiáng)大的組件集于一身,具體來說,一顆W55MH32內(nèi)置高性能Arm? Cortex-M3核心,其主頻最高可達(dá)216MHz;配備1024KB FLASH與96KB SRAM,滿足存儲(chǔ)與數(shù)據(jù)處理需求;集成TOE引擎,包含WIZnet全硬件TCP/IP協(xié)議棧、內(nèi)置MAC以及PHY,擁有獨(dú)立的32KB以太網(wǎng)收發(fā)緩存,可供8個(gè)獨(dú)立硬件socket使用。如此配置,真正實(shí)現(xiàn)了All-in-One解決方案,為開發(fā)者提供極大便利。

在封裝規(guī)格上,W55MH32 提供了兩種選擇:QFN100和QFN68。

W55MH32L采用QFN100封裝版本,尺寸為12x12mm,其資源豐富,專為各種復(fù)雜工控場(chǎng)景設(shè)計(jì)。它擁有66個(gè)GPIO、3個(gè)ADC、12通道DMA、17個(gè)定時(shí)器、2個(gè)I2C、5個(gè)串口、2個(gè)SPI接口(其中1個(gè)帶I2S接口復(fù)用)、1個(gè)CAN、1個(gè)USB2.0以及1個(gè)SDIO接口。如此豐富的外設(shè)資源,能夠輕松應(yīng)對(duì)工業(yè)控制中多樣化的連接需求,無論是與各類傳感器、執(zhí)行器的通信,還是對(duì)復(fù)雜工業(yè)協(xié)議的支持,都能游刃有余,成為復(fù)雜工控領(lǐng)域的理想選擇。 同系列還有QFN68封裝的W55MH32Q版本,該版本體積更小,僅為8x8mm,成本低,適合集成度高的網(wǎng)關(guān)模組等場(chǎng)景,軟件使用方法一致。更多信息和資料請(qǐng)進(jìn)入網(wǎng)站或者私信獲取。

此外,本W(wǎng)55MH32支持硬件加密算法單元,WIZnet還推出TOE+SSL應(yīng)用,涵蓋TCP SSL、HTTP SSL以及 MQTT SSL等,為網(wǎng)絡(luò)通信安全再添保障。

為助力開發(fā)者快速上手與深入開發(fā),基于W55MH32L這顆芯片,WIZnet精心打造了配套開發(fā)板。開發(fā)板集成WIZ-Link芯片,借助一根USB C口數(shù)據(jù)線,就能輕松實(shí)現(xiàn)調(diào)試、下載以及串口打印日志等功能。開發(fā)板將所有外設(shè)全部引出,拓展功能也大幅提升,便于開發(fā)者全面評(píng)估芯片性能。

若您想獲取芯片和開發(fā)板的更多詳細(xì)信息,包括產(chǎn)品特性、技術(shù)參數(shù)以及價(jià)格等,歡迎訪問官方網(wǎng)頁,我們期待與您共同探索W55MH32的無限可能。

wKgZPGgbOfaANhwzACodXd3sVzg463.png

第二十八章 RTC——實(shí)時(shí)時(shí)鐘

本章參考資料:《W55MH32數(shù)據(jù)手冊(cè)》、《W55MH32參考手冊(cè)》的《電源控制PWR》及《實(shí)時(shí)時(shí)鐘RTC》章節(jié)。

1 RTC實(shí)時(shí)時(shí)鐘簡(jiǎn)介

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

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

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

2 RTC外設(shè)框圖剖析

RTC外設(shè)框圖如下:

wKgZO2gxiSqAKuc3AAMaVQnnMmg254.png

框圖中淺灰色的部分都是屬于備份域的,在VDD掉電時(shí)可在VBAT的驅(qū)動(dòng)下繼續(xù)運(yùn)行。 這部分僅包括RTC的分頻器,計(jì)數(shù)器,和鬧鐘控制器。若VDD電源有效,RTC可以觸發(fā)RTC_Second(秒中斷)、 RTC_Overflow(溢出事件)和RTC_Alarm(鬧鐘中斷)。從結(jié)構(gòu)圖可以分析到,其中的定時(shí)器溢出事件無法被配置為中斷。 若W55MH32原本處于待機(jī)狀態(tài),可由鬧鐘事件或WKUP事件(外部喚醒事件,屬于EXTI模塊,不屬于RTC)使它退出待機(jī)模式。 鬧鐘事件是在計(jì)數(shù)器RTC_CNT的值等于鬧鐘寄存器RTC_ALR的值時(shí)觸發(fā)的。

在備份域中所有寄存器都是16位的, RTC控制相關(guān)的寄存器也不例外。它的計(jì)數(shù)器RTC_CNT的32位由RTC_CNTL和RTC_CNTH兩個(gè)寄存器組成,分別保存定時(shí)計(jì)數(shù)值的低16位和高16位。 在配置RTC模塊的時(shí)鐘時(shí),通常把輸入的32768Hz的RTCCLK進(jìn)行32768分頻得到實(shí)際驅(qū)動(dòng)計(jì)數(shù)器的時(shí)鐘 TR_CLK =RTCCLK/32768= 1 Hz, 計(jì)時(shí)周期為1秒,計(jì)時(shí)器在TR_CLK的驅(qū)動(dòng)下計(jì)數(shù),即每秒計(jì)數(shù)器RTC_CNT的值加1。

由于備份域的存在,使得RTC核具有了完全獨(dú)立于APB1接口的特性, 也因此對(duì)RTC寄存器的訪問要遵守一定的規(guī)則。

系統(tǒng)復(fù)位后,默認(rèn)禁止訪問后備寄存器和RTC,防止對(duì)后備區(qū)域(BKP)的意外寫操作。 執(zhí)行以下操作使能對(duì)后備寄存器和RTC的訪問:

設(shè)置RCC_APB1ENR寄存器的PWREN和BKPEN位來使能電源和后備接口時(shí)鐘。

設(shè)置PWR_CR寄存器的DBP位使能對(duì)后備寄存器和RTC的訪問。

設(shè)置后備寄存器為可訪問后,在第一次通過APB1接口訪問RTC時(shí),因?yàn)闀r(shí)鐘頻率的差異,所以必須等待APB1與RTC外設(shè)同步, 確保被讀取出來的RTC寄存器值是正確的。若在同步之后,一直沒有關(guān)閉APB1的RTC外設(shè)接口,就不需要再次同步了。

如果內(nèi)核要對(duì)RTC寄存器進(jìn)行任何的寫操作,在內(nèi)核發(fā)出寫指令后,RTC模塊在3個(gè)RTCCLK時(shí)鐘之后,才開始正式的寫RTC寄存器操作。 由于RTCCLK的頻率比內(nèi)核主頻低得多,所以每次操作后必須要檢查RTC關(guān)閉操作標(biāo)志位RTOFF,當(dāng)這個(gè)標(biāo)志被置1時(shí),寫操作才正式完成。

當(dāng)然,以上的操作都具有庫函數(shù),讀者不必具體地查閱寄存器。

3 UNIX時(shí)間戳

在使用RTC外設(shè)前,還需要引入U(xiǎn)NIX時(shí)間戳的概念。

如果從現(xiàn)在起,把計(jì)數(shù)器RTC_CNT的計(jì)數(shù)值置0,然后每秒加1, RTC_CNT什么時(shí)候會(huì)溢出呢?由于RTC_CNT是32位寄存器, 可存儲(chǔ)的最大值為(232-1),即這樣計(jì)時(shí)的話,在232秒后溢出,即它將在今后的136年時(shí)溢出:

N = 232/365/24/60/60 ≈136年

假如某個(gè)時(shí)刻讀取到計(jì)數(shù)器的數(shù)值為X = 60*60*24*2,即兩天時(shí)間的秒數(shù),而假設(shè)又知道計(jì)數(shù)器是在2011年1月1日的0時(shí)0分0秒置0的, 那么就可以根據(jù)計(jì)數(shù)器的這個(gè)相對(duì)時(shí)間數(shù)值,計(jì)算得這個(gè)X時(shí)刻是2011年1月3日的0時(shí)0分0秒了。而計(jì)數(shù)器則會(huì)在(2011+136)年左右溢出, 也就是說到了(2011+136)年時(shí),如果我們還在使用這個(gè)計(jì)數(shù)器提供時(shí)間的話就會(huì)出現(xiàn)問題。在這個(gè)例子中,定時(shí)器被置0的這個(gè)時(shí)間被稱為計(jì)時(shí)元年, 相對(duì)計(jì)時(shí)元年經(jīng)過的秒數(shù)稱為時(shí)間戳,也就是計(jì)數(shù)器中的值。

大多數(shù)操作系統(tǒng)都是利用時(shí)間戳和計(jì)時(shí)元年來計(jì)算當(dāng)前時(shí)間的,而這個(gè)時(shí)間戳和計(jì)時(shí)元年大家都取了同一個(gè)標(biāo)準(zhǔn)——UNIX時(shí)間戳和UNIX計(jì)時(shí)元年。 UNIX計(jì)時(shí)元年被設(shè)置為格林威治時(shí)間1970年1月1日0時(shí)0分0秒,大概是為了紀(jì)念UNIX的誕生的時(shí)代吧, 而UNIX時(shí)間戳即為當(dāng)前時(shí)間相對(duì)于UNIX計(jì)時(shí)元年經(jīng)過的秒數(shù)。因?yàn)閡nix時(shí)間戳主要用來表示當(dāng)前時(shí)間或者和電腦有關(guān)的日志時(shí)間(如文件創(chuàng)立時(shí)間,log發(fā)生時(shí)間等), 考慮到所有電腦文件不可能在1970年前創(chuàng)立,所以用unix時(shí)間戳很少用來表示1970前的時(shí)間。

在這個(gè)計(jì)時(shí)系統(tǒng)中,使用的是有符號(hào)的32位整型變量來保存UNIX時(shí)間戳的,即實(shí)際可用計(jì)數(shù)位數(shù)比我們上面例子中的少了一位, 少了這一位,UNIX計(jì)時(shí)元年也相對(duì)提前了,這個(gè)計(jì)時(shí)方法在2038年1月19日03時(shí)14分07秒將會(huì)發(fā)生溢出,這個(gè)時(shí)間離我們并不遠(yuǎn)。 由于UNIX時(shí)間戳被廣泛應(yīng)用到各種系統(tǒng)中,溢出可能會(huì)導(dǎo)致系統(tǒng)發(fā)生嚴(yán)重錯(cuò)誤,屆時(shí),很可能會(huì)重演一次“千年蟲”的問題,所以在設(shè)計(jì)預(yù)期壽命較長(zhǎng)的設(shè)備需要注意。

在網(wǎng)絡(luò)上搜索“UNIX時(shí)間戳”可找到一些網(wǎng)站提供當(dāng)前實(shí)時(shí)的UNIX時(shí)間戳,見下圖某網(wǎng)站顯示的實(shí)時(shí)UNIX時(shí)間戳:

wKgZPGgxiSmASso2AABBZKpowfM340.png

4 與RTC控制相關(guān)的庫函數(shù)

W55MH32標(biāo)準(zhǔn)庫對(duì)RTC控制提供了完善的函數(shù),使用它們可以方便地進(jìn)行控制,本小節(jié)對(duì)這些內(nèi)容進(jìn)行講解。

4.1 等待時(shí)鐘同步和操作完成

RTC區(qū)域的時(shí)鐘比APB時(shí)鐘慢,訪問前需要進(jìn)行時(shí)鐘同步,只要調(diào)用庫函數(shù)RTC_WaitForSynchro()即可,而如果修改了RTC的寄存器, 又需要調(diào)用RTC_WaitForLastTask()函數(shù)確保數(shù)據(jù)已寫入,見代碼清單:RTC-1 :

代碼清單:RTC-1 等待時(shí)鐘同步和操作完成

/**
* @brief  等待RTC寄存器與APB時(shí)鐘同步 (RTC_CNT, RTC_ALR and RTC_PRL)
* @note   在APB時(shí)鐘復(fù)位或停止后,在對(duì)RTC寄存器的任何操作前,必須調(diào)用本函數(shù)
* @param  None
* @retval None
*/
void RTC_WaitForSynchro(void)
{
    /* 清除 RSF 寄存器位 */
    RTC->CRL &= (uint16_t)~RTC_FLAG_RSF;
    /* 等待至 RSF 寄存器位為SET */
    while ((RTC->CRL & RTC_FLAG_RSF) == (uint16_t)RESET) {
    }
}

/**
* @brief  等待上一次對(duì) RTC寄存器的操作完成
* @note   修改RTC寄存器后,必須調(diào)用本函數(shù)
* @param  None
* @retval None
*/
void RTC_WaitForLastTask(void)
{
    /* 等待至 RTOFF 寄存器位為SET*/
    while ((RTC->CRL & RTC_FLAG_RTOFF) == (uint16_t)RESET) {
    }
}

這兩個(gè)庫函數(shù)主要通過while循環(huán)檢測(cè)RTC控制寄存器的RSF和RTOFF位實(shí)現(xiàn)等待功能。

4.2 使能備份域涉及RTC配置

默認(rèn)情況下,RTC所屬的備份域禁止訪問,可使用庫函數(shù)PWR_BackupAccessCmd()使能訪問,見代碼清單:RTC-2 :

代碼清單:RTC-2 使能備份域訪問

/**
* @brief  使能對(duì) RTC 和 backup 寄存器的訪問.
* @param   ENABLE 或 DISABLE.
* @retval None
*/
void PWR_BackupAccessCmd(FunctionalState NewState)
{
    *(__IO uint32_t *) CR_DBP_BB = (uint32_t)NewState;
}

該函數(shù)通過PWR_CR寄存器的DBP位使能訪問,使能后才可以訪問RTC相關(guān)的寄存器,然而若希望修改RTC的寄存器, 還需要進(jìn)一步使能RTC控制寄存器的CNF位使能寄存器配置,見代碼清單:RTC-3:

代碼清單:RTC-3 進(jìn)入和退出RTC配置模式

/**
* @brief  進(jìn)入 RTC 配置模式 .
* @param  None
* @retval None
*/
void RTC_EnterConfigMode(void)
{
    /* 設(shè)置 CNF 位進(jìn)入配置模式 */
    RTC->CRL |= RTC_CRL_CNF;
}

/**
* @brief  退出 RTC 配置模式 .
* @param  None
* @retval None
*/
void RTC_ExitConfigMode(void)
{
    /* 清空  CNF 位退出配置模式 */
    RTC->CRL &= (uint16_t)~((uint16_t)RTC_CRL_CNF);
}

這兩個(gè)庫函數(shù)分別提供了進(jìn)入和退出RTC寄存器的配置模式,一般情況下它們由庫函數(shù)調(diào)用。

4.3 設(shè)置RTC時(shí)鐘分頻

使用RCC相關(guān)的庫函數(shù)選擇RTC使用的時(shí)鐘后,可以使用庫函數(shù)RTC_SetPrescaler()進(jìn)行分頻, 一般會(huì)把RTC時(shí)鐘分頻得到1Hz的時(shí)鐘,見代碼清單:RTC-4:

代碼清單:RTC-4 設(shè)置RTC時(shí)鐘分頻

/**
* @brief  設(shè)置RTC分頻配置
* @param  PrescalerValue: RTC 分頻值.
* @retval None
*/
void RTC_SetPrescaler(uint32_t PrescalerValue)
{
    RTC_EnterConfigMode();
    /* 設(shè)置 RTC 分頻值的 MSB  */
    RTC->PRLH = (PrescalerValue & PRLH_MSB_MASK) >> 16;
    /* 設(shè)置 RTC 分頻值的 LSB  */
    RTC->PRLL = (PrescalerValue & RTC_LSB_MASK);
    RTC_ExitConfigMode();
}

在函數(shù)中,使用RTC_EnterConfigMode()和RTC_ExitConfigMode()進(jìn)入和退出RTC寄存器配置模式, 配置時(shí)把函數(shù)參數(shù)PrescalerValue寫入到RTC的PRLH和PRLL寄存器中。

4.4 設(shè)置、獲取RTC計(jì)數(shù)器及鬧鐘

RTC外設(shè)中最重要的就是計(jì)數(shù)器以及鬧鐘寄存器了,它們可以使用RTC_SetCounter()、RTC_GetCounter()以及RTC_SetAlarm()庫函數(shù)操作,見代碼清單:RTC-5:

代碼清單:RTC-5 設(shè)置RTC計(jì)數(shù)器及鬧鐘

/**
* @brief  設(shè)置 RTC 計(jì)數(shù)器的值 .
* @param  CounterValue: 要設(shè)置的RTC計(jì)數(shù)器值.
* @retval None
*/
void RTC_SetCounter(uint32_t CounterValue)
{
    RTC_EnterConfigMode();
    /* 設(shè)置 RTC 計(jì)數(shù)器的 MSB  */
    RTC->CNTH = CounterValue >> 16;
    /* 設(shè)置 RTC 計(jì)數(shù)器的 LSB  */
    RTC->CNTL = (CounterValue & RTC_LSB_MASK);
    RTC_ExitConfigMode();
}

/**
* @brief  獲取 RTC 計(jì)數(shù)器的值 .
* @param  None
* @retval 返回RTC計(jì)數(shù)器的值
*/
uint32_t RTC_GetCounter(void)
{
    uint16_t tmp = 0;
    tmp = RTC->CNTL;
    return (((uint32_t)RTC->CNTH ALRH = AlarmValue >> 16;
    /* 設(shè)置 RTC 鬧鐘的 LSB  */
    RTC->ALRL = (AlarmValue & RTC_LSB_MASK);
    RTC_ExitConfigMode();
}

利用RTC_SetCounter()可以向RTC的計(jì)數(shù)器寫入新數(shù)值,通常這些數(shù)值被設(shè)置為時(shí)間戳以更新時(shí)間。

RTC_GetCounter()函數(shù)則用于在RTC正常運(yùn)行時(shí)獲取當(dāng)前計(jì)數(shù)器的值以獲取當(dāng)前時(shí)間。

RTC_SetAlarm()函數(shù)用于配置鬧鐘時(shí)間,當(dāng)計(jì)數(shù)器的值與鬧鐘寄存器的值相等時(shí), 可產(chǎn)生鬧鐘事件或中斷,該事件可以把睡眠、停止和待機(jī)模式的W55MH32芯片喚醒。

5 實(shí)時(shí)時(shí)鐘

5.1 代碼解析

1.頭文件包含

#include 
#include 
#include 
#include "delay.h"
#include "w55mh32.h"

這里包含了標(biāo)準(zhǔn)庫的頭文件stdlib.h、string.h和stdio.h,以及自定義的頭文件delay.h和w55mh32.h。

2.全局變量和函數(shù)聲明

USART_TypeDef *USART_TEST = USART1;

void UART_Configuration(uint32_t bound);
void NVIC_Configuration(void);
void RCC_ClkConfiguration(void);
void RTC_Configuration(void);
void Time_Adjust(void);
void Time_Show(void);

__IO uint32_t TimeDisplay = 0;

USART_TEST:指定使用的串口為USART1。

聲明了一系列函數(shù),用于串口配置、中斷向量表配置、時(shí)鐘配置、RTC 配置、時(shí)間調(diào)整和顯示。

TimeDisplay:一個(gè)易變的全局變量,用于標(biāo)記是否需要顯示時(shí)間。

3.main()函數(shù)

int main(void)
{
    RCC_ClocksTypeDef clocks;

    delay_init();

    RCC_ClkConfiguration();

    UART_Configuration(115200);
    printf("RTC Calendar Test.n");
    RCC_GetClocksFreq(&clocks);

    printf("n");
    printf("SYSCLK: %3.1fMhz, HCLK: %3.1fMhz, PCLK1: %3.1fMhz, PCLK2: %3.1fMhz, ADCCLK: %3.1fMhzn",
           (float)clocks.SYSCLK_Frequency / 1000000, (float)clocks.HCLK_Frequency / 1000000,
           (float)clocks.PCLK1_Frequency / 1000000, (float)clocks.PCLK2_Frequency / 1000000, (float)clocks.ADCCLK_Frequency / 1000000);

    NVIC_Configuration();
    if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5)
    {
        printf("rRTC not yet configured....n");
        RTC_Configuration();

        printf("RTC configured....n");

        Time_Adjust();
        BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);
    }
    else
    {
        if (RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET)
        {
            printf("Power On Reset occurred....n");
        }
        else if (RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET)
        {
            printf("External Reset occurred....n");
        }

        printf("No need to configure RTC....n");
        RTC_WaitForSynchro();

        RTC_ITConfig(RTC_IT_SEC, ENABLE);
        RTC_WaitForLastTask();
    }

    RCC_ClearFlag();

    Time_Show();

    while (1);
}

初始化延時(shí)函數(shù)delay_init()。

配置系統(tǒng)時(shí)鐘RCC_ClkConfiguration()。

配置串口UART_Configuration(115200),并輸出測(cè)試信息。

獲取系統(tǒng)時(shí)鐘頻率并輸出。

配置中斷向量表NVIC_Configuration()。

檢查備份寄存器BKP_DR1的值,如果不等于0xA5A5,則進(jìn)行 RTC 配置和時(shí)間調(diào)整;否則,根據(jù)復(fù)位標(biāo)志輸出相應(yīng)信息,并使能 RTC 秒中斷。

清除 RCC 標(biāo)志位。

進(jìn)入Time_Show()函數(shù),循環(huán)顯示時(shí)間。

最后進(jìn)入無限循環(huán)。

4.Time_Display()函數(shù)

void Time_Display(uint32_t TimeVar)
{
    uint32_t THH = 0, TMM = 0, TSS = 0;

    if (RTC_GetCounter() == 0x0001517F)
    {
        RTC_SetCounter(0x0);
        RTC_WaitForLastTask();
    }

    THH = TimeVar / 3600;
    TMM = (TimeVar % 3600) / 60;
    TSS = (TimeVar % 3600) % 60;

    printf("Time: %0.2d:%0.2d:%0.2dn", THH, TMM, TSS);
}

該函數(shù)用于將秒數(shù)轉(zhuǎn)換為小時(shí)、分鐘和秒,并輸出當(dāng)前時(shí)間。如果 RTC 計(jì)數(shù)器達(dá)到0x0001517F,則將其重置為0。

5.Time_Show()函數(shù)

void Time_Show(void)
{
    printf("nr");
    while (1)
    {
        if (TimeDisplay == 1)
        {
            Time_Display(RTC_GetCounter());
            TimeDisplay = 0;
        }
    }
}

該函數(shù)進(jìn)入一個(gè)無限循環(huán),當(dāng)TimeDisplay為1時(shí),調(diào)用Time_Display()函數(shù)顯示當(dāng)前時(shí)間,并將TimeDisplay重置為0。

6.RTC_Configuration()函數(shù)

void RTC_Configuration(void)
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);

    PWR_BackupAccessCmd(ENABLE);

    BKP_DeInit();

    RCC_LSICmd(ENABLE);
    while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
    {
    }

    RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);

    RCC_RTCCLKCmd(ENABLE);

    RTC_WaitForSynchro();

    RTC_WaitForLastTask();

    RTC_ITConfig(RTC_IT_SEC, ENABLE);

    RTC_WaitForLastTask();

    RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) */

    RTC_WaitForLastTask();
}

該函數(shù)用于配置 RTC,包括使能電源和備份域時(shí)鐘、允許訪問備份域、復(fù)位備份寄存器、使能低速內(nèi)部時(shí)鐘(LSI)、選擇 RTC 時(shí)鐘源、使能 RTC 時(shí)鐘、等待 RTC 同步、使能 RTC 秒中斷和設(shè)置 RTC 預(yù)分頻器。

7.USART_Scanf()函數(shù)

uint8_t USART_Scanf(uint32_t value)
{
    uint32_t index  = 0;
    uint32_t tmp[2] = {0, 0};

    while (index < 2)
    {
        while (USART_GetFlagStatus(USART_TEST, USART_FLAG_RXNE) == RESET)
        {
        }
        tmp[index++] = (USART_ReceiveData(USART_TEST));
        if ((tmp[index - 1] < 0x30) || (tmp[index - 1] > 0x39))
        {
            printf("nrPlease enter valid number between 0 and 9");
            index--;
        }
    }
    index = (tmp[1] - 0x30) + ((tmp[0] - 0x30) * 10);

    if (index > value)
    {
        printf("nrPlease enter valid number between 0 and %d", value);
        return 0xFF;
    }
    return index;
}

該函數(shù)用于從串口讀取兩個(gè)數(shù)字字符,并將其轉(zhuǎn)換為一個(gè)兩位數(shù)的整數(shù)。如果輸入的字符不是數(shù)字或超出了指定范圍,則提示用戶重新輸入。

8.Time_Regulate()函數(shù)

uint32_t Time_Regulate(void)
{
    uint32_t Tmp_HH = 0xFF, Tmp_MM = 0xFF, Tmp_SS = 0xFF;

    printf("rn==============Time Settings=====================================");
    printf("rn  Please Set Hours");

    while (Tmp_HH == 0xFF)
    {
        Tmp_HH = USART_Scanf(23);
    }
    printf(":  %d", Tmp_HH);
    printf("rn  Please Set Minutes");
    while (Tmp_MM == 0xFF)
    {
        Tmp_MM = USART_Scanf(59);
    }
    printf(":  %d", Tmp_MM);
    printf("rn  Please Set Seconds");
    while (Tmp_SS == 0xFF)
    {
        Tmp_SS = USART_Scanf(59);
    }
    printf(":  %d", Tmp_SS);

    return ((Tmp_HH * 3600 + Tmp_MM * 60 + Tmp_SS));
}

該函數(shù)用于通過串口與用戶交互,讓用戶設(shè)置小時(shí)、分鐘和秒,并將其轉(zhuǎn)換為秒數(shù)返回。

9.Time_Adjust()函數(shù)

void Time_Adjust(void)
{
    RTC_WaitForLastTask();
    RTC_SetCounter(Time_Regulate());
    RTC_WaitForLastTask();
}

該函數(shù)用于調(diào)整 RTC 計(jì)數(shù)器的值,調(diào)用Time_Regulate()函數(shù)獲取用戶設(shè)置的時(shí)間,并將其設(shè)置到 RTC 計(jì)數(shù)器中。

10.NVIC_Configuration()函數(shù)

void NVIC_Configuration(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;

    /* Configure one bit for preemption priority */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

    /* Enable the RTC Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel                   = RTC_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

該函數(shù)用于配置中斷向量表,設(shè)置中斷優(yōu)先級(jí)分組為NVIC_PriorityGroup_1,并使能 RTC 中斷。

11.UART_Configuration()函數(shù)

void UART_Configuration(uint32_t bound)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    USART_InitStructure.USART_BaudRate            = bound;
    USART_InitStructure.USART_WordLength          = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits            = USART_StopBits_1;
    USART_InitStructure.USART_Parity              = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode                = USART_Mode_Rx | USART_Mode_Tx;

    USART_Init(USART_TEST, &USART_InitStructure);
    USART_Cmd(USART_TEST, ENABLE);
}

該函數(shù)用于配置串口USART1,包括使能 USART1 和 GPIOA 時(shí)鐘、配置 GPIO 引腳、設(shè)置串口參數(shù)(波特率、數(shù)據(jù)位、停止位、奇偶校驗(yàn)等),并使能串口。

12.SER_PutChar()和fputc()函數(shù)

int SER_PutChar(int ch)
{
    while (!USART_GetFlagStatus(USART_TEST, USART_FLAG_TC));
    USART_SendData(USART_TEST, (uint8_t)ch);

    return ch;
}

int fputc(int c, FILE *f)
{
    /* Place your implementation of fputc here */
    /* e.g. write a character to the USART */
    if (c == 'n')
    {
        SER_PutChar('r');
    }
    return (SER_PutChar(c));
}

SER_PutChar()函數(shù)用于向串口發(fā)送一個(gè)字符。

fputc()函數(shù)是標(biāo)準(zhǔn)庫中用于輸出字符的函數(shù),這里將其重定向到串口輸出,并且在輸出換行符時(shí)自動(dòng)添加回車符。

5.2 下載驗(yàn)證

wKgZO2gxiSmAOyQYAACFGPh8Lpg108.png

6 RTC_LSICalib

6.1 代碼解析

1. 主函數(shù) main()

int main(void) {
    // 初始化串口,打印系統(tǒng)時(shí)鐘信息
    UART_Configuration(115200);
    printf("RTC LSI Calib Test.n");
    // 配置RTC、TIM5、NVIC
    RTC_Configuration();
    TIM_Configuration();
    NVIC_Configuration();
    // 等待TIM5測(cè)量完成
    while (OperationComplete != 2); 
    // 計(jì)算LSI頻率并設(shè)置RTC預(yù)分頻
    if (PeriodValue != 0) {
        LsiFreq = (uint32_t)((uint32_t)(clocks.PCLK1_Frequency * 2) / (uint32_t)PeriodValue);
    }
    printf("LsiFreq: %d Hzn", LsiFreq);
    RTC_SetPrescaler(LsiFreq - 1);
    while (1);
}

流程:初始化串口后,配置 RTC、TIM5 和中斷,測(cè)量 LSI 頻率,最后設(shè)置 RTC 預(yù)分頻。

2. TIM5 配置(TIM_Configuration)

void TIM_Configuration(void) {
    // 使能時(shí)鐘,重映射LSI到TIM5_CH4
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
    GPIO_PinRemapConfig(GPIO_Remap_TIM5CH4_LSI, ENABLE);
    // 配置TIM5時(shí)基:不分頻,向上計(jì)數(shù),周期0xFFFF
    TIM_TimeBaseStructure.TIM_Prescaler = 0;
    TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);
    // 配置輸入捕獲:通道4,上升沿捕獲
    TIM_ICInitStructure.TIM_Channel = TIM_Channel_4;
    TIM_ICInit(TIM5, &TIM_ICInitStructure);
    TIM_Cmd(TIM5, ENABLE);
    TIM_ITConfig(TIM5, TIM_IT_CC4, ENABLE);
}

作用:將 LSI 信號(hào)連接到 TIM5_CH4,配置 TIM5 為輸入捕獲模式,測(cè)量 LSI 的周期。

3. RTC 配置(RTC_Configuration)

void RTC_Configuration(void) {
    // 使能電源和備份域時(shí)鐘,允許訪問備份域
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
    PWR_BackupAccessCmd(ENABLE);
    // 選擇LSI作為RTC時(shí)鐘源
    RCC_LSICmd(ENABLE);
    RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
    RCC_RTCCLKCmd(ENABLE);
    // 配置RTC預(yù)分頻:根據(jù)測(cè)量的LSI頻率設(shè)置
    RTC_SetPrescaler(40000); 
    BKP_RTCOutputConfig(BKP_RTCOutputSource_Second);
}

作用:使能 LSI,將其作為 RTC 時(shí)鐘源,配置 RTC 預(yù)分頻器,輸出秒信號(hào)。

4. NVIC 配置(NVIC_Configuration)

void NVIC_Configuration(void) {
    // 設(shè)置中斷優(yōu)先級(jí)分組
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    // 配置RTC中斷:最高優(yōu)先級(jí)
    NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
    NVIC_Init(&NVIC_InitStructure);
    // 配置TIM5中斷:子優(yōu)先級(jí)2
    NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
    NVIC_Init(&NVIC_InitStructure);
}

作用:設(shè)置 RTC 和 TIM5 的中斷優(yōu)先級(jí),確保中斷正確響應(yīng)。

這段代碼通過 TIM5 測(cè)量 LSI 頻率,動(dòng)態(tài)配置 RTC 預(yù)分頻,確保 RTC 計(jì)時(shí)精度,適用于需要校準(zhǔn) LSI 的嵌入式場(chǎng)景,如 RTC 時(shí)鐘源校準(zhǔn)。

6.2 下載驗(yàn)證

wKgZPGgxiSmAZq3-AABsVZJKe5Q418.png

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

    關(guān)注

    6067

    文章

    44989

    瀏覽量

    650361
  • 實(shí)時(shí)時(shí)鐘

    關(guān)注

    4

    文章

    314

    瀏覽量

    67059
  • 定時(shí)器
    +關(guān)注

    關(guān)注

    23

    文章

    3298

    瀏覽量

    118890
  • RTC
    RTC
    +關(guān)注

    關(guān)注

    2

    文章

    622

    瀏覽量

    68851
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    STM32 RTC實(shí)時(shí)時(shí)鐘(一)

    STM32處理器內(nèi)部集成了實(shí)時(shí)時(shí)鐘控制器(RTC),因此在實(shí)現(xiàn)實(shí)時(shí)時(shí)鐘功能時(shí),無須外擴(kuò)時(shí)鐘芯片即可構(gòu)建實(shí)時(shí)時(shí)鐘系統(tǒng)。
    的頭像 發(fā)表于 07-22 15:41 ?5567次閱讀
    STM32 <b class='flag-5'>RTC</b><b class='flag-5'>實(shí)時(shí)時(shí)鐘</b>(一)

    火力發(fā)電廠水汽分析方法 第二十八部分:有機(jī)物的測(cè)定(紫外吸收法)

    火力發(fā)電廠水汽分析方法 第二十八部分:有機(jī)物的測(cè)定(紫外吸收法)
    發(fā)表于 09-11 01:09

    「正點(diǎn)原子Linux連載」第二十五章RTC實(shí)時(shí)時(shí)鐘實(shí)驗(yàn)

    1)實(shí)驗(yàn)平臺(tái):正點(diǎn)原子Linux開發(fā)板2)摘自《正點(diǎn)原子I.MX6U嵌入式Linux驅(qū)動(dòng)開發(fā)指南》關(guān)注官方微信號(hào)公眾號(hào),獲取更多資料:正點(diǎn)原子第二十五章RTC實(shí)時(shí)時(shí)鐘實(shí)驗(yàn) 實(shí)時(shí)時(shí)鐘是很
    發(fā)表于 01-08 15:57

    什么是實(shí)時(shí)時(shí)鐘RTC)?如何更改RTC的時(shí)間?

    什么是實(shí)時(shí)時(shí)鐘RTC)?實(shí)時(shí)時(shí)鐘RTC)的基本功能是什么?實(shí)時(shí)時(shí)鐘RTC)晶體誤差的主要來
    發(fā)表于 07-19 08:44

    實(shí)時(shí)時(shí)鐘(RTC)概述

    實(shí)時(shí)時(shí)鐘(RTC)概述RTC(real-time clock),實(shí)時(shí)時(shí)鐘是一個(gè)獨(dú)立的時(shí)鐘RTC
    發(fā)表于 08-03 06:33

    火力發(fā)電廠水汽分析方法 第二十八部分:有機(jī)物的測(cè)定(紫外吸收

    火力發(fā)電廠水汽分析方法 第二十八部分:有機(jī)物的測(cè)定(紫外吸收法) Analytical methods of steam and water in power plants Part
    發(fā)表于 06-08 12:10 ?27次下載

    第二十八講 數(shù)模和模數(shù)轉(zhuǎn)換器

    第二十八講 數(shù)模和模數(shù)轉(zhuǎn)換器 第8章 數(shù)模和模數(shù)轉(zhuǎn)換器8.1 概述 8.2 D/A轉(zhuǎn)換器8.2.3 R-2R倒 T形電阻網(wǎng)絡(luò)D
    發(fā)表于 03-30 16:34 ?3162次閱讀
    <b class='flag-5'>第二十八</b>講 數(shù)模和模數(shù)轉(zhuǎn)換器

    模擬電路網(wǎng)絡(luò)課件 第二十八節(jié):集成電路運(yùn)算放大器的參數(shù)

    模擬電路網(wǎng)絡(luò)課件 第二十八節(jié):集成電路運(yùn)算放大器的參數(shù) 運(yùn)算放大器的參數(shù) 。VIO的大小反應(yīng)了運(yùn)放制造中電路的對(duì)稱程度和電位配合情況。VIO值
    發(fā)表于 09-17 11:39 ?718次閱讀
    模擬電路網(wǎng)絡(luò)課件 <b class='flag-5'>第二十八</b>節(jié):集成電路運(yùn)算放大器的參數(shù)

    實(shí)用雙向可控硅應(yīng)用500例二十八

    實(shí)用雙向可控硅應(yīng)用500例二十八
    發(fā)表于 09-19 11:56 ?17次下載
    實(shí)用雙向可控硅應(yīng)用500例<b class='flag-5'>二十八</b>類

    淺談RTC實(shí)時(shí)時(shí)鐘特征與原理

    一、RTC實(shí)時(shí)時(shí)鐘特征與原理 查看STM32中文手冊(cè) 16 實(shí)時(shí)時(shí)鐘RTC)(308頁) RTC (Real Time Clock):
    的頭像 發(fā)表于 06-30 15:54 ?1.1w次閱讀

    stm32溫濕度傳感器報(bào)告_「正點(diǎn)原子NANO STM32開發(fā)板資料連載」第二十八章 DHT11 數(shù)字溫濕度傳感器實(shí)驗(yàn)...

    1)實(shí)驗(yàn)平臺(tái):alientek NANO STM32F411 V1開發(fā)板2)摘自《正點(diǎn)原子STM32F4 開發(fā)指南(HAL 庫版》關(guān)注官方微信號(hào)公眾號(hào),獲取更多資料:正點(diǎn)原子第二十八章 DHT11
    發(fā)表于 12-05 16:36 ?14次下載
    stm32溫濕度傳感器報(bào)告_「正點(diǎn)原子NANO STM32開發(fā)板資料連載」<b class='flag-5'>第二十八章</b>  DHT11 數(shù)字溫濕度傳感器實(shí)驗(yàn)...

    DA1468x SoC 的實(shí)時(shí)時(shí)鐘(RTC) 概念

    DA1468x SoC 的實(shí)時(shí)時(shí)鐘 (RTC) 概念
    發(fā)表于 03-15 20:16 ?0次下載
    DA1468x SoC 的<b class='flag-5'>實(shí)時(shí)時(shí)鐘</b>(<b class='flag-5'>RTC</b>) 概念

    輕生活科技將參加第二十八屆廣州國際照明展覽會(huì)(GILE)

    輕生活科技將參加6月9日至12日的第二十八屆廣州國際照明展覽會(huì)(GILE),屆時(shí)我們將展示領(lǐng)先的離線語音控制技術(shù)方案
    的頭像 發(fā)表于 05-30 10:57 ?739次閱讀
    輕生活科技將參加<b class='flag-5'>第二十八</b>屆廣州國際照明展覽會(huì)(GILE)

    CW32實(shí)時(shí)時(shí)鐘RTC)介紹

    CW32實(shí)時(shí)時(shí)鐘RTC)介紹
    的頭像 發(fā)表于 10-24 15:36 ?1648次閱讀
    CW32<b class='flag-5'>實(shí)時(shí)時(shí)鐘</b>(<b class='flag-5'>RTC</b>)介紹

    鐳拓新款激光圓管切割機(jī)亮相第二十八屆中國五金博覽會(huì)

    編輯:鐳拓激光一年一度的五金行業(yè)盛會(huì)——中國五金博覽會(huì)即將在浙江永康國際會(huì)展中心隆重開幕,今年已經(jīng)是第二十八屆了,屆時(shí)會(huì)有來自全國各地的制造業(yè)企業(yè)參展。這樣的行業(yè)盛會(huì)怎么能少得了我們鐳拓激光呢!鐳拓
    的頭像 發(fā)表于 09-19 10:38 ?795次閱讀
    鐳拓新款激光圓管切割機(jī)亮相<b class='flag-5'>第二十八</b>屆中國五金博覽會(huì)