国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【正點(diǎn)原子STM32連載】 第二十七章 RTC實(shí)驗(yàn)摘自【正點(diǎn)原子】APM32E103最小系統(tǒng)板使用指南

這篇具有很好參考價(jià)值的文章主要介紹了【正點(diǎn)原子STM32連載】 第二十七章 RTC實(shí)驗(yàn)摘自【正點(diǎn)原子】APM32E103最小系統(tǒng)板使用指南。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

1)實(shí)驗(yàn)平臺(tái):正點(diǎn)原子APM32E103最小系統(tǒng)板
2)平臺(tái)購(gòu)買(mǎi)地址:https://detail.tmall.com/item.htm?id=609294757420
3)全套實(shí)驗(yàn)源碼+手冊(cè)+視頻下載地址: http://www.openedv.com/docs/boards/xiaoxitongban

第二十七章 RTC實(shí)驗(yàn)

本章介紹APM32E103實(shí)時(shí)時(shí)鐘(RTC)的使用,實(shí)時(shí)時(shí)鐘能為系統(tǒng)提供一個(gè)準(zhǔn)確的時(shí)間,即時(shí)系統(tǒng)復(fù)位或主電源斷電,RTC依然能夠運(yùn)行,因此RTC也經(jīng)常用于各種低功耗場(chǎng)景。通過(guò)本章的學(xué)習(xí),讀者將學(xué)習(xí)到RTC的使用。
本章分為如下幾個(gè)小節(jié):
27.1 硬件設(shè)計(jì)
27.2 程序設(shè)計(jì)
27.3 下載驗(yàn)證

27.1 硬件設(shè)計(jì)
27.1.1 例程功能

  1. LED1每秒翻轉(zhuǎn)一次,表示每秒產(chǎn)生一次RTC喚醒中斷
  2. 通過(guò)LCD實(shí)時(shí)顯示RTC時(shí)間,并可通過(guò)USMART設(shè)置RTC時(shí)間等
  3. LED0閃爍,指示程序正在運(yùn)行
    27.1.2 硬件資源
  4. LED
    LED0 - PB5
  5. USART1(PA9、PA10連接至板載USB轉(zhuǎn)串口芯片上)
  6. 正點(diǎn)原子 2.8/3.5/4.3/7/10寸TFTLCD模塊(僅限MCU屏,16位8080并口驅(qū)動(dòng))
  7. RTC
    27.1.3 原理圖
    本章實(shí)驗(yàn)使用的RTC為APM32E103的片上資源,因此沒(méi)有相應(yīng)的連接原理圖。
    27.2 程序設(shè)計(jì)
    27.2.1 Geehy標(biāo)準(zhǔn)庫(kù)的PMU驅(qū)動(dòng)
    本章實(shí)驗(yàn)要使用到RTC,因此需要對(duì)RTC及其相關(guān)的寄存器進(jìn)行配置,但是為了防止誤操作,系統(tǒng)復(fù)位后備份區(qū)域(指RTC、備份寄存器)是被禁止寫(xiě)訪問(wèn)的,備份區(qū)域的寫(xiě)訪問(wèn)是由電源管理單元(PMU)進(jìn)行配置的,具體的配置步驟如下:
    ①:使能寫(xiě)備份區(qū)域
    在Geehy標(biāo)準(zhǔn)庫(kù)中對(duì)應(yīng)的驅(qū)動(dòng)函數(shù)如下:
    ①:使能寫(xiě)備份區(qū)域
    該函數(shù)用于使能寫(xiě)備份區(qū)域,其函數(shù)原型如下所示:
    void PMU_EnableBackupAccess(void);
    該函數(shù)的形參描述,如下表所示:
    形參 描述
    無(wú) 無(wú)
    表27.2.1.1 函數(shù)PMU_EnableBackupAccess()形參描述
    該函數(shù)的返回值描述,如下表所示:
    返回值 描述
    無(wú) 無(wú)
    表27.2.1.2 函數(shù)PMU_EnableBackupAccess()返回值描述
    該函數(shù)的使用示例,如下所示:
#include " apm32e10x.h"
#include "apm32e10x _pmu.h"

void example_fun(void)
{
    /* 使能寫(xiě)備份區(qū)域 */
    PMU_EnableBackupAccess();
}

