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 获取 日历 时钟相关推荐

  1. STM32F103 RTC LSE/LSI为时钟源的代码

    内部低速时钟LSI为40K,外部低速时钟LSE-32.768K 在头文件有如下定义用以适用LSI或者LSE: #define RTC_LSI_EN (0) /*内部低速时钟-40K*/ #define ...

  2. STM32F103学习笔记四 时钟系统

    STM32F103学习笔记四 时钟系统 本文简述了自己学习时钟系统的一些框架,参照风水月 1. 单片机中时钟系统的理解 1.1 概述 时钟是单片机的脉搏,是单片机的驱动源 用任何一个外设都必须打开相应 ...

  3. 系统时间不够精确?试试RTC(实时时钟)

    01 什么是 RTC? RTC(实时时钟)是 real time clock的简称,是一种计算机时钟,通常采用集成电路的形式,专门用于计时.自然地,它可以计算秒.分.小时.日.月甚至是年.RTC可以在 ...

  4. php取月份函数,分享3个php获取日历的函数

    本文给大家汇总了3个php获取日历的函数,分别是php获取指定日期的月份的日历.获取指定日期所在月的开始日期与结束日期.获取当前星期的日期范围,都是比较常用的方法,有需要的小伙伴可以参考下. 提供一个 ...

  5. c语言日历时钟编程,基于DS1302的日历时钟(1602液晶显示DS1302时钟)C语言程序设计...

    原标题:基于DS1302的日历时钟(1602液晶显示DS1302时钟)C语言程序设计 //实例98:基于 的 #include //包含寄存器的头文件 #include //包含_nop_()函数定义 ...

  6. STM32F103学习之系统时钟配置

    STM32F103学习之系统时钟配置 文章目录 一.根据时钟源配置系统时钟(SYSCLK) 二.系统时钟配置步骤 1.代码 一.根据时钟源配置系统时钟(SYSCLK) 1.开发板选择的8M的外部高速时 ...

  7. MSP430G2553 launchpad 口袋板 口袋实验平台 数字电子日历时钟设计 秒表 闹钟 整点报时 万年历 电子时钟

    题10 数字电子日历/时钟设计 设计一个基于MSP430的电子日历和时钟. 基本要求 (1)可通过按键在日历和时间之间切换显示: (2)可由按键调整日期和时间 (3)可整点报时('铆.嘟"声 ...

  8. 单片机 RTC获取时间转时间戳

    项目场景: RTC获取时间后,需要转换成时间戳 问题描述 一开始百度了很多时间转时间戳,但是都没发现能直接用的.这边写下来,方便以后过来看. 解决方案: #include "time.h&q ...

  9. html 日历时钟插件,日历时钟 - Chrome生产工具插件 - 画夹插件网

    日历时钟的开发背景 在我们的电脑中通常可以很简单地查看到时间和日期,而Windows7早期的小工具中也存在着日期和时间的小工具,但是由于小工具的安全问题,最终Windows操作系统废弃掉.今天给大家推 ...

最新文章

  1. 定时器php windows任务计划
  2. JZOJ 5490. 【清华集训2017模拟11.28】图染色
  3. 你知道SQL的这些错误用法吗?
  4. 平台or职位,你怎么选?
  5. Firefox 5 公开测试下载
  6. 边缘计算 ai_在边缘探索AI!
  7. Java多线程编程:变量共享分析(Thread)
  8. 修改epo服务器 gps,epo
  9. c 语言bool 类型数据_C ++中的bool数据类型
  10. python中赋值,深拷贝,浅拷贝区别
  11. 使用SQL Server进行时间点恢复
  12. 【Mybatis源码解析】Mybatis源码体系结构
  13. System.InvalidOperationException: Failed to deploy distro docker-desktop......
  14. 关于统计分析软件Spss统计个案数和实际数据的个案数不一致问题
  15. python语句中str_python中str是什么意思
  16. R语言---scale函数,match函数和%in%详解
  17. Qt之绘制折线图:图标以及坐标轴设置
  18. selenium框架爬取p2p问题平台信息,需加载点击页面的。
  19. 正则表达式 “.*“匹配任意字符
  20. 一套关于 Django 的笔试题

热门文章

  1. Jvm之用java解析class文件
  2. Scala基础教程(六):字符串、数组、集合
  3. GitHub添加SSH keys报错Key is invalid. It must begin with 'ssh-ed25519', 'ssh-rsa', 'ssh-dss', 'ecdsa-sha
  4. Eclipse安装Hadoop插件配置Hadoop开发环境
  5. 【OpenCV3】Opencv3.2.0在Hisi3521下的交叉编译和移植
  6. 保存/恢复cxGrid布局
  7. 软件成本度量方法及CMMI V2.0,你Get到了吗?
  8. 全能系统监控工具dstat
  9. 传统制造业面临大数据的7种改变方式
  10. 科沃斯旺宝与阿里云联合参加通信展