找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1168|回复: 0
打印 上一主题 下一主题
收起左侧

STM32 RTc模块

[复制链接]
跳转到指定楼层
楼主
ID:384719 发表于 2018-8-9 17:45 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
芯片内集成了计数器+存储器  外面接电源+晶振即可代码表现为一个init+一个算法


#include "rtc.h"

void STEP1_RCC(void)
{
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
}

void STEP2_NVIC(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

        NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
}



void Set_alarm(uint32_t AlarmValue)
{
        if(RTC_GetITStatus(RTC_IT_ALR) != RESET)                                 //alarm interrupt
        {
                RTC_ClearITPendingBit(RTC_IT_ALR);
        }

        RTC_ITConfig(RTC_IT_ALR, ENABLE);
        RTC_WaitForLastTask();
        RTC_SetAlarm(AlarmValue);
}

void Disable_alarm(void)
{
  RTC_ITConfig(RTC_IT_ALR , DISABLE);
  RTC_WaitForLastTask();
}

void RTC_Configuration(void)
{
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);

        //允许访问BKP区域
        PWR_BackupAccessCmd(ENABLE);
        //复位BKP
        BKP_DeInit();
        //使能外部低速晶振 32.768K
        RCC_LSEConfig(RCC_LSE_ON);
        //等待外部低速晶振就绪
        while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==RESET);
        //选择RTC外部时钟为低速晶振 32.768K
        RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
        //使能RTC时钟
        RCC_RTCCLKCmd(ENABLE);
        //等待RTC寄存器同步
        RTC_WaitForSynchro();
        //等待写RTC寄存器完成
        RTC_WaitForLastTask();
        //使能RTC秒中断
        RTC_ITConfig(RTC_IT_SEC,ENABLE);         
       
        Set_alarm(2);
        //设置预分频
        RTC_SetPrescaler(32767);
        //等待写RTC寄存器完成
        RTC_WaitForLastTask();
}

void Clock_Init(void)
{
        if(BKP_ReadBackupRegister(BKP_DR1)!=0xA5A5)
        {
                 //第一次运行  初始化设置
                //RTC初始化
                RTC_Configuration();
                //等待写RTC寄存器完成
            RTC_WaitForLastTask();
                //设置时间初值
                RTC_SetCounter(0xA442);
                //等待写RTC寄存器完成
            RTC_WaitForLastTask();
                //写配置标志
                BKP_WriteBackupRegister(BKP_DR1,0xA5A5);
        }
        else
        {
                //等待RTC寄存器同步
                RTC_WaitForSynchro();
                //等待写RTC寄存器完成
                RTC_WaitForLastTask();
                //使能RTC秒中断
          RTC_ITConfig(RTC_IT_SEC,ENABLE);
    //等待写RTC寄存器完成
                RTC_WaitForLastTask();
          Set_alarm(2);
        }

        RCC_ClearFlag();//清除复位标志;
}

void RTC_Init(void)
{
        STEP1_RCC();
        STEP2_NVIC();
        Clock_Init();
}






