查看: 8264|回复: 25

[教程] Nordic 实现日历(年月日时分秒)

  [复制链接]

8

主题

2

好友

404

积分

秀才

Rank: 3Rank: 3

  • TA的每日心情
    奋斗
    2014-11-26 16:58
  • 签到天数: 34 天

    [LV.5]常住居民I

    发表于 2014-5-14 14:41:27 |显示全部楼层
    本帖最后由 Depth 于 2016-7-1 13:40 编辑

    前言】 NORDIC 带有两个RTC ,但是都只是简单的计数器而已,并没有用作日历的寄存器。但是很多项目都需要国际标准时间(UTC)用作日历信息。在不加外部RTC新片的前提下,我们有两种方法实现。

             1.利用RTC的 counter 寄存器。设置一个开始时间,每次需要日历信息的时候,都去读一次 counter 寄存器中的值,并换算成时间,加上开始时间,就可知道当前的时间了。
              优点: 不需要中断,可以在CPU完全休眠的状态下,保持RTC的运行,等需要用到时间信息的时候,才需要去RTC counter 寄存器中读一次数据,再换算即可。
             缺点: RTC的counter 寄存器的位数有限,假定我们将RTC设置为1秒加一次。那么对于32位RTC 从0x00000000~ 0xFFFFFFFF, 理论上可以计136年 RTC才会溢出。(当然RTC跑那么长时间,误差肯定会很大)。对于24位RTC ,0x000000~0xFFFFFF 理论上可以计194天。

             2. 利用RTC 中断,设置每秒产生一次中断,每次中断让一个自定义的变量 加 1,每次需要时间的时候,把这个变量转换成时间。
              优点: 定时时间会比较准,RTC可以用来做其他的事情。
              缺点:每次都要响应RTC中断,CPU被频繁唤醒,耗电量会增加。

    【正文】

           Nordic51822 自带了两个RTC,但是如果使能 SolfDevice,  RTC0是被占用的,用户不可操作。RTC1是一个24位计数器,如果利用方法1,将只能计数194天。而且RTC1还用作了app_timer 的实现,我们最好不要直接去操作其寄存器。于是我选择了方法2.
    并且利用nordic官方的app_timer模块,来实现定时。


    下面是实现步骤:
    (Note: 以下日历的实现算法,并非原创,借鉴于TI CC2540 官方文档,  我修复了一个它会出现4月0号的BUG,经验证其他没有问题)

          1. 新建一个app_timer .(包括  TIMER_ID , TIEMR_INTERVAL, timeout_handler  )
          2.自定义一个变量TimeSeconds ,用来保存秒信息。
          3.创建一个函数  UTCTime   ConvertUTCSecs( UTCTimeStruct *tm ) ,用来把上位机的日历信息,转换成秒.(默认的开始时间为 2000年01月01日00时00分00秒)
          4.创建一个函数void ConvertUTCTime( UTCTimeStruct *tm, UTCTime secTime ),用来把秒转换成UTC时间。
          5.启动定时器                     err_code = app_timer_start(m_calender_timer_id, CALENDER_TIEMR_INTERVAL , NULL);
                APP_ERROR_CHECK(err_code);
          6.当接收到上位机日历信息后,调用 ConvertUTCSecs ();
          7.在每次日历定时器定时时间到后,TimeSeconds +1
          8. 当需要读取当前时间时,  调用  ConvertUTCTime ()  ,将TimeSeconds  转换成 UTC 时间。
    1. app_timer_id_t                               m_calender_timer_id;                         /**< 日历定时器. */
    2. #define CALENDER_TIEMR_INTERVAL              APP_TIMER_TICKS(1000, APP_TIMER_PRESCALER)   /**< 日历定时器定时间隙. */
    复制代码
    记得在每次新建app_timer的时候,都应该将 APP_TIMER_MAX_TIMERS +1
    1. /**@brief Function for handling the calender timer timeout.
    2. * @details This function will be called each time the calender timer expires.
    3. * @param[in]   p_context   Pointer used for passing some arbitrary information (context) from the
    4. *                          app_start_timer() call to the timeout handler.
    5. */
    6. void calender_timeout_handler(void * p_context)
    7. {   
    8.     TimeSeconds++;

    9.           UNUSED_PARAMETER(p_context);
    10. }
    复制代码
    1.    // Create Calender timer
    2.     err_code = app_timer_create(&m_calender_timer_id,
    3.                                 APP_TIMER_MODE_REPEATED,
    4.                                 calender_timeout_handler);

    5.     APP_ERROR_CHECK(err_code);
    复制代码

    app_calender.rar

    2.51 KB, 下载次数: 292

    售价: 2 铜板  [记录]

    nordic 实现日历(年月日时分秒)

    回复

    使用道具 举报

    0

    主题

    0

    好友

    48

    积分

    白丁

    Rank: 1

  • TA的每日心情
    擦汗
    2014-5-23 23:46
  • 签到天数: 6 天

    [LV.2]偶尔看看I

    发表于 2014-5-14 17:43:41 |显示全部楼层
    还没理解过来,现支持一下~~~~~~
    回复

    使用道具 举报

    0

    主题

    0

    好友

    257

    积分

    秀才

    Rank: 3Rank: 3

  • TA的每日心情
    奋斗
    2016-5-25 22:50
  • 签到天数: 10 天

    [LV.3]偶尔看看II

    发表于 2014-5-14 23:40:29 |显示全部楼层
    学习中!!!!!!
    回复

    使用道具 举报

    4

    主题

    0

    好友

    283

    积分

    秀才

    Rank: 3Rank: 3

  • TA的每日心情
    擦汗
    2014-8-6 09:10
  • 签到天数: 51 天

    [LV.5]常住居民I

    发表于 2014-5-15 08:02:34 |显示全部楼层
    好东西,支持支持~
    回复

    使用道具 举报

    4

    主题

    0

    好友

    283

    积分

    秀才

    Rank: 3Rank: 3

  • TA的每日心情
    擦汗
    2014-8-6 09:10
  • 签到天数: 51 天

    [LV.5]常住居民I

    发表于 2014-5-15 08:03:48 |显示全部楼层
    好东西~支持支持~
    回复

    使用道具 举报

    8

    主题

    2

    好友

    404

    积分

    秀才

    Rank: 3Rank: 3

  • TA的每日心情
    奋斗
    2014-11-26 16:58
  • 签到天数: 34 天

    [LV.5]常住居民I

    发表于 2014-5-15 08:50:43 |显示全部楼层
    ayuan_h0n9 发表于 2014-5-14 17:43
    还没理解过来,现支持一下~~~~~~

    原理就是借助一个自定义全局变量 TimeSeconds ,可实现UTC时间(国际标准时间格式)的转换。
    做日历我们必须要有的两个函数就是 设置时间  Set_Clock(),和 提取时间 Get_Clock().
    设置时间 是你希望从哪个时间开始计时,提取时间 是获得当前时间。
    在 Set_Clock() 中,我们通过算法,把UTC时间转换为  TimeSeconds.
    并且每 1 s 让 TimeSeconds + 1,(由一个循环计数的定时器来实现)
    在我们需要获得当前时间的时候,Get_Clock(). 会将 现在的 TimeSeconds 转换成 UTC 时间。
    回复

    使用道具 举报

    3

    主题

    1

    好友

    130

    积分

    童生

    Rank: 2

  • TA的每日心情
    郁闷
    2014-4-24 15:31
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    发表于 2014-5-15 09:01:06 |显示全部楼层
    支持。RTC讲的很好。有空讲下time定时器吗?要寄存器的设置
    回复

    使用道具 举报

    59

    主题

    18

    好友

    2977

    积分

    进士

    Rank: 5Rank: 5

  • TA的每日心情
    奋斗
    2016-9-9 09:13
  • 签到天数: 293 天

    [LV.8]以坛为家I

    爱板会员勋章 活跃会员勋章

    发表于 2014-5-15 09:26:23 |显示全部楼层
    顶一个~~~~~~~~~~~~~~~~~~~~
    第五年了,这次一定要坚持到底,不留遗憾!!!
    回复

    使用道具 举报

    0

    主题

    1

    好友

    88

    积分

    童生

    Rank: 2

  • TA的每日心情
    开心
    2014-4-19 09:57
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2014-5-15 10:25:01 |显示全部楼层
    学习了-----------------------
    回复

    使用道具 举报

    1083

    主题

    2

    好友

    1万

    积分

    翰林

    Rank: 7Rank: 7Rank: 7

  • TA的每日心情
    开心
    2014-9-23 05:09
  • 签到天数: 113 天

    [LV.6]常住居民II

    发表于 2014-5-27 09:28:49 |显示全部楼层
    谢谢楼主分享
    回复

    使用道具 举报

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

    关闭

    站长推荐上一条 /6 下一条


    手机版|爱板网 |网站地图  

    GMT+8, 2016-12-7 22:23 , Processed in 0.158168 second(s), 20 queries , Memcache On.

    苏公网安备 32059002001056号

    Powered by Discuz!

    回顶部