【BLE
本篇博文最后修改时间: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读写器
三、版权声明
博主:甜甜的大香瓜
声明:喝水不忘挖井人,转载请注明出处。
原文地址:.NET/feilusia
联系方式:897503845@qq
香瓜BLE之CC2541群:127442605
香瓜BLE之CC2640群:557278427
香瓜BLE之Android群:541462902
香瓜单片机之STM8/STM32群:164311667香瓜单片机之Linux群:512598061
香瓜单片机之职场交流群:450154342
甜甜的大香瓜的小店(淘宝店):/?spm=2013.1.1000126.d21.hd2o8i
四、 实验前提 1、在进行本文步骤前,请先 阅读 以下博文: 暂无
2、在进行本文步骤前,请先 实现以下博文:
1)《CC2640之添加自定义服务》:
五、基础知识
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-59uint8_t minutes; // 0-59uint8_t hour; // 0-23uint8_t day; // 0-30uint8_t month; // 0-11uint16_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
//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
//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
//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
//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
//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
//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) { //char1case 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, ¬ify_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, ¬ify_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分钟,实验结果基本正确。
香瓜未做更为精确的测试去计算误差,大家自行测试吧。 至此,实验结束。
发布者:admin,转转请注明出处:http://www.yc00.com/news/1710054316a1692522.html
评论列表(0条)