【BLE-CC2640】CC2640之RTC

CC2640 RTC 实现

本篇博文最后修改时间:2017年06月02日,21:49。


一、简介

本文以SimpleBLEPeripheral工程为例,介绍如何通过app的指令对设备进行设置时间、读取时间


二、实验平台

协议栈版本:ble_cc26xx_2_01_00_44423

编译软件:IAR Embedded Workbench for ARM Version 7.40

硬件平台:CC26xxDK开发板

仿真器:XDS100V3(香瓜)

手机平台:小米4S

APP:BLE读写器


版权声明

博主:甜甜的大香瓜

声明:喝水不忘挖井人,转载请注明出处。

原文地址:http://blog.csdn.NET/feilusia

联系方式:897503845@qq.com

香瓜BLE之CC2541群:127442605

香瓜BLE之CC2640群:557278427

香瓜BLE之Android群:541462902

香瓜单片机之STM8/STM32群:164311667
香瓜单片机之Linux群:512598061
香瓜单片机之职场交流群:450154342
甜甜的大香瓜的小店(淘宝店):https://shop217632629.taobao.com/?spm=2013.1.1000126.d21.hd2o8i

四、 实验前提
1、在进行本文步骤前,请先 阅读 以下博文:
暂无


2、在进行本文步骤前,请先 实现以下博文:
1)《CC2640之添加自定义服务》:http://blog.youkuaiyun.com/feilusia/article/details/52333664

五、基础知识

1、什么是RTC?
答:RTC(Real-time clock),也就是实时时钟。它常被用于设备端的时钟计时。

2、手机端已经有时间了,为何还要能通过app设置设备端时间、读取设备端时间?
答:例如智能保温杯项目,商家想根据用户的喝水习惯,在app端给用户合适的健康建议。
这时在智能保温杯中增加RTC时间功能,即可记录下用户一天内喝水的时间,当app连接时将喝水时间上报给app,app即可给出建议“喝水较少,建议多喝水”。

3、CC2640中如何使用RTC?
答:协议栈中已有RTC驱动,使用流程如下:
1)设置RTC时间
①启动RTC计数:调用UTC_init函数。
②填写时间 年、月、日、时、分、秒 ):填写UTCTimeStruct结构体的数据。
转换时间 ):通过UTC_convertUTCSecs函数,将UTCTimeStruct时间(年、月、日、时、分、秒)转换为UTCTime时间(秒)。
④更新时间:调用UTC_setClock函数,参数是③中转换所得的UTCTime时间。

2)读取RTC时间
①获取RTC时间:调用UTC_convertUTCTime函数。
②转换时间( 年、月、日、时、分、秒):将上面获得的 UTCTime时间(秒),转换为UTCTimeStruct时间(年、月、日、时、分、秒)。

4、CC2640中使用RTC时需要注意什么?
答:
1)一天下来,RTC的时钟计数有个几秒误差是正常的,因此尽量每次app连接时能更新一下最新的时间。
2)特别注意协议栈中的月、日、时三个数据,是从0开始,而不是我们通常习惯的1开始。
typedef struct
{
  uint8_t seconds;  // 0-59
  uint8_t minutes;  // 0-59
  uint8_t hour;     // 0-23
  uint8_t day;      // 0-30
  uint8_t month;    // 0-11
  uint16_t year;    // 2000+ 
} UTCTimeStruct;

5、既然协议栈中已有RTC的驱动,为何香瓜要再封装一个驱动文件?
答:为了简化使用、并且解决上述第3点的第2)小点注意事项的问题,香瓜自己封装了一个RTC驱动文件。
该文件中一共3个函数,初始化、读、写,读出来的便是最终可直接拿来使用的转换好的时间数据,非常方便使用。
PS:相信你用过之后会觉得协议栈的原始RTC驱动真TMD的难用。

六、实验步骤
1、添加协议栈的RTC驱动
1)添加UTC_clock.c和UTC_clock.h(文件路径在“……\ble_cc26xx_2_01_00_44423\Projects\ble\common\cc26xx\Time”)


2)IAR设置中增加协议栈RTC文件的路径
$PROJ_DIR$/../../../../../../../Projects/ble/common/cc26xx/Time

3)修改UTC_Clock.h

#include <stdint.h>
不增加这个头文件的话,会报错,缺少uint8等数据类型的定义。

2、编写并添加香瓜RTC驱动
1)写一个香瓜RTC驱动源文件GUA_RTC.c(存放在“……\ble_cc26xx_2_01_00_44423\Projects\ble\SimpleBLEPeripheral\CC26xx\Source\Application\GUA”路径下)
//******************************************************************************        
//name:         GUA_RTC.c        
//introduce:    香瓜自定义的RTC驱动   
//author:       甜甜的大香瓜      
//email:        897503845@qq.com   
//QQ group      香瓜BLE之CC2640(557278427) 
//changetime:   2016.09.04
//******************************************************************************
#include "GUA_RTC.h"

