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 例程功能
- LED1每秒翻轉(zhuǎn)一次,表示每秒產(chǎn)生一次RTC喚醒中斷
- 通過(guò)LCD實(shí)時(shí)顯示RTC時(shí)間,并可通過(guò)USMART設(shè)置RTC時(shí)間等
- LED0閃爍,指示程序正在運(yùn)行
27.1.2 硬件資源 - LED
LED0 - PB5 - USART1(PA9、PA10連接至板載USB轉(zhuǎn)串口芯片上)
- 正點(diǎn)原子 2.8/3.5/4.3/7/10寸TFTLCD模塊(僅限MCU屏,16位8080并口驅(qū)動(dòng))
- 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ù),如下所示:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-806295.html
/**
* @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)!