STM32的RTC學習筆記

STM32的RTC學習筆記

Mcu:STM32F103RBT6

1、RTC簡介

RTC(Real Time Clock)實時時鐘,是STM32片內的一個外設,這個外設使用起來跟普通定時器有一點區別,他是獨立的一個定時器,並且能產生兩個中斷,秒中斷和鬧鐘中斷,他的時鐘源可以由外部或內部驅動,由使用者選擇,一些教程說RTC使用內部低速時鐘(LSI)的時鐘頻率不準,可能跑久了以後就會出現誤差。

2、RTC配置流程

1、使能RTC外設時鐘

RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);//RTC時鐘使能(電源)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);//RTC時鐘使能(備份)

2、使能備份寄存器訪問

PWR_BackupAccessCmd(ENABLE);//使能備份寄存器訪問

開啓後才能對備份寄存器進行訪問,後期可以講數據寫進備份寄存器裏,以防掉電數據丟失。

3、初始化備份寄存器

BKP_DeInit();//初始化備份配置,即復位備份區域

4、時鐘源選擇與使能

RCC_LSICmd(ENABLE);//使能內部低速時鐘

while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == 0 );//內部低速時鐘是否已開啓

RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);//配置RTC時鐘爲內部低速時鐘
RCC_RTCCLKCmd(ENABLE);//使能RTC時鐘

因爲開發板原因,我用的是內部低速時鐘,時鐘頻率爲40K,先使能低速時鐘源,等待使能完畢,然後再配置它爲RTC的時鐘源。

5、寫RTC寄存器

RTC_WaitForSynchro();//等待寄存器校準
RTC_WaitForLastTask();//等待RTC寄存器寫入完成(每次向RTC寄存器寫入後都要調用這個函數)

RTC_ITConfig(RTC_IT_SEC,ENABLE);
RTC_WaitForLastTask();//等待RTC寄存器寫入完成(每次向RTC寄存器寫入後都要調用這個函數)
Rtc_Nvic_Config();

RTC_SetPrescaler(39999);//設置預分頻係數
RTC_WaitForLastTask();//等待RTC寄存器寫入完成(每次向RTC寄存器寫入後都要調用這個函數)

RTC_SetCounter(hour*3600+min*60+sec);//設置當前時間,單位爲秒 
RTC_WaitForLastTask();//等待RTC寄存器寫入完成(每次向RTC寄存器寫入後都要調用這個函數) 

<RTC_WaitForSynchro>等待寄存器校準函數是用於等待RTC的計數寄存器,鬧鐘寄存器和預分頻寄存器進行同步;
<RTC_WaitForLastTask>函數則用於,每次向RTC寫入數據時候,都要等待數據寫入完成後再來進行下面操作;
配置RTC中斷我是用於中斷判斷是否計數值溢出,計數值溢出則已經計了86400個數(一天86400秒),後清0;
預分頻係數配置爲1Hz,則計數器每一秒計一個數,而預分頻係數值爲n(輸入的值)+1,所以40kHz要分配成1Hz要填入數值爲39999;
設置當前時間也是設置當前的計數值,我只設置時間,沒有日期。

6、中斷優先級

NVIC_InitTypeDef NVIC_InitStruct;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStruct.NVIC_IRQChannel = RTC_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);

因爲沒有使用其他中斷,所以中斷優先級隨意。

7、中斷服務函數

uint16_t data = 31;(自己定義的全局變量)

void RTC_IRQHandler(void)
{
    if(RTC_GetITStatus(RTC_IT_SEC) == 1)
    {
        RTC_ClearITPendingBit(RTC_IT_SEC);//清楚中斷標誌位
        RTC_WaitForLastTask();//等待RTC寄存器寫入完成(每次向RTC寄存器寫入後都要調用這個函數)
        if(RTC_GetCounter() == 86399)
        {
            data++;//每過一天,日期加1,一天爲86400秒
            RTC_SetCounter(0); //計數值一到64000就清零,爲午夜12點
            RTC_WaitForLastTask();//等待RTC寄存器寫入完成(每次向RTC寄存器寫入後都要調用這個函數)
        }  
    }       
}

7、LCD屏顯示函數

void RtcTime_Display(void)
{
    uint32_t Time_temp = 0;
    static uint8_t Run_Ping = 0;//閏年爲1,平年爲0
    static uint16_t hour = 0,min = 0,sec = 0,mon = 12,year = 20;
    uint8_t Rtc_arr[20],Counter_arr[20],Rtc_date[20];
    Time_temp = RTC_GetCounter();
	
	//判斷一年是閏年還是平年:
    if(((year%4==0)&&(year%100!=0))||(year%400==0))Run_Ping = 1;
    else Run_Ping = 0;
	
	//判斷一個月有30天還是31天:
    if(((mon==1)||(mon==3)||(mon==5)||(mon==7)||(mon==8)||(mon==10)||(mon==12))&&(data>31))
    {   
        data = 1;
        mon++;  
    }
    if(((mon==4)||(mon==6)||(mon==9)||(mon==11))&&(data>30))
    {   
        data = 1;
        mon++;  
    }

	//特殊月份2月做特殊處理:
    if((mon==2)&&(Run_Ping==1)&&(data>29))
    {
        data = 1;
        mon++;
    }
    else if((mon==2)&&(Run_Ping==0)&&(data>28))
    {
        data = 1;
        mon++;
    }
	//準備跨年:
    if(mon>12)
    {   
        mon = 1;
        year++;
    }
	
	//時分秒:
    hour = Time_temp/3600;
    min = Time_temp%3600/60;
    sec = Time_temp%3600%60;

	//計數值打印:RTC_GetCounter
    sprintf((char *)Counter_arr,"counter = %5d",Time_temp);
    LCD_DisplayStringLine(Line6,Counter_arr); 

	//打印日期,順便打印潤平年:
    if(Run_Ping==1)
    {
        sprintf((char *)Rtc_date," 20%2d-%2d-%2d   Run",year,mon,data);
        LCD_DisplayStringLine(Line3,Rtc_date);
    }
    else
    {
        sprintf((char *)Rtc_date," 20%2d-%2d-%2d   Ping",year,mon,data);
        LCD_DisplayStringLine(Line3,Rtc_date);    
    }
	//打印時間:
    sprintf((char *)Rtc_arr," %2d:%2d:%2d",hour,min,sec);
    LCD_DisplayStringLine(Line4,Rtc_arr);     
}

心得:

1、RTC在配置上跟普通定時器不一樣,但是用法一樣,用RTC做一個時鐘和用一個通用定時器做一個時鐘基本的邏輯是一樣的,但在F429這種更高級一點的MCU裏添加了月份星期的寄存器,使用起來可能更方便;
2、一定要初始化備份寄存器的配置,不然在後面的寄存器校準就會死循環卡死,因爲它在一直等待校準完成,或者可以寫一個延時退出;
3、每次向RTC的寄存器寫入後都要等待寫入完成,若不等待,有可能寫入不進去,比如設置當前時間,就不是自己設置的當前時間開始跑了。

發佈了11 篇原創文章 · 獲贊 12 · 訪問量 2197
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章