新聞中心

        stm32的RTC操作

        作者: 時(shí)間:2016-12-03 來(lái)源:網(wǎng)絡(luò) 收藏
        分為兩個(gè)文件:
        rtc.c

        /*******************************************************************************
        * 文件名 :rtc.c
        * 描述 :wit_yuan
        * 論壇 :
        **********************************************************************************/
        #include "rtc.h"
        #include "stdio.h"
        #include "misc.h"
        uint8_t const *WEEK_STR[] = {"日", "一", "二", "三", "四", "五", "六"};
        uint8_t const *zodiac_sign[] = {"豬", "鼠", "牛", "虎", "兔", "龍", "蛇", "馬", "羊", "猴", "雞", "狗"};

        /* 秒中斷標(biāo)志,進(jìn)入秒中斷時(shí)置1,當(dāng)時(shí)間被刷新之后清0 */
        __IO uint32_t TimeDisplay;
        extern struct rtc_time systemtime;
        /*
        * 函數(shù)名:NVIC_Configuration
        * 描述 :配置RTC秒中斷的主中斷優(yōu)先級(jí)為1,次優(yōu)先級(jí)為0
        * 輸入 :無(wú)
        * 輸出 :無(wú)
        * 調(diào)用 :外部調(diào)用
        */
        void RTC_NVIC_Configuration(void)
        {
        NVIC_InitTypeDef NVIC_InitStructure;

        /* Configure one bit for preemption priority */
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

        /* Enable the RTC Interrupt */
        NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
        }

        /*
        * 函數(shù)名:RTC_Configuration
        * 描述 :配置RTC
        * 輸入 :無(wú)
        * 輸出 :無(wú)
        * 調(diào)用 :外部調(diào)用
        */
        void RTC_Configuration(void)
        {
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
        PWR_BackupAccessCmd(ENABLE);
        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);
        RTC_WaitForLastTask();
        }

        /*
        * 函數(shù)名 :Time_Regulate
        * 描述 :返回用戶在超級(jí)終端中輸入的時(shí)間值,并將值儲(chǔ)存在
        * RTC 計(jì)數(shù)寄存器中。
        * 輸出 :用戶在超級(jí)終端中輸入的時(shí)間值,單位為 s
        * 調(diào)用 :內(nèi)部調(diào)用
        * editted : 2014-07-05
        * author : wit_yuan
        */
        extern struct rtc_time systemtime;

        uint32_t Time_Regulate(struct rtc_time *tm)
        {
        tm->tm_year = systemtime.tm_year + 2000;
        tm->tm_mon = systemtime.tm_mon;
        tm->tm_mday = systemtime.tm_mday;
        tm->tm_hour = systemtime.tm_hour;
        tm->tm_min = systemtime.tm_min;
        tm->tm_sec = systemtime.tm_sec;
        /* Return the value to store in RTC counter register */
        return(((systemtime.tm_hour) * 3600 + (systemtime.tm_min) * 60 + systemtime.tm_sec));
        }


        /*
        * 函數(shù)名:Time_Adjust
        * 描述 :時(shí)間調(diào)節(jié)
        * 輸入 :無(wú)
        * 輸出 :無(wú)
        * 調(diào)用 :外部調(diào)用
        */
        void Time_Adjust(struct rtc_time *tm)
        {
        /* Wait until last write operation on RTC registers has finished */
        RTC_WaitForLastTask();
        /* Get time entred by the user on the hyperterminal */
        Time_Regulate(tm);

        /* Get wday */
        GregorianDay(tm);
        /* Change the current time */
        RTC_SetCounter(mktimev(tm));
        /* Wait until last write operation on RTC registers has finished */
        RTC_WaitForLastTask();
        }


        /*
        * 函數(shù)名:Time_Display
        * 描述 :顯示當(dāng)前時(shí)間值
        * 輸入 :-TimeVar RTC計(jì)數(shù)值,單位為 s
        * 輸出 :無(wú)
        * 調(diào)用 :內(nèi)部調(diào)用
        */
        void Time_Display(uint32_t TimeVar,struct rtc_time *tm)
        {
        volatile uint32_t THH = 0, TMM = 0, TSS = 0;
        uint32_t BJ_TimeVar;
        /*把標(biāo)準(zhǔn)時(shí)間轉(zhuǎn)換為北京時(shí)間*/
        BJ_TimeVar =TimeVar + 8*60*60;

        to_tm(BJ_TimeVar, tm);/*把定時(shí)器的值轉(zhuǎn)換為北京時(shí)間*/
        }
        /*
        * 函數(shù)名:Time_Show
        * 描述 :在超級(jí)終端中顯示當(dāng)前時(shí)間值
        * 輸入 :無(wú)
        * 輸出 :無(wú)
        * 調(diào)用 :外部調(diào)用
        */
        void Time_Show(void)
        {

        }


        uint8_t USART_Scanf(uint32_t value)
        {
        uint32_t index = 0;
        uint32_t tmp[2] = {0, 0};

        while (index < 2)
        {
        while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET)
        {}
        tmp[index++] = (USART_ReceiveData(USART1));
        if ((tmp[index - 1] < 0x30) || (tmp[index - 1] > 0x39))
        {
        index--;
        }
        }
        index = (tmp[1] - 0x30) + ((tmp[0] - 0x30) * 10);
        if (index > value)
        {
        return 0xFF;
        }
        return index;
        }

        void Time_Config(struct rtc_time *tm)
        {
        if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5)
        {
        RTC_Configuration();
        Time_Adjust(tm);
        BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);
        }
        else
        {
        if (RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET)
        {
        }
        else if (RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET)
        {
        }
        RTC_WaitForSynchro();

        RTC_ITConfig(RTC_IT_SEC, ENABLE);

        RTC_WaitForLastTask();
        }
        #ifdef RTCClockOutput_Enable
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
        PWR_BackupAccessCmd(ENABLE);
        BKP_TamperPinCmd(DISABLE);
        BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock);
        #endif
        RCC_ClearFlag();
        //Time_Show();
        }

        /*********************************************************
        * funciton : drv_set_time
        * description : set the rtc time
        * time : 2015-08-22 pm
        * author : wit_yuan
        ***********************************************************/
        void drv_set_time(struct rtc_time *tm)
        {
        RTC_Configuration();
        Time_Adjust(tm);
        BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);
        RCC_ClearFlag();
        }

        /*********************************************************
        * funciton : wit_get_time
        * description : get the rtc time
        * time : 2015-07-07 am
        * author : wit_yuan
        ***********************************************************/

        void drv_get_time(struct rtc_time *tm)
        {
        uint32_t TimeVar;
        //struct rtc_time tm;
        uint32_t BJ_TimeVar;
        TimeVar = RTC_GetCounter();
        *tm = systemtime;
        BJ_TimeVar =TimeVar + 8 * 60 * 60;
        to_tm(BJ_TimeVar, tm);/*把定時(shí)器的值轉(zhuǎn)換為北京時(shí)間*/
        // printf("%d年%d月%d日 %d時(shí)%d分%d秒 n",tm.tm_year,tm.tm_mon,tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec);
        // return tm;
        }



        void RTC_IRQHandler(void)
        {
        if (RTC_GetITStatus(RTC_IT_SEC) != RESET)
        {
        RTC_ClearITPendingBit(RTC_IT_SEC);
        TimeDisplay = 1;
        if (TimeDisplay == 1)
        {
        TimeDisplay = 0;
        }
        RTC_WaitForLastTask();
        }
        }


        void init_rtc(void )
        {
        RTC_NVIC_Configuration();
        Time_Config(&systemtime);
        }


        /*****************************END OF FILE****2015-08-23 guide by wit_yuan**************************/

        本文引用地址:http://www.104case.com/article/201612/325188.htm
        2、date.c

        #include "date.h"

        #define FEBRUARY 2
        #define STARTOFTIME 1970
        #define SECDAY 86400L
        #define SECYR (SECDAY * 365)
        #define leapyear(year) ((year) % 4 == 0)
        #define days_in_year(a) (leapyear(a) ? 366 : 365)
        #define days_in_month(a) (month_days[(a) - 1])

        static int month_days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

        /*
        * This only works for the Gregorian calendar - i.e. after 1752 (in the UK)
        */
        /*計(jì)算公歷*/
        void GregorianDay(struct rtc_time * tm)
        {
        int leapsToDate;
        int lastYear;
        int day;
        int MonthOffset[] = { 0,31,59,90,120,151,181,212,243,273,304,334 };

        lastYear=tm->tm_year-1;

        /*計(jì)算從公元元年到計(jì)數(shù)的前一年之中一共經(jīng)歷了多少個(gè)閏年*/
        leapsToDate = lastYear/4 - lastYear/100 + lastYear/400;
        /*如若計(jì)數(shù)的這一年為閏年,且計(jì)數(shù)的月份在2月之后,則日數(shù)加1,否則不加1*/
        if((tm->tm_year%4==0) &&
        ((tm->tm_year%100!=0) || (tm->tm_year%400==0)) &&
        (tm->tm_mon>2)) {
        /*
        * We are past Feb. 29 in a leap year
        */
        day=1;
        } else {
        day=0;
        }
        day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + tm->tm_mday ; /*計(jì)算從公元元年元旦到計(jì)數(shù)日期一共有多少天*/

        tm->tm_wday=day%7;
        }

        /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
        * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
        * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
        *
        * [For the Julian calendar (which was used in Russia before 1917,
        * Britain & colonies before 1752, anywhere else before 1582,
        * and is still in use by some communities) leave out the
        * -year/100+year/400 terms, and add 10.]
        *
        * This algorithm was first published by Gauss (I think).
        *
        * WARNING: this function will overflow on 2106-02-07 06:28:16 on
        * machines were long is 32-bit! (However, as time_t is signed, we
        * will already get problems at other places on 2038-01-19 03:14:08)

        *ADD by fire:本函數(shù)在工程中的輸入?yún)?shù)為北京時(shí)間,
        所以在轉(zhuǎn)換成時(shí)間戳?xí)r最后要從北京時(shí)間轉(zhuǎn)換為標(biāo)準(zhǔn)時(shí)間的時(shí)間戳
        */
        u32 mktimev(struct rtc_time *tm)
        {
        if (0 >= (int) (tm->tm_mon -= 2)) { /* 1..12 -> 11,12,1..10 */
        tm->tm_mon += 12; /* Puts Feb last since it has leap day */
        tm->tm_year -= 1;
        }

        return (((
        (u32) (tm->tm_year/4 - tm->tm_year/100 + tm->tm_year/400 + 367*tm->tm_mon/12 + tm->tm_mday) +
        tm->tm_year*365 - 719499
        )*24 + tm->tm_hour /* now have hours */
        )*60 + tm->tm_min /* now have minutes */
        )*60 + tm->tm_sec-8*60*60; /* finally seconds */
        /*Add by fire: -8*60*60 把輸入的北京時(shí)間轉(zhuǎn)換為標(biāo)準(zhǔn)時(shí)間,
        再寫(xiě)入計(jì)時(shí)器中,確保計(jì)時(shí)器的數(shù)據(jù)為標(biāo)準(zhǔn)的UNIX時(shí)間戳*/
        }

        void to_tm(u32 tim, struct rtc_time * tm)
        {
        register u32 i;
        register long hms, day;

        day = tim / SECDAY;
        hms = tim % SECDAY;
        /* Hours, minutes, seconds are easy */
        tm->tm_hour = hms / 3600;
        tm->tm_min = (hms % 3600) / 60;
        tm->tm_sec = (hms % 3600) % 60;
        /* Number of years in days */ /*算出當(dāng)前年份,起始的計(jì)數(shù)年份為1970年*/
        for (i = STARTOFTIME; day >= days_in_year(i); i++) {
        day -= days_in_year(i);
        }
        tm->tm_year = i;
        /* Number of months in days left */ /*計(jì)算當(dāng)前的月份*/
        if (leapyear(tm->tm_year)) {
        days_in_month(FEBRUARY) = 29;
        }
        for (i = 1; day >= days_in_month(i); i++) { //程序編寫(xiě)時(shí)間是2013年8月
        day -= days_in_month(i);
        }
        days_in_month(FEBRUARY) = 28;
        tm->tm_mon = i;
        /* Days are what is left over (+1) from all that. *//*計(jì)算當(dāng)前日期*/
        tm->tm_mday = day + 1;//+ 1; //2013年8月3日修改,實(shí)現(xiàn)功能
        /*
        * Determine the day of week
        */
        GregorianDay(tm);

        }

        對(duì)外接口:
        函數(shù):init_rtc(),drv_set_time(),drv_get_time().
        變量:extern struct rtc_time systemtime;


        關(guān)鍵詞: stm32RTC操

        評(píng)論


        技術(shù)專(zhuān)區(qū)

        關(guān)閉
        主站蜘蛛池模板: 佛教| 准格尔旗| 雷州市| 理塘县| 灌阳县| 平顺县| 沅江市| 通道| 斗六市| 太康县| 濮阳市| 胶州市| 柘荣县| 新巴尔虎左旗| 融水| 德昌县| 醴陵市| 宿州市| 南宫市| 新民市| 错那县| 龙川县| 阜宁县| 昌江| 驻马店市| 灵石县| 吴川市| 巴楚县| 平舆县| 共和县| 宁化县| 南充市| 若羌县| 呼伦贝尔市| 红河县| 甘肃省| 尖扎县| 台北县| 黔东| 伽师县| 聂荣县|