RTC簡(jiǎn)介
實(shí)時(shí)時(shí)鐘(Real Time Clock,RTC),是一個(gè)可以不使用系統(tǒng)主電源供電的定時(shí)器。在系統(tǒng)主電源斷開(kāi) 的情況下,依靠紐扣電池供電繼續(xù)計(jì)時(shí),只要都VBAT不斷,都不影響RTC正常工作,只有當(dāng)系統(tǒng)電源VDD和紐扣電池VBAT都斷開(kāi)時(shí),RTC才停止工作。RTC的時(shí)鐘源有三個(gè)。第一個(gè)由外部高速時(shí)鐘源(HSE)經(jīng)過(guò)128分頻得到,第二個(gè)來(lái)自外部低速時(shí)鐘源(LSE),第三個(gè)來(lái)自?xún)?nèi)部低速時(shí)鐘源(LSI)。只有LSE在系統(tǒng)主電源掉電時(shí),可以由VBAT供電,因此如果想RTC在主電源掉電也能運(yùn)行,只能選擇LSE提供時(shí)鐘。外部低速時(shí)鐘(LSE)的晶振頻率為32.768KHz,經(jīng)過(guò)2^15=32768分頻后,剛好為1Hz,即計(jì)數(shù)器每計(jì)數(shù)一次,剛好就是一秒。
RTC初始化配置
RTC相關(guān)參數(shù)的設(shè)置較少,只需要設(shè)置預(yù)分頻系數(shù)和將RTC時(shí)鐘源配置為L(zhǎng)SE即可。具體代碼如下。需要注意的是,設(shè)置RTC的預(yù)分頻系數(shù)理論上是32768,但是由于實(shí)際的外部晶振的頻率并不是準(zhǔn)確的32.768kHz,所以RTC走時(shí)會(huì)較快或者較慢,這時(shí)就需要根據(jù)實(shí)際情況來(lái)調(diào)整預(yù)分頻系數(shù)了。
//RTC初始化
void RTC_Init(void)
{
hrtc.Instance = RTC;
//這里可以設(shè)置為RTC_AUTO_1_SECOND,自動(dòng)計(jì)算1秒對(duì)應(yīng)的預(yù)分頻值
hrtc.Init.AsynchPrediv = 32776;
if(HAL_RTC_Init(&hrtc) != HAL_OK)
{
printf("RTC初始化失敗\r\n");
}
__HAL_RCC_RTC_ENABLE(); //使能RTC時(shí)鐘
}
//HAL_RTC_Init回調(diào)硬件初始化
void HAL_RTC_MspInit(RTC_HandleTypeDef *RTC_Handle)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_PeriphCLKInitTypeDef PeriphCLKInitStruct;
//配置LSE時(shí)鐘源
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
printf("LSE時(shí)鐘源開(kāi)啟失敗\r\n");
}
//配置RTC時(shí)鐘
PeriphCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
PeriphCLKInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
if(HAL_RCCEx_PeriphCLKConfig(&PeriphCLKInitStruct) != HAL_OK)
{
printf("RTC時(shí)鐘源配置失敗\r\n");
}
__HAL_RTC_ALARM_ENABLE_IT(&hrtc,RTC_IT_ALRA); //使能鬧鐘中斷
HAL_NVIC_SetPriority(RTC_Alarm_IRQn,1,0);
HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);
}
RTC時(shí)間的設(shè)置與獲取
要配置RTC日歷(時(shí)間和日期),使用HAL_RTC_SetTime()和HAL_RTC_SetDate()函數(shù)。讀取RTC日歷,使用HAL_RTC_GetTime()和HAL_RTC_GetDate()函數(shù)。
具體代碼如下,值得注意的是,獲取RTC時(shí)間和日期時(shí),需要先調(diào)用HAL_RTC_GetTime獲取時(shí)間再調(diào)用HAL_RTC_GetDate獲取日期,否則會(huì)出現(xiàn)獲取的時(shí)間不準(zhǔn)等一系列問(wèn)題。
//定義日期和時(shí)間結(jié)構(gòu)體,用于接收時(shí)間和日期信息
RTC_DateTypeDef RTC_DataStruct;
RTC_TimeTypeDef RTC_TimeStruct;
//設(shè)置RTC時(shí)間和日期(數(shù)據(jù)格式 BIN,即使用 10 進(jìn)制表示)
void RTC_SetTime(uint16_t year, uint8_t month, uint8_t day,
uint8_t hour, uint8_t min, uint8_t sec)
{
// 使能訪問(wèn)后備寄存器相關(guān)條件
__HAL_RCC_PWR_CLK_ENABLE(); // 使能 PWR 電源時(shí)鐘
__HAL_RCC_BKP_CLK_ENABLE(); // 使能 BKP 后備寄存器時(shí)鐘
HAL_PWR_EnableBkUpAccess(); // 使能對(duì) BKP 后備寄存器訪問(wèn)
//由該結(jié)構(gòu)體的定義得知年份參數(shù)范圍是0到99,所以要將具體的年份減去2000
RTC_DataStruct.Year = year - 2000;
RTC_DataStruct.Month= month;
RTC_DataStruct.Date= day;
RTC_DataStruct.WeekDay = RTC_WEEKDAY_MONDAY; //星期會(huì)自動(dòng)計(jì)算,這里傳入任意值
HAL_RTC_SetDate(&hrtc,&RTC_DataStruct,RTC_FORMAT_BIN);
RTC_TimeStruct.Hours = hour;
RTC_TimeStruct.Minutes= min;
RTC_TimeStruct.Seconds= sec;
HAL_RTC_SetTime(&hrtc,&RTC_TimeStruct,RTC_FORMAT_BIN);
}
//獲取RTC時(shí)間和日期
void RTC_GetTime(void)
{
HAL_RTC_GetTime(&hrtc,&RTC_TimeStruct,RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc,&RTC_DataStruct,RTC_FORMAT_BIN);
}
這里再插一個(gè)注意:STM32F1系列使用的RTC版本為V1版本。V2(其他系列)支持的所有特性在F1上都不支持。
在V2中,主要的RTC特性由HW管理。而在F1上,日期特性完全由軟件管理。所以,與其他系列相比,有一些限制:
?HAL只支持24小時(shí)格式(不支持12小時(shí)格式)
?日期保存在SRAM中。當(dāng)MCU處于STOP或STANDBY模式時(shí),或者掉電重新上電數(shù)據(jù)將丟失。若想在下次上電或者低功耗喚醒之后仍然可以獲取到日期信息需要另尋他法。
RTC中斷
秒中斷:
如果在RTC_CR寄存器中使能了SECIE位(Second interrupt enable),則每個(gè)TR_CLK周期RTC會(huì)產(chǎn)生一
個(gè)中斷。通常TR_CLK周期為1秒,因此該中斷也被稱(chēng)為秒中斷。
鬧鐘中斷:
鬧鐘中斷就是設(shè)置一個(gè)預(yù)設(shè)定的值,當(dāng)目前時(shí)間到達(dá)設(shè)定的值,就會(huì)產(chǎn)生中斷信號(hào)。當(dāng)然,RTC鬧鐘中斷還有一個(gè)功能就是將MCU從低功耗模式下喚醒,而不用依靠外部中斷喚醒的方式
這里主要介紹鬧鐘中斷的使用,秒中斷的使用方法大同小異。
使用HAL_RTC_SetAlarm()函數(shù)配置RTC鬧鐘。使用HAL_RTC_SetAlarm_IT()函數(shù)配置中斷模式的RTC鬧鐘。
讀取RTC鬧鐘,使用HAL_RTC_GetAlarm()函數(shù)。下面是設(shè)置RTC鬧鐘和鬧鐘中斷函數(shù)的代碼,其中鬧鐘中斷的中斷優(yōu)先級(jí)設(shè)置和使能等已經(jīng)在RTC初始化配置過(guò)了。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-417157.html
//RTC設(shè)置鬧鐘時(shí)間
void RTC_SetAlarm(uint8_t hour,uint8_t min,uint8_t sec)
{
RTC_AlarmStruct.AlarmTime.Hours = hour;
RTC_AlarmStruct.AlarmTime.Minutes = min;
RTC_AlarmStruct.AlarmTime.Seconds = sec;
HAL_RTC_SetAlarm_IT(&hrtc,&RTC_AlarmStruct,RTC_FORMAT_BIN);
}
//RTC鬧鐘中斷服務(wù)函數(shù)
void RTC_Alarm_IRQHandler(void)
{
HAL_RTC_AlarmIRQHandler(&hrtc);
}
//RTC鬧鐘喚醒中斷回調(diào)函數(shù)
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *RTC_Handle)
{
__HAL_RTC_ALARM_EXTI_CLEAR_FLAG(); //清除鬧鐘中斷標(biāo)志位
//你的中斷服務(wù)具體代碼.....
//............
}
以上就是基于STM32HAL庫(kù)的RTC時(shí)鐘的一些我認(rèn)為比較重要的點(diǎn),當(dāng)然還有一些沒(méi)有介紹到,比如如何寫(xiě)入和讀取后備寄存器還有RTC的32位向上計(jì)數(shù)器Uinx 時(shí)間戳轉(zhuǎn)換等等。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-417157.html
到了這里,關(guān)于STM32F1系列HAL庫(kù)開(kāi)發(fā)——RTC實(shí)時(shí)時(shí)鐘的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!