27.2.2 Geehy標(biāo)準(zhǔn)庫(kù)的RCM驅(qū)動(dòng)
本章實(shí)驗(yàn)使用了RTC,因此需要配置RTC的時(shí)鐘,RTC的時(shí)鐘可以來(lái)自LSE、LSI或HSE的分頻,以上均由RCM進(jìn)行管理,其具體的配置步驟如下:
①:優(yōu)先使能LSE
②:若LSE無(wú)法就緒,則使能LSI
③:配置RTC的時(shí)鐘源為L(zhǎng)SE或LSI
在Geehy標(biāo)準(zhǔn)庫(kù)中對(duì)應(yīng)的驅(qū)動(dòng)函數(shù)如下:
①:使能LSE
該函數(shù)用于配置LSE,其函數(shù)原型如下所示:
void RCM_ConfigLSE(RCM_LSE_T state);
該函數(shù)的形參描述,如下表所示:
形參 描述
state LSE的配置狀態(tài)
例如:RCM_LSE_CLOSE、RCM_LSE_OPEN等(在apm32e10x_rcm.h文件中有定義)
表27.2.2.1 函數(shù)RCM_ConfigLSE()形參描述
該函數(shù)的返回值描述,如下表所示:
返回值 描述
無(wú) 無(wú)
表27.2.2.2 函數(shù)RCM_ConfigLSE()返回值描述
該函數(shù)的使用示例,如下所示:

#include "apm32e10x.h"
#include "apm32e10x_rcm.h"

void example_fun(void)
{
    /* 使能LSE */
    RCM_ConfigLSE(RCM_LSE_OPEN);
    
    /* 禁止LSE */
    RCM_ConfigLSE(RCM_LSE_CLOSE);
}

②:使能LSI
該函數(shù)用于使能LSI,其函數(shù)原型如下所示:
void RCM_EnableLSI(void);
該函數(shù)的形參描述,如下表所示:
形參 描述
無(wú) 無(wú)
表27.2.2.3 函數(shù)RCM_EnableLSI()形參描述
該函數(shù)的返回值描述,如下表所示:
返回值 描述
無(wú) 無(wú)
表27.2.2.4 函數(shù)RCM_EnableLSI()返回值描述
該函數(shù)的使用示例,如下所示:

#include "apm32e10x.h"
#include "apm32e10x_rcm.h"

void example_fun(void)
{
    RCM_EnableLSI(); /* 使能LSI */
}

③:配置RTC的時(shí)鐘源
該函數(shù)用于配置RTC的時(shí)鐘源,其函數(shù)原型如下所示:
void RCM_ConfigRTCCLK(RCM_RTCCLK_T rtcClkSelect);
該函數(shù)的形參描述,如下表所示:
形參 描述
rtcClkSelect RTC的時(shí)鐘源選擇
例如:RCM_RTCCLK_LSE、RCM_RTCCLK_LSI等(在apm32e10x_rcm.h文件中有定義)
表27.2.2.5 函數(shù)RCM_ConfigRTCCLK()形參描述
該函數(shù)的返回值描述,如下表所示:
返回值 描述
無(wú) 無(wú)
表27.2.2.6 函數(shù)RCM_ConfigRTCCLK()返回值描述
該函數(shù)的使用示例,如下所示:

#include "apm32e10x.h"
#include "apm32e10x_rcm.h"

void example_fun(void)
{
    /* 配置RTC的時(shí)鐘源為L(zhǎng)SE */
    RCM_ConfigRTCCLK(RCM_RTCCLK_LSE);
}

