简介:
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是通过外部或内部晶振来计时,误差会比较大,所以最好在连接到蓝牙时就校时,并且最好设定为比如每隔几个小时来校时,以使时间显示得比较准确。