/***********************判断是否为闰年********/
const uint8_t monthTable[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
/*
    函数功能:判断是否闰年
    函数参数:需要判断的年份
    返回值:    返回1成功 其他失败
*/
static uint8_t isLeapYear(uint16_t mYear)   
{
    if (((mYear%4 == 0)&&((mYear%100) != 0))||(mYear%400) == 0)
    {
        return 1;
    }else
    {
        return 0;
    }
}
/********************************************************************************/
/*
    函数功能:日期转换为秒并配置RTC
    函数参数:年、月、日、时、分、秒
    返回值:    返回0成功 其他失败
*/
uint8_t RTC_SetSec(_TM* DATA)
{
    uint32_t secCount = 0;
    uint16_t i;
          uint16_t year=DATA->year;
          uint8_t month=DATA->mon;
          uint8_t day=DATA->day;
          uint8_t hour=DATA->hour;
          uint8_t minute=DATA->min;
          uint8_t sec=DATA->sec;

    if (year <1970 || year >2099)
    {
        return 1;
    }
    for (i=1970; i<year; i++)
    {
        if (isLeapYear(i))
        {
            secCount += 31622400UL;
        }
        else
        {
            secCount += 31536000UL;
        }
    }

    for (i=0; i<month-1; i++)
    {
        secCount += ((uint32_t)monthTable[i]*86400UL);
        if (isLeapYear(year) && i==1)   //润年 多加一天
        {
            secCount += 86400UL;
        }
    }
    secCount += (uint32_t)(day-1) * 86400UL;   
    secCount += (uint32_t)(hour)*3600;
    secCount += (uint32_t)(minute)*60;
    secCount += (uint32_t)(sec);


    /*执行以下操作可以使能对备份寄存器和 RTC 的访问:
    1)通过设置寄存器 RCC_APB1ENR 的 PWREN 和 BKPEN 位来打开电源和后备接口的时钟
    2)电源控制寄存器(PWR_CR)的 DBP 位来使能对后备寄存器和 RTC 的访问
    */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP, ENABLE);
    PWR_BackupAccessCmd(ENABLE);
    RTC_SetCounter(secCount);
    RTC_WaitForLastTask();
    return 0;
}
/********************************************************************************/
/*
    函数功能:从RTC获取秒转换为年、月、日、星期、时、分、秒
                        存入 struct thisDate 中
    函数参数:struct thisDate
    返回值:    返回0成功 其他失败
*/
uint8_t RTC_GetDate(_TM* thisDate)
{
    uint32_t timeCount = 0;
    uint32_t Count ;
    uint16_t tmp = 0;
    timeCount = RTC_GetCounter();
    Count = timeCount/86400UL;  //计算出天数
    thisDate->week = (4+Count)%7;
    if (Count !=0)                  //大于一天
    {
        tmp = 1970;                     //从1970年开始
        while(Count>=365)
        {
            if (isLeapYear(tmp))//是闰年
            {
                if (Count>= 366)    //天数大于366
                {
                    Count -= 366;
                }else
                {
                    tmp++;                  //天数小于366 最后一年
                    break;
                }
            }else
            {
                Count -= 365;       //平年
            }
                tmp++;
        }
        thisDate->year = tmp;   //获取到了年
        tmp = 0;
        while(Count>= 28)
        {
            if (isLeapYear(thisDate->year) && tmp == 1)
            {
                if (Count >= 29)
                {
                    Count -= 29;
                }
                else   
                {
                    break;  //当年是闰年 二月 某时
                }
            }else
            {
                if (Count >= monthTable[tmp])
                {
                    Count -= monthTable[tmp];
                }else
                {
                    break;
                }
            }
                tmp ++;
        }
        thisDate->mon = tmp+1;    //获取到月
        thisDate->day = Count+1;    //获取到日
    }
    Count = timeCount%86400UL;
    thisDate->hour = Count/3600;
    thisDate->min= (Count%3600)/60;
    thisDate->sec = (Count%3600)%60;
    return 0;
}


_RTC Rtc = {RTC_Init,RTC_GetDate,RTC_SetSec};
_TM  Today={12,27,13,1,8,8,2018};





#ifndef __RTC_H
#define __RTC_H

#include "time.h"//等待研究
#include "stm32f10x_bkp.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_rtc.h"
#include "stm32f10x_pwr.h"
#include "misc.h"

typedef struct
{
  u8 sec;
        u8 min;
        u8 hour;
        u8 week;
        u8 day;
        u8 mon;
        u16 year;
}_TM;


typedef struct
{
        void (*init)(void);
        u8 (*GetTime)(_TM *);
        u8 (*SetTime)(_TM *);
}_RTC;

extern _RTC Rtc;
extern _TM  Today;
#endif


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表