27.2.3 Geehy標(biāo)準(zhǔn)庫(kù)的RTC驅(qū)動(dòng)
本章實(shí)驗(yàn)使用了RTC,RTC最基本的操作就是設(shè)置和獲取時(shí)間和日期,同時(shí)還需要讀寫(xiě)RTC備份寄存器保存是否已經(jīng)在初始化過(guò)程中設(shè)置過(guò)時(shí)間的標(biāo)志,其具體的步驟如下:
①:初始化配置RTC
②:讀取RTC備份寄存器判斷是否進(jìn)行設(shè)置過(guò)時(shí)間
③:若未設(shè)置過(guò)時(shí)間,則設(shè)置RTC的時(shí)間
④:若未設(shè)置過(guò)時(shí)間,則設(shè)置RTC的日期
⑤:將設(shè)置過(guò)時(shí)間的標(biāo)志寫(xiě)入RTC備份寄存器
⑥:讀取RTC的時(shí)間
⑦:讀取RTC的日期
在Geehy標(biāo)準(zhǔn)庫(kù)中對(duì)應(yīng)的驅(qū)動(dòng)函數(shù)如下:
①:讀取RTC備份寄存器
該函數(shù)用于讀取RTC備份寄存器,其函數(shù)原型如下所示:
uint16_t BAKPR_ReadBackupRegister(BAKPR_DATA_T bakrData);
該函數(shù)的形參描述,如下表所示:
形參 描述
bakrData RTC指定數(shù)據(jù)備份寄存器
例如:BAKPR_DATA1、BAKPR_DATA2等(在apm32e10x_rtc.h文件中有定義)
表27.2.3.3 函數(shù)BAKPR_ReadBackupRegister ()形參描述
該函數(shù)的返回值描述,如下表所示:
返回值 描述
uint16_t類(lèi)型數(shù)據(jù) RTC備份寄存器值
表27.2.3.4 函數(shù)BAKPR_ReadBackupRegister ()返回值描述
該函數(shù)的使用示例,如下所示:

#include "apm32e10x.h"
#include "apm32e10x_rtc.h"

void example_fun(void)
{
    uint32_t rtc_backup_data1;
    
    /* 讀取RTC備份寄存器1 */
    rtc_backup_data1 = BAKPR_ReadBackupRegister (BAKPR_DATA1);
    
    /* Do something. */
}

②:寫(xiě)入RTC備份寄存器
該函數(shù)用于寫(xiě)入RTC備份寄存器,其函數(shù)原型如下所示:
void BAKPR_ConfigBackupRegister(BAKPR_DATA_T bakrData, uint16_t data);
該函數(shù)的形參描述,如下表所示:
形參 描述
bakrData RTC指定數(shù)據(jù)備份寄存器
例如:BAKPR_DATA1、BAKPR_DATA2等(在apm32e10x_rtc.h文件中有定義)
data RTC備份寄存器值
表27.2.3.9 函數(shù)BAKPR_ConfigBackupRegister ()形參描述
該函數(shù)的返回值描述,如下表所示:
返回值 描述
無(wú) 無(wú)
表27.2.3.10 函數(shù)BAKPR_ConfigBackupRegister ()返回值描述
該函數(shù)的使用示例,如下所示:

#include "apm32e10x.h"
#include "apm32e10x_rtc.h"

void example_fun(void)
{
    /* 往RTC備份寄存器0寫(xiě)入0x50505050 */
    BAKPR_ConfigBackupRegister(BAKPR_DATA1, 0x50505050);
}

③:使能RTC指定中斷
該函數(shù)用于使能RTC的指定中斷,其函數(shù)原型如下所示:
void RTC_EnableInterrupt(uint32_t interrupt);
該函數(shù)的形參描述,如下表所示:
形參 描述
interrupt 指定的RTC中斷
例 如:RTC_INT_OVR、RTC_INT_ALR等(在apm32e10x_rtc.h文件中有定義)
表27.2.3.19 函數(shù)RTC_EnableInterrupt()形參描述
該函數(shù)的返回值描述,如下表所示:
返回值 描述
無(wú) 無(wú)
表27.2.3.20 函數(shù)RTC_EnableInterrupt()返回值描述
該函數(shù)的使用示例,如下所示:

#include "apm32e10x.h"
#include "apm32e10x_rtc.h"

void example_fun(void)
{
    /* 使能RTC喚醒中斷 */
    RTC_EnableInterrupt(RTC_INT_OVR);
}

④:使能RTC中斷
請(qǐng)見(jiàn)第12.2.3小節(jié)中配置中斷的相關(guān)內(nèi)容。
本實(shí)驗(yàn)同時(shí)也使能了RTC的鬧鐘功能,鬧鐘功能可以在RTC時(shí)間到達(dá)設(shè)定值時(shí)觸發(fā)中斷,其具體的使用步驟如下:
①:配置RTC鬧鐘
②:配置RTC鬧鐘對(duì)應(yīng)的EINT線
③:使能RTC鬧鐘中斷
④:使能RTC鬧鐘中斷,并配置其相關(guān)的中斷優(yōu)先級(jí)
⑤:使能RTC鬧鐘
在Geehy標(biāo)準(zhǔn)庫(kù)中對(duì)應(yīng)的驅(qū)動(dòng)函數(shù)如下:
①:配置RTC鬧鐘
該函數(shù)用于配置RTC的鬧鐘,其函數(shù)原型如下所示:
void RTC_ConfigAlarm(uint32_t value);
該函數(shù)的形參描述,如下表所示:
形參 描述
value RTC鬧鐘數(shù)值
表27.2.3.23 函數(shù)RTC_ConfigAlarm()形參描述
該函數(shù)的返回值描述,如下表所示:
返回值 描述
無(wú) 無(wú)
表27.2.3.24 函數(shù)RTC_ConfigAlarm()返回值描述
該函數(shù)使用數(shù)值變量傳入RTC鬧鐘的配置參數(shù),并未用到具體的結(jié)構(gòu)體。