//******************************************************************************        
//name:             GUA_RTC_Init       
//introduce:        香瓜的RTC初始化      
//parameter:        none      
//return:           none     
//author:           甜甜的大香瓜             
//email:            897503845@qq.com 
//QQ group          香瓜BLE之CC2640(557278427)              
//changetime:       2016.09.04                 
//******************************************************************************
void GUA_RTC_Init(void)
{
  //初始化UTC.
  UTC_init(); 
}
//******************************************************************************        
//name:             GUA_RTC_Set       
//introduce:        香瓜的RTC设置时间函数      
//parameter:        pGUA_Timer:传入的时间      
//return:           none     
//author:           甜甜的大香瓜             
//email:            897503845@qq.com 
//QQ group          香瓜BLE之CC2640(557278427)              
//changetime:       2016.09.04                 
//******************************************************************************
void GUA_RTC_Set(UTCTimeStruct *pGUA_Timer)
{
  UTCTimeStruct SetTime; 
  UTCTime SetTime_seconds;  
  
  //转换数据
  SetTime.year = pGUA_Timer->year;              
  SetTime.month = pGUA_Timer->month - 1;        
  SetTime.day = pGUA_Timer->day - 1;           
  SetTime.hour = pGUA_Timer->hour - 1;          
  SetTime.minutes = pGUA_Timer->minutes;       
  SetTime.seconds = pGUA_Timer->seconds; 

  //将时间转换为秒
  SetTime_seconds = UTC_convertUTCSecs(&SetTime);
    
  //设置时间
  UTC_setClock(SetTime_seconds);  
}

//******************************************************************************        
//name:             GUA_RTC_Get       
//introduce:        香瓜的RTC获取时间函数      
//parameter:        pGUA_Timer:传入的时间      
//return:           none     
//author:           甜甜的大香瓜             
//email:            897503845@qq.com 
//QQ group          香瓜BLE之CC2640(557278427)              
//changetime:       2016.09.04                 
//******************************************************************************
void GUA_RTC_Get(UTCTimeStruct *pGUA_Timer)
{
  UTCTimeStruct GetTime;
  
  //获取当前数据
  UTC_convertUTCTime(&GetTime, UTC_getClock());
    
  //抓换数据
  pGUA_Timer->year = GetTime.year;                      
  pGUA_Timer->month = GetTime.month + 1;                
  pGUA_Timer->day = GetTime.day + 1;                    
  pGUA_Timer->hour = GetTime.hour + 1;                  
  pGUA_Timer->minutes = GetTime.minutes;                
  pGUA_Timer->seconds = GetTime.seconds;                
}
 

2)写一个香瓜RTC驱动头文件GUA_RTC.h(存放在“……\ble_cc26xx_2_01_00_44423\Projects\ble\SimpleBLEPeripheral\CC26xx\Source\Application\GUA”路径下)
//******************************************************************************        
//name:         GUA_RTC.h        
//introduce:    香瓜自定义的RTC驱动头文件    
//author:       甜甜的大香瓜      
//email:        897503845@qq.com   
//QQ group      香瓜BLE之CC2640(557278427) 
//changetime:   2016.09.04 
//******************************************************************************
#ifndef _GUA_RTC_H_
#define _GUA_RTC_H_

/*********************头文件************************/ 
#include "UTC_Clock.h"

/*********************函数声明************************/ 
extern void GUA_RTC_Init(void);
extern void GUA_RTC_Set(UTCTimeStruct *pGUA_Timer);
extern void GUA_RTC_Get(UTCTimeStruct *pGUA_Timer);

#endif

3)工程中添加GUA_RTC.c和GUA_RTC.h


4)在IAR设置中添加服务的文件路径
$PROJ_DIR$/../../../Source/Application/GUA     
如果已添加过,就不用添加了。

3、在应用层中添加RTC相关的代码
1)添加GUA_RTC头文件(SimpleBLEPeripheral.c中)
#include "GUA_RTC.h"

2)香瓜RTC初始化(SimpleBLEPeripheral.c的SimpleBLEPeripheral_Init中)
  //香瓜RTC初始化
  GUA_RTC_Init();  
初始化RTC,否则时钟不会计数。

