STM32 RTC小結(jié)
RTC設(shè)置需要涉及對電源(PWR)、備份區(qū)域(BKP)和RCC部分寄存器的改寫。
本文引用地址:http://butianyuan.cn/article/201611/317055.htmRTC所需的晶振在RCC部分的寄存器中選擇。在芯片時(shí)鐘系統(tǒng)中對RTC的時(shí)鐘提供如下圖所示。RTC時(shí)鐘可以從LSI, LSE和HSE分頻中選擇。這些需要對RCC寄存器的一些位進(jìn)行設(shè)置。
RTC的預(yù)分頻器、計(jì)數(shù)器和鬧鐘寄存器在備份區(qū)域中,以保證系統(tǒng)掉電后,在電池供電時(shí)仍能計(jì)數(shù),如下圖所示。在電源部分,系統(tǒng)復(fù)位后,將禁止向備份區(qū)域?qū)懭雰?nèi)容,因此,若要配置RTC,需要在電源部分允許對備份區(qū)域的寫入。
備份區(qū)中有留給用戶寫入數(shù)據(jù)的空間。由于掉電后備份區(qū)中的內(nèi)容仍保持,可以通過對用戶寫入數(shù)據(jù)的比較,知道備份區(qū)中的設(shè)置(尤其是RTC設(shè)置)是否存在。若不存在,需要清空備份區(qū)并重新寫入;若存在,則只需再次寫入備份區(qū)之外的RTC_CR。
由于用戶是通過APB1接口讀寫RTC寄存器,在上電之后,需要先等待APB1接口與RTC同步完成,否則讀取的RTC值可能有誤;完成同步以RTC_CRL的RSF位置1為標(biāo)志。對于寫RTC寄存器,先查詢RTC_CRL的RTOFF位,直到為1,說明上一次操作已經(jīng)完成;再CNF置1,進(jìn)入配置模式;寫寄存器;CNF置0,退出配置模式;等待RTOFF位為1,說明本次寫入已經(jīng)完成。
下面貼一個(gè)可以跑通的簡化流程,完成按秒計(jì)數(shù)的功能。
- #include"stm32f10x.h"
- #include"stm32_eval.h"
- #include
- #include"stm3210c_eval_lcd.h"
- volatileuint32_tTimeDisplay=0;
- intmain(void)
- {
- /*!
- thisisdonethroughSystemInit()functionwhichiscalledfromstartup
- file(startup_stm32f10x_xx.s)beforetobranchtoapplicationmain.
- ToreconfigurethedefaultsettingofSystemInit()function,referto
- system_stm32f10x.cfile
- */
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP,ENABLE);
- PWR_BackupAccessCmd(ENABLE);
- NVIC_Configuration();
- STM3210C_LCD_Init();
- LCD_Clear(LCD_COLOR_WHITE);
- LCD_SetTextColor(LCD_COLOR_BLUE);
- if(BKP_ReadBackupRegister(BKP_DR1)!=0xA5A5)
- {
- RTC_Configuration();
- Time_Adjust();
- BKP_WriteBackupRegister(BKP_DR1,0xA5A5);
- }
- else
- {
- RTC_WaitForSynchro();
- RTC_WaitForLastTask();
- RTC_ITConfig(RTC_IT_SEC,ENABLE);
- RTC_WaitForLastTask();
- }
- RCC_ClearFlag();
- Time_Show();
- }
- voidNVIC_Configuration(void)
- {
- NVIC_InitTypeDefNVIC_InitStructure;
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
- 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);
- }
- voidRTC_Configuration(void)
- {
- BKP_DeInit();
- RCC_LSEConfig(RCC_LSE_ON);
- while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==RESET)
- {}
- RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
- RCC_RTCCLKCmd(ENABLE);
- RTC_WaitForSynchro();
- RTC_WaitForLastTask();
- RTC_ITConfig(RTC_IT_SEC,ENABLE);
- RTC_WaitForLastTask();
- RTC_SetPrescaler(32767);/*RTCperiod=RTCCLK/RTC_PR=(32.768KHz)/(32767+1)*/
- RTC_WaitForLastTask();
- }
- uint32_tTime_Regulate(void)
- {
- uint32_tTmp_HH=0x00,Tmp_MM=0x00,Tmp_SS=0x00;
- return((Tmp_HH*3600+Tmp_MM*60+Tmp_SS));
- }
- voidTime_Adjust(void)
- {
- RTC_WaitForLastTask();
- RTC_SetCounter(0);//Time_Regulate());
- RTC_WaitForLastTask();
- }
- voidTime_Display(uint32_tTimeVar)
- {
- uint32_tTHH=0,TMM=0,TSS=0;
- charbuf[15];
- /*ResetRTCCounterwhenTimeis23:59:59*/
- if(TimeVar==0x0001517F)
- {
- RTC_WaitForLastTask();
- RTC_SetCounter(0x0);
- /*WaituntillastwriteoperationonRTCregistershasfinished*/
- RTC_WaitForLastTask();
- }
- /*Computehours*/
- THH=TimeVar/3600;
- /*Computeminutes*/
- TMM=(TimeVar%3600)/60;
- /*Computeseconds*/
- TSS=(TimeVar%3600)%60;
- sprintf(buf,"%0.2d:%0.2d:%0.2d/r",THH,TMM,TSS);
- LCD_DisplayStringLine(LCD_LINE_2,buf);
- //printf("Time:%0.2d:%0.2d:%0.2d/r",THH,TMM,TSS);
- }
- /**
- *@briefShowsthecurrenttime(HH:MM:SS)ontheHyperterminal.
- *@paramNone
- *@retvalNone
- */
- voidTime_Show(void)
- {
- //printf("/n/r");
- /*Infiniteloop*/
- while(1)
- {
- /*If1shasbeenelapased*/
- if(TimeDisplay==1)
- {
- uint32_tCounter=0;
- Counter=RTC_GetCounter();
- Time_Display(Counter);
- TimeDisplay=0;
- }
- }
- }
- voidRTC_IRQHandler(void)
- {
- if(RTC_GetITStatus(RTC_IT_SEC)!=RESET)
- {
- RTC_WaitForLastTask();
- /*CleartheRTCSecondinterrupt*/
- RTC_ClearITPendingBit(RTC_IT_SEC);
- /*ToggleLED1*/
- //STM_EVAL_LEDToggle(LED1);
- /*Enabletimeupdate*/
- TimeDisplay=1;
- /*WaituntillastwriteoperationonRTCregistershasfinished*/
- RTC_WaitForLastTask();
- }
- }
評論