#include "apm32e10x.h"
#include "apm32e10x_rtc.h"

void example_fun(uint8_t hour, uint8_t min, uint8_t sec)
{
uint32_t seccount = 0;

    seccount += (date - 1) * 86400;
    seccount += hour * 3600;
    seccount += min * 60;
    seccount += sec;

    RTC_ConfigAlarm(seccount);
}

②:使能RTC指定中斷
請(qǐng)見(jiàn)第27.2.3小節(jié)中使能RTC指定中斷的內(nèi)容。
③:使能RTC中斷
請(qǐng)見(jiàn)第12.2.3小節(jié)中配置中斷的相關(guān)內(nèi)容。
27.2.4 RTC驅(qū)動(dòng)
本章實(shí)驗(yàn)的RTC驅(qū)動(dòng)主要負(fù)責(zé)向應(yīng)用層提供RTC的初始化和配置自動(dòng)喚醒及鬧鐘的函數(shù)。本章實(shí)驗(yàn)中,RTC的驅(qū)動(dòng)代碼包括rtc.c和rtc.h兩個(gè)文件。
RTC驅(qū)動(dòng)中,RTC的初始化函數(shù),如下所示:

/**
 * @brief       初始化RTC
 * @param       無(wú)
 * @retval      初始化結(jié)果
 * @arg         0: 初始化成功
 * @arg         1: 初始化失敗
 */
uint8_t rtc_init(void)
{
    uint16_t bkpflag;
    uint16_t retry;
    
    RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_PMU);    /* 使能PMU時(shí)鐘 */
    RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_BAKR);   /* 使能BAKPR時(shí)鐘 */
    PMU_EnableBackupAccess();                          /* 使能訪問(wèn)備份寄存器 */
    bkpflag = rtc_read_bkr(BAKPR_DATA1);               /* 讀取備份寄存器1的值 */
    
    retry = 0;
    RCM_ConfigLSE(RCM_LSE_OPEN);                       /* 嘗試使能LSE */
    
    while ((retry < 200) && (RCM->BDCTRL_B.LSERDYFLG != SET))
    {
        retry++;
        delay_ms(5);
    }
    
    if (RCM->BDCTRL_B.LSERDYFLG != SET)                /* LSE無(wú)法就緒,改用LSI */
    {
        RCM_ConfigLSE(RCM_LSE_CLOSE);                  /* 禁用LSE */
        RCM_EnableLSI();                               /* 使能LSI */
        while (RCM->CSTS_B.LSIRDYFLG != SET)           /* 等待LSI就緒 */
        {
            delay_ms(5);
        }
        RCM_ConfigRTCCLK(RCM_RTCCLK_LSI);              /* 選擇RTC的時(shí)鐘源為L(zhǎng)SI */
        rtc_write_bkr(BAKPR_DATA1, 0x5051);
    }
    else                                               /* LSE已就緒 */
    {
        RCM_ConfigRTCCLK(RCM_RTCCLK_LSE);              /* 選擇RTC的時(shí)鐘源為L(zhǎng)SE */
        rtc_write_bkr(BAKPR_DATA1, 0x5050);
    }
    
    RCM_EnableRTCCLK();                                /* 使能RTC時(shí)鐘 */
    RTC_WaitForSynchro();                              /* 等待RTC寄存器同步 */
    RTC_WaitForLastTask();                             /* 等待RTC操作完成 */
    
    RTC_ConfigPrescaler(32767);                        /* 配置RTC預(yù)分頻寄存器 */
    RTC_WaitForLastTask();
   
    if ((bkpflag != 0x5050) && (bkpflag != 0x5051))    /* 之前從未配置過(guò) */
    {
        rtc_set(22, 10, 22, 8, 8, 8);                  /* 設(shè)置RTC時(shí)間 */
    }
    
    RTC_EnableInterrupt(RTC_INT_SEC);                  /* 使能RTC秒中斷 */
    RTC_WaitForLastTask();
    NVIC_EnableIRQRequest(RTC_IRQn, 2, 0);
    
    return 0;
}

