日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

stm32f103 rtc 获取 日历 时钟

發布時間:2025/3/21 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 stm32f103 rtc 获取 日历 时钟 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
STM32的RTC實現日歷功能程序發布時間:2011-09-30 14:53:05 ?

STM32的RTC只有一個32位的計數器用來計時,沒有寄存器來存年月日時分秒等。通過設置可以讓這個計數器1秒加1,從0-0XFFFFFFFF大概可以計時136年。程序要設置一個時間起點表示0,一般設置起始時間為1970-01-01 0:0:0。這是UNIX時間戳。如果要設置RTC時間,如2011-9-30 12:00FAMILY: 宋體">到1970-01-01 0:0:0有多少秒,把這個值寫到RTC計數器就可以了。如果要讀當前的年月日時分秒,先讀出32位RTC計數器值,然后以1970-01-01 0:0:0為時間基點,算出當前時間。

為什么要設置起始時間為1970-01-01 0:0:0,因為有一個TIME.H文件,里面有寫好的設置時間函數,讀時間函數,使用的參數就是32位計數器。不過我沒有找到這個文件。不使用這個文件的函數的話,起始時間可以設為任意值。

直接使用32位計數器來計算時間的優點:

1、可以不使用RTC的秒中斷,因為在STM32掉電時,只有電池供電,這時RTC在計數,但是STM32的內核中斷應該是不能使用的。

2、不用在備份區保存年月日等參數。

下面是網上找的程序,我實際測試過,是正確的。

//時間結構體

typedef struct

{

?????? u8 hour;

?????? u8 min;

?????? u8 sec;?????????????????

?????? //公歷日月年周

?????? u16 w_year;

?????? u8? w_month;

?????? u8? w_date;

?????? u8? week;????????????

}tm;

tm timer;

/*

?*

?*

?*/

void RTC_Config(void)

{

???? u16 u16_WaitForOscSource;

???? //我們在BKP的后備寄存器1中,存了一個特殊字符0xA5A5

??? //第一次上電或后備電源掉電后,該寄存器數據丟失,

??? //表明RTC數據丟失,需要重新配置

??? if (BKP_ReadBackupRegister(BKP_DR1) != 0x5A5A)

??? {

??????? //重新配置RTC

??????? /* Enable PWR and BKP clocks */

? ??? RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);

?

? ??? /* Allow access to BKP Domain */

? ??? PWR_BackupAccessCmd(ENABLE);

?

? ??? /* Reset Backup Domain */

????? ?BKP_DeInit();

?

? ??? /* Enable LSE */

? ??? RCC_LSEConfig(RCC_LSE_ON);

?????? for(u16_WaitForOscSource=0;u16_WaitForOscSource<5000;u16_WaitForOscSource++)

??? ?????? {

??? ?????? }

? ??? /* Wait till LSE is ready */

? ??? while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);

?

? ??? /* Select LSE as RTC Clock Source */

? ??? RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

?

? ??? /* Enable RTC Clock */

? ??? RCC_RTCCLKCmd(ENABLE);

?

? ??? /* Wait for RTC registers synchronization */

? ??? RTC_WaitForSynchro();

?

? ??? /* Wait until last write operation on RTC registers has finished */

? ??? RTC_WaitForLastTask();

?

? ??? /* Enable the RTC Second */

? ??? RTC_ITConfig(RTC_IT_SEC, ENABLE);

?

? ??? /* Wait until last write operation on RTC registers has finished */

????? ?RTC_WaitForLastTask();

?

? ??? /* Set RTC prescaler: set RTC period to 1sec */

? ??? RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) */

?

? ??? /* Wait until last write operation on RTC registers has finished */

? ??? RTC_WaitForLastTask();

??????? //配置完成后,向后備寄存器中寫特殊字符0xA5A5

??????? BKP_WriteBackupRegister(BKP_DR1, 0x5A5A);

?????? ?RTC_Set(2011,01,01,0,0,0);//默認時間

??? }

??? else

??? {

??????? //若后備寄存器沒有掉電,則無需重新配置RTC

??????? //這里我們可以利用RCC_GetFlagStatus()函數查看本次復位類型

??????? RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);

??? ?????? ?for(u16_WaitForOscSource=0;u16_WaitForOscSource<5000;u16_WaitForOscSource++);

??????? if (RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET)

??????? {

??????????? //這是上電復位

??????? }

??????? else if (RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET)

??????? {

??????????? //這是外部RST管腳復位

??????? }

??????? //清除RCC中復位標志

??????? RCC_ClearFlag();

?

??????? //雖然RTC模塊不需要重新配置,且掉電后依靠后備電池依然運行

??????? //但是每次上電后,還是要使能RTCCLK???????

??????? //RCC_RTCCLKCmd(ENABLE);

??????? //等待RTC時鐘與APB1時鐘同步

??????? //RTC_WaitForSynchro();

?

??????? //使能秒中斷

??????? RTC_ITConfig(RTC_IT_SEC, ENABLE);

??????? //等待操作完成

??????? RTC_WaitForLastTask();

??? }

?

?

?

??? return;

}

//判斷是否是閏年函數

//月份?? 1? 2? 3? 4? 5? 6? 7? 8? 9? 10 11 12

//閏年?? 31 29 31 30 31 30 31 31 30 31 30 31

//非閏年 31 28 31 30 31 30 31 31 30 31 30 31

//輸入:年份

//輸出:該年份是不是閏年.1,是.0,不是

u8 Is_Leap_Year(u16 year)

