stm32f103 rtc 获取 日历 时钟
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 获取 日历 时钟相关推荐
- STM32F103 RTC LSE/LSI为时钟源的代码
内部低速时钟LSI为40K,外部低速时钟LSE-32.768K 在头文件有如下定义用以适用LSI或者LSE: #define RTC_LSI_EN (0) /*内部低速时钟-40K*/ #define ...
- STM32F103学习笔记四 时钟系统
STM32F103学习笔记四 时钟系统 本文简述了自己学习时钟系统的一些框架,参照风水月 1. 单片机中时钟系统的理解 1.1 概述 时钟是单片机的脉搏,是单片机的驱动源 用任何一个外设都必须打开相应 ...
- 系统时间不够精确?试试RTC(实时时钟)
01 什么是 RTC? RTC(实时时钟)是 real time clock的简称,是一种计算机时钟,通常采用集成电路的形式,专门用于计时.自然地,它可以计算秒.分.小时.日.月甚至是年.RTC可以在 ...
- php取月份函数,分享3个php获取日历的函数
本文给大家汇总了3个php获取日历的函数,分别是php获取指定日期的月份的日历.获取指定日期所在月的开始日期与结束日期.获取当前星期的日期范围,都是比较常用的方法,有需要的小伙伴可以参考下. 提供一个 ...
- c语言日历时钟编程,基于DS1302的日历时钟(1602液晶显示DS1302时钟)C语言程序设计...
原标题:基于DS1302的日历时钟(1602液晶显示DS1302时钟)C语言程序设计 //实例98:基于 的 #include //包含寄存器的头文件 #include //包含_nop_()函数定义 ...
- STM32F103学习之系统时钟配置
STM32F103学习之系统时钟配置 文章目录 一.根据时钟源配置系统时钟(SYSCLK) 二.系统时钟配置步骤 1.代码 一.根据时钟源配置系统时钟(SYSCLK) 1.开发板选择的8M的外部高速时 ...
- MSP430G2553 launchpad 口袋板 口袋实验平台 数字电子日历时钟设计 秒表 闹钟 整点报时 万年历 电子时钟
题10 数字电子日历/时钟设计 设计一个基于MSP430的电子日历和时钟. 基本要求 (1)可通过按键在日历和时间之间切换显示: (2)可由按键调整日期和时间 (3)可整点报时('铆.嘟"声 ...
- 单片机 RTC获取时间转时间戳
项目场景: RTC获取时间后,需要转换成时间戳 问题描述 一开始百度了很多时间转时间戳,但是都没发现能直接用的.这边写下来,方便以后过来看. 解决方案: #include "time.h&q ...
- html 日历时钟插件,日历时钟 - Chrome生产工具插件 - 画夹插件网
日历时钟的开发背景 在我们的电脑中通常可以很简单地查看到时间和日期,而Windows7早期的小工具中也存在着日期和时间的小工具,但是由于小工具的安全问题,最终Windows操作系统废弃掉.今天给大家推 ...
最新文章
- 定时器php windows任务计划
- JZOJ 5490. 【清华集训2017模拟11.28】图染色
- 你知道SQL的这些错误用法吗?
- 平台or职位,你怎么选?
- Firefox 5 公开测试下载
- 边缘计算 ai_在边缘探索AI!
- Java多线程编程:变量共享分析(Thread)
- 修改epo服务器 gps,epo
- c 语言bool 类型数据_C ++中的bool数据类型
- python中赋值,深拷贝,浅拷贝区别
- 使用SQL Server进行时间点恢复
- 【Mybatis源码解析】Mybatis源码体系结构
- System.InvalidOperationException: Failed to deploy distro docker-desktop......
- 关于统计分析软件Spss统计个案数和实际数据的个案数不一致问题
- python语句中str_python中str是什么意思
- R语言---scale函数,match函数和%in%详解
- Qt之绘制折线图:图标以及坐标轴设置
- selenium框架爬取p2p问题平台信息,需加载点击页面的。
- 正则表达式 “.*“匹配任意字符
- 一套关于 Django 的笔试题
热门文章
- Jvm之用java解析class文件
- Scala基础教程(六):字符串、数组、集合
- GitHub添加SSH keys报错Key is invalid. It must begin with 'ssh-ed25519', 'ssh-rsa', 'ssh-dss', 'ecdsa-sha
- Eclipse安装Hadoop插件配置Hadoop开发环境
- 【OpenCV3】Opencv3.2.0在Hisi3521下的交叉编译和移植
- 保存/恢复cxGrid布局
- 软件成本度量方法及CMMI V2.0,你Get到了吗?
- 全能系统监控工具dstat
- 传统制造业面临大数据的7种改变方式
- 科沃斯旺宝与阿里云联合参加通信展