從上面的代碼中可以看出,RTC的初始化函數(shù)中,優(yōu)先嘗試使用LSE作為RTC的時(shí)鐘源,若LSE無(wú)法就緒,則使用LSI作為RTC的時(shí)鐘源。配置好RTC的時(shí)鐘源后,配置RTC為24小時(shí)制,并配置RTC的預(yù)分頻寄存器的數(shù)值為32767。最后根據(jù)RTC備份寄存器中的標(biāo)志,決定是否配置RTC的時(shí)間,若之前已經(jīng)配置過(guò),則不會(huì)再次配置。
RTC驅(qū)動(dòng)中設(shè)置、獲取RTC時(shí)間、日期的三個(gè)函數(shù),如下所示:
/

**
 * @brief       設(shè)置RTC時(shí)間
 * @param       year :* @param       month:* @param       date :* @param       hour : 小時(shí)
 * @param       min  : 分鐘
 * @param       sec  : 秒鐘
 * @retval      設(shè)置結(jié)果
 * @arg         0: 設(shè)置成功
 * @arg         1: 設(shè)置失敗
 */
uint8_t rtc_set(uint8_t year, uint8_t month,
                uint8_t date, uint8_t hour, 
                uint8_t min,  uint8_t sec)
{
    uint16_t year_4;
    uint16_t index;
    uint32_t seccount = 0;
    
    year_4 = year + 2000;
    if ((year_4 < 1970) || (year_4 > 2099))
    {
        return 1;
    }
    
    for (index=1970; index<year_4; index++)
    {
        if (is_leap_year(index))
        {
            seccount += 31622400;
        }
        else
        {
            seccount += 31536000;
        }
    }
    
    month--;
    for (index=0; index<month; index++)
    {
        seccount += (uint32_t)month_table[index] * 86400;
        if (is_leap_year(year_4) && (index == 1))
        {
            seccount += 86400;
        }
    }
    
    seccount += (uint32_t)(date - 1) * 86400;
    seccount += (uint32_t)hour * 3600;
    seccount += (uint32_t)min * 60;
    seccount += sec;
    
    RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_PMU);     /* 使能PMU時(shí)鐘 */
    RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_BAKR);    /* 使能BAKPR時(shí)鐘 */
    PMU_EnableBackupAccess();                           /* 使能訪問(wèn)備份寄存器 */
    
    RTC_ConfigCounter(seccount);                        /* 設(shè)置RTC計(jì)數(shù)值 */
    RTC_WaitForLastTask();
    
    return 0;
}

/**
 * @brief       獲取RTC時(shí)間
 * @param       year : 年
 * @param       month: 月
 * @param       date : 日
 * @param       week : 星期
 * @param       hour : 小時(shí)
 * @param       min  : 分鐘
 * @param       sec  : 秒鐘
 * @retval      無(wú)
 */
void rtc_get(uint8_t *year, uint8_t *month,
             uint8_t *date, uint8_t *week,
             uint8_t *hour, uint8_t *min,
             uint8_t *sec)

{
    uint32_t seccount;
    uint16_t daycount;
    static uint16_t last_daycount = 0;
    uint16_t index;
    
    /* 讀取RTC計(jì)數(shù)值 */
    seccount = RTC_ReadCounter();
    daycount = seccount / 86400;
    if (last_daycount != daycount)
    {
        last_daycount = daycount;
        
        index = 1970;
        while (daycount >= 365)
        {
            if (is_leap_year(index))
            {
                if (daycount >= 366)
                {
                    daycount -= 366;
                }
                else
                {
                    index++;
                    break;
                }
            }
            else
            {
                daycount -= 365;
            }
            index++;
        }
        *year = index - 2000;
        
        index=0;
        while (daycount >= 28)
        {
            if (is_leap_year(*year + 2000) && (index == 1))
            {
                if (daycount >= 29)
                {
                    daycount -= 29;
                }
                else
                {
                    break;
                }
            }
            else
            {
                if (daycount >= month_table[index])
                {
                    daycount -= month_table[index];
                }
                else
                {
                    break;
                }
            }
            index++;
        }
        *month = index + 1;
        *date = daycount + 1;
    }
    
    daycount = seccount % 86400;
    *hour = daycount / 3600;
    *min = (daycount % 3600) / 60;
    *sec = (daycount % 3600) % 60;
    *week = rtc_get_week(*year + 2000, *month, *date);
}

