简介:
TI BLE协议栈提供的例程里面有一个TimeApp,从文档TI_BLE_Software_Developer's_Guide.pdf的第16章介绍来看,是使用了类似RTC的时钟来实现一个蓝牙手表功能。这两天研究了一下,另外在网上也找到了一篇写得还算详尽的博文(参考文献1),发现TI BLE协议栈已经封装好一个RTC,在OSAL_ClockBLE.c文件中,该文件在资料中供参考,也可以去参考(http://www.eeskill.com/article/id/38669)中,里面有作者的一些中文注释,可以帮助大家更好的理解。
OSAL_ClockBLE.c中的主要函数及功能:
1)void osalTimeUpdate( void );
更新时间
2)void osal_setClock( UTCTime newTime );
设定时间,输入参数为秒数,指的是从2000年1月1日0时0分0秒开始的秒数。UTCTime的定义如下:
// number of seconds since 0 hrs, 0 minutes, 0 seconds, on the
// 1st of January 2000 UTC
typedef uint32 UTCTime;
3)UTCTime osal_getClock( void );
获取当前时间,返回的是秒数,UTCTime的定义见2),秒数也是从2000年1月1日0时0分0秒开始的秒数。
4)void osal_ConvertUTCTime( UTCTimeStruct *tm, UTCTime secTime );
将秒数转换成UTCTimeStruct结构。UTCTimeStruct结构的定义如下:
typedef struct
{
uint8 seconds; // 0-59
uint8 minutes; // 0-59
uint8 hour; // 0-23
uint8 day; // 0-30
uint8 month; // 0-11
uint16 year; // 2000+
} UTCTimeStruct;
5)UTCTime osal_ConvertUTCSecs( UTCTimeStruct *tm );
将UTCTimeStruct结构转换成秒数。
简单来说,BLE协议栈中的RTC是从2000年1月1日0时0分0秒开始定时的,获取和设定时间时都用的这个秒数,对于用户来说,转换成UTCTimeStruct最方便。所以要获取当前时间,要调用osal_getClock( )后再调用osal_ConvertUTCTime( ),将秒数转成UTCTimeStruct;要修改设定时间,可以将新的时间填充到UTCTimeStruct中,再调用osal_ConvertUTCSecs( ),然后调用osal_setClock( ),这样就重新更新了时间。
测试的步骤可以参考如下:
1)添加一个Time Profile,定义一个Time Service和一个Time Characteristic,该特征值是6字节的的数组,用来更新时间,可以理解为手机App通过蓝牙来同步时间。数据用来保存年月日时分秒的信息,年只保存后两位,即,如2015年,只用15来表示,毕竟一个字节最大只能到255.
2)定义一个UTCTimeStruct变量,用来保存蓝牙更新过来的时间,同时调用相关函数来设定时间。
3)定义一个周期事件,如30s,获取当前时间,通过LCD或通过UART到PC上来显示时间。
下面是一段通过特征值来设定时间并显示的代码片段。这里只显示了时和分,如15:57
UTCTimeStruct *Time;
uint8 TimeDisplayBuf[5];
uint8 newValue[6];
UTCTimeStruct TimeTemp;
UTCTime newTime;
TIME_GetParameter(TIME_CHAR, newValue);
TimeTemp.year = 2000 + newValue[0];
TimeTemp.month = newValue[1];
TimeTemp.day = newValue[2];
TimeTemp.hour = newValue[3];
TimeTemp.minutes = newValue[4];
TimeTemp.seconds = newValue[5];
newTime = osal_ConvertUTCSecs( &TimeTemp );
osal_setClock( newTime );
osalTimeUpdate();
osal_ConvertUTCTime( Time, osal_getClock() );
TimeDisplayBuf[0] = (Time->hour) / 10 + '0';
TimeDisplayBuf[1] = (Time->hour) % 10 + '0';
TimeDisplayBuf[3] = (Time->minutes) / 10 + '0';
TimeDisplayBuf[4] = (Time->minutes) % 10 + '0';
TimeDisplayBuf[2] = ‘:’;
LCD_ShowString(0,4, TimeDisplayBuf);
CC2541的RTC是通过外部或内部晶振来计时,误差会比较大,所以最好在连接到蓝牙时就校时,并且最好设定为比如每隔几个小时来校时,以使时间显示得比较准确。