找回密码
 立即注册

QQ登录

只需一步,快速开始

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

STM32 RTC模块实现日历功能

[复制链接]
跳转到指定楼层
楼主
ID:104126 发表于 2016-1-23 02:53 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近在用STM32 RTC时钟部分,要实现的功能是通过RTC模块实现日历功能,首先配置RTC模块

int RTC_Configuration(void)
{
    u32count=0x200000;

   
   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)&& (--count) );
    if ( count == 0)//防止没有外部
    {
       return -1;
    }

   
   RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

   
   RCC_RTCCLKCmd(ENABLE);

   
   RTC_WaitForSynchro();

   
   RTC_WaitForLastTask();

   
   RTC_SetPrescaler(32767);

   
   RTC_WaitForLastTask();

    return 0;
}

RTC_Configuration函数主要是初始化RTC硬件部分,打开对应模块的时钟源,设置时钟频率为1HZ及1S中断一次,系统已这个时钟源为基础进行处理!
读取RTC时钟寄存器:时钟寄存器是32位格式分为高16和低16

uint32_t RTC_GetCounter(void)
{
  uint16_t tmp =0;
  tmp =RTC->CNTL;
  return(((uint32_t)RTC->CNTH<< 16 ) | tmp) ;
}

设置秒寄存器
       RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR |RCC_APB1Periph_BKP, ENABLE);

      
       PWR_BackupAccessCmd(ENABLE);

      
       RTC_WaitForLastTask();

      
       RTC_SetCounter(*time);

      
       RTC_WaitForLastTask();

       BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);



其中RTC_SetCounter是设置秒累加器的
void RTC_SetCounter(uint32_t CounterValue)
{
  RTC_EnterConfigMode();

  RTC->CNTH = CounterValue>> 16;

  RTC->CNTL = (CounterValue& RTC_LSB_MASK);
  RTC_ExitConfigMode();
}

也是通过设置RTC高16位RTC->CNTH和RTC低16位寄存器实现的,可见RTC部分也是通过控制RTC->CNTL和 RTC->CNTH 寄存器实现的,写寄存器就是设置,然后读寄存器就是读秒,它是按照设置的1HZ及1s的频率不断的累加,掉电也是可以工作的,因为VBAT管脚外接3V纽扣电池作为后备电池,

设置日期的函数
void set_date(rt_uint32_t year, rt_uint32_t month, rt_uint32_tday)
{
    time_t now;
    struct tm* ti;
    rt_device_tdevice;

    ti = RT_NULL;
   
   time(&now);

    ti =localtime(&now);
    if (ti != RT_NULL)
    {
       ti->tm_year = year -1900;//UNIX下时间处理
       ti->tm_mon = month - 1;
       ti->tm_mday = day;
    }

    now = mktime(ti);

    device =rt_device_find("rtc");
    if (device !=RT_NULL)
    {
       rt_rtc_control(device,RT_DEVICE_CTRL_RTC_SET_TIME, &now);
    }
}
FINSH_FUNCTION_EXPORT(set_date, set date. e.g:set_date(2010,2,28))

void set_time(rt_uint32_t hour, rt_uint32_t minute,rt_uint32_t second)
{
    time_t now;
    struct tm* ti;
    rt_device_tdevice;

    ti = RT_NULL;
   
   time(&now);

    ti =localtime(&now);
    if (ti != RT_NULL)
    {
       ti->tm_hour = hour;
       ti->tm_min = minute;
       ti->tm_sec = second;
    }

    now = mktime(ti);
    device =rt_device_find("rtc");
    if (device !=RT_NULL)
    {
       rt_rtc_control(device,RT_DEVICE_CTRL_RTC_SET_TIME, &now);
    }
}


显示时间和日期函数
void list_date(void)
{
    time_t now;
struct tm *pt;
   time(&now);//读取当前秒数
     pt =localtime(&now); //把当前时间戳转换成对应的日期
if(pt != NULL)
   {
rt_kprintf(" Y = %d M = %d D = %d\n",(1900+pt->tm_year),(1+pt->tm_mon),pt->tm_mday);
rt_kprintf(" %d \n", pt->tm_wday);
rt_kprintf(" %d:%d:%d \n", pt->tm_hour,pt->tm_min, pt->tm_sec);
}
rt_kprintf("%d\n",now);//把秒转换成对应的时间日期
    rt_kprintf("%s\n",ctime(&now));//把秒转换成对应的时间日期
}



上面还有一个需要注意的地方
gmtime在MDK下面是无法正常使用的,嗲有gmtime函数返回的一直是NULL,后来找到库函数使用说明:
gmtime语法:
   #include <time.h>  struct tm *gmtime( const time_t *time );
功能:函数返回给定的统一世界时间(通常是格林威治时间),如果系统不支持统一世界时间系统返回NULL。警告!
相关主题:
localtime(), time(), andasctime().

gmtime()函数是分时区的世界时间,而MDK环境下面是不支持的,所以使用gmtime()函数无法得到想要的结果,解决方法很简单直接localtime()即可

   #include <time.h>  struct tm *localtime( const time_t *time );
功能:函数返回本地日历时间。警告!
相关主题:
gmtime(), time(), andasctime().


localtime函数此处不再去介绍它是标准的POSIX接口函数,所以可以去查POSIX时间相关的API,此处不再详细介绍,总体来说RTC使用还是挺简单的,希望此篇文章能够给像我一样使用RTC的同学一些帮助,


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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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