/**
 * @brief       通過(guò)日期計(jì)算星期
 * @param       year : 年
 * @param       month: 月
 * @param       date : 日
 * @retval      星期
 */
uint8_t rtc_get_week(uint16_t year, uint8_t month, uint8_t date)
{
    uint8_t year_l;
    uint8_t year_h;
    uint8_t week;
    
    year_h = year / 100;
    year_l = year % 100;
    if (year_h > 19)
    {
        year_l += 100;
    }
    
    week = (((year_l + (year_l >> 2)) % 7) + date + week_table[month - 1] - ((((year_l % 4) == 0) && (month < 3)) ? 1 : 0)) % 7;
    
    return week;
}

以上三個(gè)獲取、設(shè)置RTC時(shí)間、日期的函數(shù),均是對(duì)Geehy標(biāo)準(zhǔn)庫(kù)中RTC驅(qū)動(dòng)的簡(jiǎn)單封裝。
RTC驅(qū)動(dòng)中,配置RTC喚醒中斷及其對(duì)應(yīng)的中斷回調(diào)函數(shù),如下所示:

/**
 * @breif       RTC中斷服務(wù)函數(shù)
 * @param       無(wú)
 * @retval      無(wú)
 */
void RTC_IRQHandler(void)
{
    if (RTC_ReadIntFlag(RTC_INT_SEC) == SET)    /* 判斷秒中斷標(biāo)志 */
    {
        LED1_TOGGLE();
        RTC_ClearIntFlag(RTC_INT_SEC);          /* 清除秒中斷標(biāo)志 */
    }
    
    if (RTC_ReadIntFlag(RTC_INT_ALR) == SET)    /* 判斷鬧鐘中斷標(biāo)志 */
    {
        printf("ALARM!\r\n");
        RTC_ClearIntFlag(RTC_INT_ALR);          /* 清除鬧鐘中斷標(biāo)志 */
    }
    
    RTC_WaitForLastTask();
}

從上面的代碼中可以看出,在RTC的秒中斷中翻轉(zhuǎn)了LED1的亮滅狀態(tài),并清除了秒中斷標(biāo)志,因此RTC時(shí)間將會(huì)周期性地發(fā)生,也就能看到LED1周期性地改變狀態(tài)。同時(shí),在進(jìn)行判斷秒中斷標(biāo)志時(shí),也對(duì)鬧鐘中斷標(biāo)志位進(jìn)行了判斷。在該過(guò)程中,我們通過(guò)串口打印出的“ALARM”字樣提示得知單片機(jī)正在響應(yīng)該中斷。
RTC驅(qū)動(dòng)中,配置RTC鬧鐘中斷及其對(duì)應(yīng)的中斷回調(diào)函數(shù),如下所示:

/**
 * @breif       設(shè)置RTC鬧鐘時(shí)間
 * @param       year : 年
 * @param       month: 月
 * @param       date : 日
 * @param       hour : 小時(shí)
 * @param       min  : 分鐘
 * @param       sec  : 秒鐘
 * @retval      無(wú)
 */
void rtc_set_alarm(uint8_t year, uint8_t month,
                   uint8_t date, uint8_t hour,
                   uint8_t min,  uint8_t sec)