3)添加app的处理指令(替换SimpleBLEPeripheral.c的GUA_CharValueChangeEvt函数
//******************************************************************************            
//name:             GUA_CharValueChangeEvt           
//introduce:        应用层香瓜服务的处理函数         
//parameter:        paramID:特征值ID                  
//return:           none         
//author:           甜甜的大香瓜                 
//email:            897503845@qq.com     
//QQ group          香瓜BLE之CC2640(557278427)                  
//changetime:       2016.09.04                   
//****************************************************************************** 
#define GUA_COMMAND_GET_TIME    0x01
#define GUA_COMMAND_SET_TIME    0x02
static void GUA_CharValueChangeEvt(uint8_t paramID)
{  
  uint16 notify_Handle;     
  uint8 bBuf[20] = {0};   
  uint8 *p = bBuf;  
  UTCTimeStruct GUA_Timer;
  
  switch(paramID)  
  {  
    //char1
    case GUAPROFILE_CHAR1:   
    {                  
      //读出特征值数据
      GUAProfile_GetParameter(GUAPROFILE_CHAR1, p);
        
      //根据通信协议进行事件分发,功能码+年(2字节)+月+日+时+分+秒
      switch(p[0])
      {
        //读当前时间
        case GUA_COMMAND_GET_TIME:
        {
          //获取当前时间
          GUA_RTC_Get(&GUA_Timer);
          
          //整理发送缓冲区
          memset(p, 0xff, GUAPROFILE_CHAR1_LEN); 
          
          p[0] = GUA_COMMAND_GET_TIME;
          p[1] = GUA_Timer.year >> 8;
          p[2] = GUA_Timer.year & 0xff;          
          p[3] = GUA_Timer.month;          
          p[4] = GUA_Timer.day;
          p[5] = GUA_Timer.hour;  
          p[6] = GUA_Timer.minutes;
          p[7] = GUA_Timer.seconds;     
          
          //发送
          GAPRole_GetParameter(GAPROLE_CONNHANDLE, &notify_Handle); 
          GUAprofile_Notify(GUAPROFILE_CHAR1, notify_Handle, p, 20); 
          break;
        }
      
        //设置当前时间
        case GUA_COMMAND_SET_TIME:
        {
          //读出要设置的时间
          GUA_Timer.year = p[1];
          GUA_Timer.year <<= 8;
          GUA_Timer.year |= p[2];          
          GUA_Timer.month = p[3];          
          GUA_Timer.day = p[4];
          GUA_Timer.hour = p[5];  
          GUA_Timer.minutes = p[6];
          GUA_Timer.seconds = p[7];
          
          
          //设置当前时间           
          GUA_RTC_Set(&GUA_Timer);
          
          //获取当前时间
          GUA_RTC_Get(&GUA_Timer);
          
          //整理发送缓冲区
          memset(p, 0xff, GUAPROFILE_CHAR1_LEN); 
          
          p[0] = GUA_COMMAND_SET_TIME;
          p[1] = GUA_Timer.year >> 8;
          p[2] = GUA_Timer.year & 0xff;          
          p[3] = GUA_Timer.month;          
          p[4] = GUA_Timer.day;
          p[5] = GUA_Timer.hour;  
          p[6] = GUA_Timer.minutes;
          p[7] = GUA_Timer.seconds;     
          
          //发送
          GAPRole_GetParameter(GAPROLE_CONNHANDLE, &notify_Handle); 
          GUAprofile_Notify(GUAPROFILE_CHAR1, notify_Handle, p, 20); 
          break;
        }   
        
        //其他
        default:break;        
      }

      break;        
    }
  
    default:break;  
  }  
}  
利用香瓜服务的char1,增加了两条指令:读RTC时间指令、设置RTC时间指令。

七、指令
指令使用简单的通信协议: 功能码(1字节)+年(2字节)+月(1字节)+日(1字节)+时(1字节)+分(1字节)+秒(1字节)+补齐字节(n字节)
1)读RTC时间指令
01ffffffffffffffffffffffffffffffffffffff 
注:
①0x01:功能码( 读RTC时间指令)。
②其余0xff:补齐字节,补齐至20字节,也就是19个0xff。

2)设置RTC时间指令
0207e00904102d1effffffffffffffffffffffff( 2016年09月04日  16点45分30秒
注:
①0x02: 功能码( 设置RTC时间指令 )。
②0x07e0:2016(年)
③0x09:9(月)
④0x04:4(日)
0x10:16(时)
0x2d:45(分)
0x1e:30(秒)
⑧其余0xff:补齐字节,补齐至20字节,也就是13个0xff。

八、实验结果
1、读一下RTC默认时间
1)发送读RTC时间指令


2)读到返回的默认的RTC时间

如果去解析,就会发现它是2000年1月1日1时2分28秒。
其实RTC默认是从 2000年1月1日1时0分0秒开始计算的,只是我发送指令读取时是在计数开始的2分28秒之后了。

2、更新RTC时间
1) 发送设置RTC时间指令2016年09月04日  16点45分30秒


2)读到返回的默认的RTC时间

跟我们发送的指令一样,是 2016年09月04日  16点45分30秒。

3、两分钟后,再次读RTC时间
1)发送读RTC时间指令


2)读到返回的默认的RTC时间

解析后发现它是2016年09月04日16时47分52秒。
比上一次读取的时间多了2分钟,实验结果基本正确。

香瓜未做更为精确的测试去计算误差,大家自行测试吧。
至此,实验结束。





评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

甜甜的大香瓜

谢谢你的支持^_^

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值