{?????????????????? ?

?????? if(year%4==0) //必須能被4整除

?????? {

????????????? if(year%100==0)

????????????? {

???????????????????? if(year%400==0)return 1;//如果以00結尾,還要能被400整除 ????? ???

???????????????????? else return 0;??

????????????? }else return 1;??

?????? }else return 0;

}???? ?????????????????? ???

//設置時鐘

//把輸入的時鐘轉換為秒鐘

//以1970年1月1日為基準

//1970~2099年為合法年份

//返回值:0,成功;其他:錯誤代碼.

//月份數據表???????????????????????????????????????????????????????????????????????

u8 const table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; //月修正數據表 ?

//平年的月份日期表

const u8 mon_table[12]={31,28,31,30,31,30,31,31,30,31,30,31};

u8 RTC_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec)

{

?????? u16 t;

?????? u32 seccount=0;

?????? if(syear<2000||syear>2099)return 1;//syear范圍1970-2099,此處設置范圍為2000-2099???? ??

?????? for(t=1970;t<syear;t++) //把所有年份的秒鐘相加

?????? {

????????????? if(Is_Leap_Year(t))seccount+=31622400;//閏年的秒鐘數

????????????? else seccount+=31536000;????????????????? ? //平年的秒鐘數

?????? }

?????? smon-=1;

?????? for(t=0;t<smon;t++)????? ?? //把前面月份的秒鐘數相加

?????? {

????????????? seccount+=(u32)mon_table[t]*86400;//月份秒鐘數相加

????????????? if(Is_Leap_Year(syear)&&t==1)seccount+=86400;//閏年2月份增加一天的秒鐘數????? ??

?????? }

?????? seccount+=(u32)(sday-1)*86400;//把前面日期的秒鐘數相加

?????? seccount+=(u32)hour*3600;//小時秒鐘數

??? seccount+=(u32)min*60;????? //分鐘秒鐘數

?????? seccount+=sec;//最后的秒鐘加上去

?????????????????????????????????????????????????????????????????????????????????????????? ???

?????? //設置時鐘

? /*? RCC->APB1ENR|=1<<28;//使能電源時鐘

??? RCC->APB1ENR|=1<<27;//使能備份時鐘

?????? PWR->CR|=1<<8;? ??//取消備份區寫保護

?????? //上面三步是必須的!*/

?????? PWR_BackupAccessCmd(ENABLE);

?????? RTC_WaitForLastTask();

?????? RTC_SetCounter(seccount);

?????? RTC_WaitForLastTask();

?????? return 0;? ???

}

//得到當前的時間

//返回值:0,成功;其他:錯誤代碼.

u8 RTC_Get(void)

{

?????? static u16 daycnt=0;

?????? u32 timecount=0;

?????? u32 temp=0;

?????? u16 temp1=0;

?

?????? timecount=RTC_GetCounter();

?????? ??

?????? /*timecount=RTC->CNTH;//得到計數器中的值(秒鐘數)

?????? timecount<<=16;

?????? timecount+=RTC->CNTL;??? */??????????

?

?????? temp=timecount/86400;?? //得到天數(秒鐘數對應的)

?????? if(daycnt!=temp)//超過一天了

?????? {???? ?

????????????? daycnt=temp;

????????????? temp1=1970;? //從1970年開始

????????????? while(temp>=365)

????????????? {?????????????????????????

???????????????????? if(Is_Leap_Year(temp1))//是閏年

???????????????????? {

??????????????????????????? if(temp>=366)temp-=366;//閏年的秒鐘數

??????????????????????????? else {temp1++;break;}?

???????????????????? }

???????????????????? else temp-=365;???? ? //平年

???????????????????? temp1++;?

????????????? }??

????????????? timer.w_year=temp1;//得到年份

????????????? temp1=0;

????????????? while(temp>=28)//超過了一個月

????????????? {

???????????????????? if(Is_Leap_Year(timer.w_year)&&temp1==1)//當年是不是閏年/2月份

???????????????????? {

??????????????????????????? if(temp>=29)temp-=29;//閏年的秒鐘數

??????????????????????????? else break;

???????????????????? }

???????????????????? else

???????????????????? {

??????????????????????????? if(temp>=mon_table[temp1])temp-=mon_table[temp1];//平年

??????????????????????????? else break;

???????????????????? }

???????????????????? temp1++;?

????????????? }

????????????? timer.w_month=temp1+1;//得到月份

????????????? timer.w_date=temp+1;? //得到日期

?????? }

?????? temp=timecount%86400;???? //得到秒鐘數?? ???

?????? timer.hour=temp/3600;???? //小時

?????? timer.min=(temp%3600)/60; //分鐘?????

?????? timer.sec=(temp%3600)%60; //秒鐘

?????? timer.week=RTC_Get_Week(timer.w_year,timer.w_month,timer.w_date);//獲取星期??

?????? return 0;

}????

//獲得現在是星期幾

//功能描述:輸入公歷日期得到星期(只允許1901-2099年)

//輸入參數:公歷年月日

//返回值:星期號????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

u8 RTC_Get_Week(u16 year,u8 month,u8 day)

{????

?????? u16 temp2;

?????? u8 yearH,yearL;

??????

?????? yearH=year/100;???? yearL=year%100;

?????? // 如果為21世紀,年份數加100?

?????? if (yearH>19)yearL+=100;

?????? // 所過閏年數只算1900年之后的?

?????? temp2=yearL+yearL/4;

?????? temp2=temp2%7;

?????? temp2=temp2+day+table_week[month-1];

?????? if (yearL%4==0&&month<3)temp2--;

?????? return(temp2%7);

}

總結

以上是生活随笔為你收集整理的stm32f103 rtc 获取 日历 时钟的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。