STM32F4——RTC實時時鐘
對于STM32F的RTC實時時鐘提供了一個日歷時鐘,兩個可編程鬧鐘中斷和一個具有中斷功能的可編程喚醒標(biāo)志。由于RTC的時鐘配置是在后備區(qū)域,因此在后備區(qū)域供電正常的情況下,即使是系統(tǒng)復(fù)位或者是從待機模式喚醒之后時間依然維持不變。下邊就以RTC模塊的框圖為引線,對RTC的相關(guān)功能和操作做相關(guān)介紹。
本文引用地址:http://m.butianyuan.cn/article/201611/317628.htm二、框圖:
首先是時鐘的選擇,一般選擇LSE作為時鐘來源,頻率32768Hz,隨后經(jīng)過一個7位的異步預(yù)分頻(默認(rèn)值為127+1)和一個15位的同步預(yù)分頻(255+1),得到1Hz的時鐘頻率,對于日歷的配置,寄存器RTC_TR用來配置時間(時分秒),寄存器RTC_DR用來配置日期(年月日和星期),由于寄存器RTC_SSR由第一次分頻得到的頻率來驅(qū)動,則寄存器RTC_SSR可以存放比秒還要小的單位壓秒(該寄存器不用來設(shè)置,可以讀?。t[鐘A和鬧鐘B設(shè)定時間,來和當(dāng)前時間比較,如果相等則會觸發(fā)相應(yīng)的中斷。下邊是自動喚醒功能,首先是預(yù)分頻器的分頻,得到相應(yīng)時鐘,然后選擇相應(yīng)的時鐘驅(qū)動自動重載寄存器(RTC_WUTR),自動重載寄存器的值依次遞減至0,做相應(yīng)的中斷操作。
三、相關(guān)配置過程及其相關(guān)庫函數(shù):
基于上邊的認(rèn)識,分析代碼及其配置過程。
RTC時間設(shè)置:
ErrorStatus RTC_Set_Time(u8 hour,u8 min,u8 sec,u8 ampm){RTC_TimeTypeDef RTC_TimeTypeInitStructure;RTC_TimeTypeInitStructure.RTC_Hours=hour; //小時RTC_TimeTypeInitStructure.RTC_Minutes=min; //分鐘RTC_TimeTypeInitStructure.RTC_Seconds=sec; //秒RTC_TimeTypeInitStructure.RTC_H12=ampm; //時間格式return RTC_SetTime(RTC_Format_BIN,&RTC_TimeTypeInitStructure);}
RTC日期設(shè)置:
ErrorStatus RTC_Set_Date(u8 year,u8 month,u8 date,u8 week){RTC_DateTypeDef RTC_DateTypeInitStructure;RTC_DateTypeInitStructure.RTC_Date=date; //日RTC_DateTypeInitStructure.RTC_Month=month; //月RTC_DateTypeInitStructure.RTC_WeekDay=week; //星期RTC_DateTypeInitStructure.RTC_Year=year; //年return RTC_SetDate(RTC_Format_BIN,&RTC_DateTypeInitStructure);}
RTC初始化:
u8 My_RTC_Init(void){RTC_InitTypeDef RTC_InitStructure;u16 retry=0X1FFF; RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);//使能PWR時鐘PWR_BackupAccessCmd(ENABLE); //使能后備寄存器訪問 if(RTC_ReadBackupRegister(RTC_BKP_DR0)!=0x5050) //是否第一次配置?{RCC_LSEConfig(RCC_LSE_ON);//LSE 開啟 while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) //檢查指定的RCC標(biāo)志位設(shè)置與否,等待低速晶振就緒{retry++;delay_ms(10);}if(retry==0)return 1; //LSE 開啟失敗. RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //設(shè)置RTC時鐘(RTCCLK),選擇LSE作為RTC時鐘 RCC_RTCCLKCmd(ENABLE); //使能RTC時鐘 RTC_InitStructure.RTC_AsynchPrediv = 0x7F;//RTC異步分頻系數(shù)(1~0X7F)RTC_InitStructure.RTC_SynchPrediv = 0xFF;//RTC同步分頻系數(shù)(0~7FFF)RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;//RTC設(shè)置為,24小時格式RTC_Init(&RTC_InitStructure);RTC_Set_Time(20,59,56,RTC_H12_AM); //設(shè)置時間RTC_Set_Date(15,8,13,1); //設(shè)置日期RTC_WriteBackupRegister(RTC_BKP_DR0,0x5050); //標(biāo)記已經(jīng)初始化過了} return 0;}
設(shè)置鬧鐘時間:
void RTC_Set_AlarmA(u8 week,u8 hour,u8 min,u8 sec){ EXTI_InitTypeDef EXTI_InitStructure;RTC_AlarmTypeDef RTC_AlarmTypeInitStructure;RTC_TimeTypeDef RTC_TimeTypeInitStructure;RTC_AlarmCmd(RTC_Alarm_A,DISABLE);//關(guān)閉鬧鐘A RTC_TimeTypeInitStructure.RTC_Hours=hour;//小時RTC_TimeTypeInitStructure.RTC_Minutes=min;//分鐘RTC_TimeTypeInitStructure.RTC_Seconds=sec;//秒RTC_TimeTypeInitStructure.RTC_H12=RTC_H12_AM;RTC_AlarmTypeInitStructure.RTC_AlarmDateWeekDay=week;//星期RTC_AlarmTypeInitStructure.RTC_AlarmDateWeekDaySel=RTC_AlarmDateWeekDaySel_WeekDay;//按星期鬧RTC_AlarmTypeInitStructure.RTC_AlarmMask=RTC_AlarmMask_None;//精確匹配星期,時分秒RTC_AlarmTypeInitStructure.RTC_AlarmTime=RTC_TimeTypeInitStructure;RTC_SetAlarm(RTC_Format_BIN,RTC_Alarm_A,&RTC_AlarmTypeInitStructure);RTC_ClearITPendingBit(RTC_IT_ALRA);//清除RTC鬧鐘A的標(biāo)志EXTI_ClearITPendingBit(EXTI_Line17);//清除LINE17上的中斷標(biāo)志位 RTC_ITConfig(RTC_IT_ALRA,ENABLE);//開啟鬧鐘A中斷RTC_AlarmCmd(RTC_Alarm_A,ENABLE);//開啟鬧鐘A EXTI_InitStructure.EXTI_Line = EXTI_Line17;//LINE17EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中斷事件EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿觸發(fā) EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能LINE17EXTI_Init(&EXTI_InitStructure);//配置NVIC_InitStructure.NVIC_IRQChannel = RTC_Alarm_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;//搶占優(yōu)先級1NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//子優(yōu)先級2NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中斷通道NVIC_Init(&NVIC_InitStructure);//配置}
周期喚醒配置:
void RTC_Set_WakeUp(u32 wksel,u16 cnt){ EXTI_InitTypeDef EXTI_InitStructure;RTC_WakeUpCmd(DISABLE);//關(guān)閉WAKE UPRTC_WakeUpClockConfig(wksel);//喚醒時鐘選擇RTC_SetWakeUpCounter(cnt);//設(shè)置WAKE UP自動重裝載寄存器RTC_ClearITPendingBit(RTC_IT_WUT); //清除RTC WAKE UP的標(biāo)志EXTI_ClearITPendingBit(EXTI_Line22);//清除LINE22上的中斷標(biāo)志位 RTC_ITConfig(RTC_IT_WUT,ENABLE);//開啟WAKE UP 定時器中斷RTC_WakeUpCmd( ENABLE);//開啟WAKE UP 定時器 EXTI_InitStructure.EXTI_Line = EXTI_Line22;//LINE22EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中斷事件EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿觸發(fā) EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能LINE22EXTI_Init(&EXTI_InitStructure);//配置NVIC_InitStructure.NVIC_IRQChannel = RTC_WKUP_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;//搶占優(yōu)先級1NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//子優(yōu)先級2NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中斷通道NVIC_Init(&NVIC_InitStructure);//配置}
相關(guān)的中斷服務(wù)函數(shù):
//RTC鬧鐘中斷服務(wù)函數(shù)void RTC_Alarm_IRQHandler(void){ if(RTC_GetFlagStatus(RTC_FLAG_ALRAF)==SET)//ALARM A中斷{RTC_ClearFlag(RTC_FLAG_ALRAF);//清除中斷標(biāo)志printf("ALARM A!rn");} EXTI_ClearITPendingBit(EXTI_Line17); //清除中斷線17的中斷標(biāo)志 }//RTC WAKE UP中斷服務(wù)函數(shù)void RTC_WKUP_IRQHandler(void){ if(RTC_GetFlagStatus(RTC_FLAG_WUTF)==SET)//WK_UP中斷{ RTC_ClearFlag(RTC_FLAG_WUTF); //清除中斷標(biāo)志LED1=!LED1; } EXTI_ClearITPendingBit(EXTI_Line22);//清除中斷線22的中斷標(biāo)志 }
評論