{
    uint16_t year_4;
    uint16_t index;
    uint32_t seccount = 0;
    
    year_4 = year + 2000;
    if ((year_4 < 1970) || (year_4 > 2099))
    {
        return;
    }
    
    for (index=1970; index<year_4; index++)
    {
        if (is_leap_year(index))
        {
            seccount += 31622400;
        }
        else
        {
            seccount += 31536000;
        }
    }
    
    month--;
    for (index=0; index<month; index++)
    {
        seccount += month_table[index] * 86400;
        if (is_leap_year(year_4) && (index == 1))
        {
            seccount += 86400;
        }
    }
    
    seccount += (date - 1) * 86400;
    seccount += hour * 3600;
    seccount += min * 60;
    seccount += sec;
    
    RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_PMU);     /* 使能PMU時(shí)鐘 */
    RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_BAKR);    /* 使能BAKPR時(shí)鐘 */
    PMU_EnableBackupAccess();                           /* 使能訪問(wèn)備份寄存器 */
    
    RTC_ConfigAlarm(seccount);                          /* 設(shè)置RTC鬧鐘 */
    RTC_WaitForLastTask();
}
從上面的代碼中可以看到,通過(guò)傳入的年,月,日,時(shí),分,秒等參數(shù)對(duì)鬧鐘進(jìn)行設(shè)置,而這些參數(shù)已經(jīng)在RTC初始化函數(shù)中已經(jīng)設(shè)置完成,用戶只需調(diào)根據(jù)自己的需求進(jìn)行函數(shù)調(diào)用即可,用戶同時(shí)也可以在RTC初始化函數(shù)中對(duì)以上參數(shù)進(jìn)行自定義設(shè)置。在這里便不做過(guò)多闡述。
27.2.5 實(shí)驗(yàn)應(yīng)用代碼
本章實(shí)驗(yàn)的應(yīng)用代碼,如下所示:
int main(void)
{
    uint8_t year;
    uint8_t month;
    uint8_t date;
    uint8_t week;
    uint8_t hour;
    uint8_t min;
    uint8_t sec;
    uint8_t tbuf[40];
    uint8_t t = 0;
    
    NVIC_ConfigPriorityGroup(NVIC_PRIORITY_GROUP_4);  /* 設(shè)置中斷優(yōu)先級(jí)分組為組4 */
    sys_apm32_clock_init(15);                         /* 配置系統(tǒng)時(shí)鐘 */
    delay_init(120);                                  /* 初始化延時(shí)功能 */
    usart_init(115200);                               /* 初始化串口 */
    usmart_dev.init(120);                             /* 初始化USMART */
    led_init();                                       /* 初始化LED */
    lcd_init();                                       /* 初始化LCD */
    rtc_init();                                       /* 初始化RTC */
    
    lcd_show_string(30, 50, 200, 16, 16, "APM32", RED);
    lcd_show_string(30, 70, 200, 16, 16, "RTC TEST", RED);
    lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
    
    while (1)
    {
        t++;
        if ((t % 10) == 0)                            /* 每100毫秒更新一次數(shù)據(jù) */
        {
            rtc_get(&year, &month, &date, &week, &hour, &min, &sec);
            sprintf((char *)tbuf, "Time:%02d:%02d:%02d", hour, min, sec);
            lcd_show_string(30, 130, 210, 16, 16, (char *)tbuf, RED);
            sprintf((char *)tbuf, "Date:20%02d-%02d-%02d", year, month, date);
            lcd_show_string(30, 150, 210, 16, 16, (char *)tbuf, RED);
            sprintf((char *)tbuf, "Week:%d", week);
            lcd_show_string(30, 170, 210, 16, 16, (char *)tbuf, RED);
        }
        if ((t % 20) == 0)
        {
            LED0_TOGGLE();
        }
        
        delay_ms(10);
    }
}

從上面的代碼中可以看到,在初始化完RTC后便每間隔100毫秒獲取一次RTC的時(shí)間和日期,并在LCD上進(jìn)行顯示。
本實(shí)驗(yàn)同時(shí)也使用的USMART調(diào)試組件,并在usart_config.c文件中添加了RTC驅(qū)動(dòng)中相關(guān)的函數(shù),以便調(diào)試。
27.3 下載驗(yàn)證
在完成編譯和燒錄操作后,可以看到LCD上實(shí)時(shí)地顯示著RTC的時(shí)間,并且可以看到LED1在RTC周期性喚醒的驅(qū)動(dòng)下以0.5Hz的頻率閃爍著,此時(shí)可以通過(guò)串口調(diào)試助手調(diào)用USMART調(diào)試組件的rtc_set_alarma()函數(shù)來(lái)設(shè)置RTC的鬧鐘,當(dāng)通過(guò)LCD觀察到RTC的時(shí)間達(dá)到設(shè)置的鬧鐘時(shí)間后,可以看到串口調(diào)試助手上打印了“ALARM A!\r\n”的字符串提示。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-806295.html

到了這里,關(guān)于【正點(diǎn)原子STM32連載】 第二十七章 RTC實(shí)驗(yàn)摘自【正點(diǎn)原子】APM32E103最小系統(tǒng)板使用指南的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包