nrf51822实现日历
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 时间。