TA的每日心情 | 奋斗 2014-11-26 16:58 |
---|
签到天数: 34 天 连续签到: 1 天 [LV.5]常住居民I
|
本帖最后由 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 时间。- app_timer_id_t m_calender_timer_id; /**< 日历定时器. */
- #define CALENDER_TIEMR_INTERVAL APP_TIMER_TICKS(1000, APP_TIMER_PRESCALER) /**< 日历定时器定时间隙. */
复制代码 记得在每次新建app_timer的时候,都应该将 APP_TIMER_MAX_TIMERS +1- /**@brief Function for handling the calender timer timeout.
- * @details This function will be called each time the calender timer expires.
- * @param[in] p_context Pointer used for passing some arbitrary information (context) from the
- * app_start_timer() call to the timeout handler.
- */
- void calender_timeout_handler(void * p_context)
- {
- TimeSeconds++;
- UNUSED_PARAMETER(p_context);
- }
复制代码- // Create Calender timer
- err_code = app_timer_create(&m_calender_timer_id,
- APP_TIMER_MODE_REPEATED,
- calender_timeout_handler);
- APP_ERROR_CHECK(err_code);
复制代码 |
|