找回密码
 立即注册

QQ登录

只需一步,快速开始

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

STM32开发经验之RTC

[复制链接]
跳转到指定楼层
楼主
ID:102014 发表于 2016-1-6 01:52 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
大家好,我是陈滨。本人学STM32也有几个月的时间,从对ARM望而生畏到现在会开发STM32程序,途中付出也不少,很多人看到ARM处理器那些复杂的寄存器,都望而却步;但是本人没有这样子,反而越复杂越想征服它!在开发的过程中,本人积累了不少经验,这个就有其中的RTC。这不,最近在开发3264万年历就积累了这个知识。大家都知道STM32F103系列的RTC只是一个秒计数器,没有提供真正的年月日功能,网上很多资料都把这个计数器进行60进制处理得到时间,但是这个方法效率很低不说,闰年闰月还不好处理;这个是一个问题,而且在设置的时候,处理也是一个问题!经过本人苦苦的研究发现:KEIL已经帮我们完成这个问题。KEIL里面有一个头文件,叫time.h,专门针对32位处理器处理实时时钟功能,该文件支持把计数器直接转换成时间信息,也支持设置时间信息,还支持计算两地的时间差,并且自动计算出星期信息,支持从1970年到2108年的计算,更有趣的是,该文件还支持把计数器的值直接打印成字符串,下面是本人将这个功能直接打印在液晶屏的结果:

下面本人将按实际教大家来写这个程序:
在该头文件中,定义了一个结构体TM:
struct tm {
    int tm_sec;   /* seconds after the minute, 0 to 60
                     (0 - 60 allows for the occasional leap second) */
    int tm_min;   /* minutes after the hour, 0 to 59 */
    int tm_hour;  /* hours since midnight, 0 to 23 */
    int tm_mday;  /* day of the month, 1 to 31 */
    int tm_mon;   /* months since January, 0 to 11 */
    int tm_year;  /* years since 1900 */
    int tm_wday;  /* days since Sunday, 0 to 6 */
    int tm_yday;  /* days since January 1, 0 to 365 */
    int tm_isdst; /* Daylight Savings Time flag */
    union {       /* ABI-required extra fields, in a variety of types */
        struct {
            int __extra_1, __extra_2;
        };
        struct {
            long __extra_1_long, __extra_2_long;
        };
        struct {
            char *__extra_1_cptr, *__extra_2_cptr;
        };
        struct {
            void *__extra_1_vptr, *__extra_2_vptr;
        };
    };
};
从以上的结构体注释可以看出(虽然本人的英语很差,但还是看得懂):在结构体中声明了很多变量,其中的tm_sec就是秒,范围是0-59;还有tm_min,自然就是分钟,下面的tm_hour不用我说了吧?到了tm_yday这个是今年到现在的天数,可以不用管,下面是tm_isdst是设置保存标志,一般也不用管。那么怎么从这个结构体得到时间信息或者是设置时间呢?在这个头文件中,定义了一个函数:
extern _ARMABI struct tm *localtime(const time_t * /*timer*/) __attribute__((__nonnull__(1)));
这个函数的功能是输入一个32位秒计算值,输出一个时间信息结构体,好,现在我来写这个程序:
首先创建一个函数,名字就叫Get_time吧:
void Get_time()
{
u32 temp;
u8 sec,min,hour,day,week,month,year; //定义时间信息变量
struct tm *loca;   //定义一个结构体指针
temp=RTC->CNTH; //从STM32的RTC中取出高16数据赋值给临时变量temp
temp<<=16; //左移16位把数据移向高16位
time_count=temp|RTC->CNTL; //从STM32的RTC中读取低16数据与高16数据相或得到一个32位数据,这个关系数学计算,本人的数学还可以,哈哈
    loca=localtime(&time_count); 将这个32位数据地址赋值给locatime的参数入口,这个时候这个函数开始工作,接下来可以读取信息了
  sec=loca->tm_sec; ///取出秒信息,这个关系到C语言的指针知识,如果你看不懂,再去学习
  min=loca->tm_min; //取出分钟,下面以此类推
  hour=loca->tm_hour;
  day=loca->tm_mday;
  week=loca->wday;
  month=loca->tm_mon;
year=loca->tm_year;
}
以上是得到时间日期的信息,头文件定义了下面的函数:
extern _ARMABI time_t mktime(struct tm * /*timeptr*/) __attribute__((__nonnull__(1)));
这个函数的功能是输入一个结构体时间信息,输出一个32位计数值,
下面本人再写个程序,将设置的时间日期信息写入RTC:
void Set_time(u8 sec,u8 s_min,u8 s_hour,u8 s_day,u8 s_month,u16 s_year)
{
struct tm Rtc; //定义一个时间结构体
u32 tim;
  Rtc.tm_sec=sec; //将参数的值赋值给设置值
  Rtc.tm_min=s_min;
  Rtc.tm_hour=s_hour;
  Rtc.tm_mday=s_day;
  Rtc.tm_mon=s_month-1; //月份从0-11,填入的是1-12,所以减去1
  Rtc.tm_year=s_year-1900; //减去1900年,这个是由keil的函数决定的
Rtc.tm_isdst=-1;
tim=mktime(&Rtc);
  PWR->CR=PWR_CR_DBP; //取消后备保护
RTC->CRL=RTC_CRL_CNF; //进入STM32配置模式
RTC->CNTH=tim>>16;
RTC->CNTL=tim&0xffff;
RTC->CRL&=0x2f;  //退出配置模式
while(!(RTC->CRL&RTC_CRL_RTOFF)); //等待写入完成
PWR->CR=0; //打开保护
}
注意:星期是无需设置的,该函数自动会计算生成!
以上是读出和写入的功能,文件中还定义了另外一个函数:
extern _ARMABI unsigned char *asctime(const struct tm * /*timeptr*/) __attribute__((__nonnull__(1)));
这个就是本文开头的功能了,就是输入一个时间结构体,输出字符串信息,这个不难了吧?大家自己研究。







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

使用道具 举报

沙发
ID:99538 发表于 2016-1-19 15:32 | 只看该作者
楼主辛苦了,开发板是什么牌子的,多少钱,好用吗
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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