网上商城怎么开发/霸榜seo
本篇博文最后修改时间:2016年12月12日,10:51。
一、简介
本文以SimpleBLEPeripheral工程为例,介绍如何在一个可读、可写、可通知、20字节长的特征值char6基础上,添加一个香瓜自定义的通信协议,并用app发送指令实现P11口上的LED点灯。
二、实验平台
协议栈版本:BLE-CC254x-1.4.0
编译软件: IAR 8.20.2
硬件平台: Smart RF开发板(主芯片CC2541)
手机型号: 小米4S
安卓版本:安卓5.1
安卓app:TruthBlue
三、版权声明
博主:甜甜的大香瓜
声明:喝水不忘挖井人,转载请注明出处。
原文地址:http://blog.csdn.NET/feilusia
联系方式:897503845@qq.com
香瓜BLE之CC2541群:127442605
香瓜BLE之CC2640群:557278427
五、基础知识
1、通信协议是什么?
答:通信协议是通信双方的通信规范,有被广泛使用如Modbus协议。
本文使用香瓜项目中最常用的一套自定义通信协议。
2、为什么要通信协议?
答:如果通信双方没有制定通信协议,会导致香瓜从CC2541端发送一个0x38数据给app端,app端不清楚这个数据是表示电机转动、还是温度值、还是电量值、又或是在骂人……
因此通信过程中的数据含义需要在开发之前定义下来,也就是要定义通信协议。
3、本文使用的通信协议是如何的?
答:
简单来说,就是通信过程采取20字节为一包的通信数据包,如果实际数值不满20字节,需要填充补齐上0xFF至20字节。
通信协议规定了指令集一共有两条:开关灯指令、应答错误指令。
4、本文中APP端需发送的指令集
答:
香瓜的测试指令1、功能码0x00(开关灯)
1)关灯
fe010000ffffffffffffffffffffffffffffffff2)开灯
fe01000100ffffffffffffffffffffffffffffff
一共两条指令:关灯、开灯。
可自行对照上面的通信协议加强理解该指令。
六、实验步骤
1、编写并添加自定义的通信协议驱动
1)写一个通信协议驱动GUA_RF_Communication.c(存放在“……\BLE-CC254x-1.4.0\Projects\ble\SimpleBLEPeripheral\Source\GUA”路径下)
//******************************************************************************
//name: GUA_RF_Communication.c
//introduce: 香瓜的通信协议
//author: 甜甜的大香瓜
//email: 897503845@qq.com
//QQ group 香瓜BLE之CC2541(127442605)
//changetime: 2016.12.08
//******************************************************************************
#include "GUA_RF_Communication.h"
#include <string.h>/*********************宏定义************************/
//通信协议的功能码
#define FUNC_GUA_LED_ON_OFF 0x00 //led开关的功能码//应用层事件(从应用层复制过来)
#define SBP_START_DEVICE_EVT 0x0001
#define SBP_PERIODIC_EVT 0x0002
#define SBP_GUA_RF_COMMUNICAION_PROCESS_EVT 0x0004 //通信处理事件
#define SBP_GUA_RF_COMMUNICAION_COMMAND_ERR_EVT 0x0008 //通信数据出错事件#define SBP_GUA_LED_ON_OFF_EVT 0x0040 //led开关事件//通信协议的数据包长度
#define GUA_DATA_PACKAGE_LEN 20 //20字节一包//******************************************************************************
//name: GUA_RF_Communication_Judgment
//introduce: RF的通信数据判断
//parameter: npGUA_Receive: 接收缓冲区首地址
//return: true: 数据包正确
// false: 数据包错误
//author: 甜甜的大香瓜
//email: 897503845@qq.com
//QQ group 香瓜BLE之CC2541(127442605)
//changetime: 2016.12.08
//******************************************************************************
GUA_U8 GUA_RF_Communication_Judgment(GUA_U8 *npGUA_Receive)
{GUA_U8 nGUA_Sof = *npGUA_Receive;GUA_U8 nGUA_Len = *(npGUA_Receive + 1);GUA_U8 nGUA_Func = *(npGUA_Receive + 2); GUA_U8 *npGUA_Data = npGUA_Receive + 3;GUA_U8 nGUA_Crc = *(npGUA_Receive + 3 + nGUA_Len);GUA_U8 nGUA_Crc_Count = 0; //判断起始位正确性if(nGUA_Sof != 0xFE){return GUA_RF_COMMUNICATION_JUDGMENT_FALSE; } //接收数据长度if(nGUA_Len > 16){return GUA_RF_COMMUNICATION_JUDGMENT_FALSE; } //计算校验和nGUA_Crc_Count += nGUA_Sof; nGUA_Crc_Count += nGUA_Len; nGUA_Crc_Count += nGUA_Func;while(nGUA_Len--){nGUA_Crc_Count += *(npGUA_Data + nGUA_Len);}//比较校验和if(nGUA_Crc != nGUA_Crc_Count) {return GUA_RF_COMMUNICATION_JUDGMENT_FALSE; } //数据包正确return GUA_RF_COMMUNICATION_JUDGMENT_TRUE;
}extern void GUA_SimpleGATTprofile_Char6_Notify(GUA_U16 nGUA_ConnHandle, GUA_U8 *npGUA_Value, GUA_U8 nGUA_Len);
//******************************************************************************
//name: GUA_RF_Communication_DataPackage_Send
//introduce: RF的通信数据打包并发送(包头+有效数据长度+功能码+有效数据+补齐字节)
//parameter: nGUA_Func: 功能码
// npGUA_ValidData: 有效数据首地址
// nGUA_ValidData_Len: 要发送的数据长度
//return: none
//author: 甜甜的大香瓜
//email: 897503845@qq.com
//QQ group 香瓜BLE之CC2541(127442605)
//changetime: 2016.12.08
//******************************************************************************
void GUA_RF_Communication_DataPackage_Send(GUA_U16 nGUA_ConnHandle, GUA_U8 nGUA_Func, GUA_U8 *npGUA_ValidData, GUA_U8 nGUA_ValidData_Len)
{GUA_U8 nbGUA_DataPackage_Data[GUA_DATA_PACKAGE_LEN]; GUA_U8 nGUA_Num;//初始化发送缓冲区memset(nbGUA_DataPackage_Data, 0xFF, 20); //填充数据nbGUA_DataPackage_Data[0] = 0xFE; //包头nbGUA_DataPackage_Data[1] = nGUA_ValidData_Len; //有效数据长度 nbGUA_DataPackage_Data[2] = nGUA_Func; //功能码memcpy(nbGUA_DataPackage_Data + 3, npGUA_ValidData, nGUA_ValidData_Len); //有效数据nbGUA_DataPackage_Data[3 + nGUA_ValidData_Len] = 0; //校验和清零 for(nGUA_Num = 0; nGUA_Num < (3 + nGUA_ValidData_Len); nGUA_Num++){nbGUA_DataPackage_Data[3 + nGUA_ValidData_Len] += nbGUA_DataPackage_Data[nGUA_Num]; //校验和累加 } //发送数据 GUA_SimpleGATTprofile_Char6_Notify(nGUA_ConnHandle, nbGUA_DataPackage_Data, GUA_DATA_PACKAGE_LEN);
}//******************************************************************************
//name: GUA_RF_Communication_Process
//introduce: RF的通信数据处理
//parameter: npGUA_Receive: 接收缓冲区首地址
// nGUA_Event: 要启动的事件
//return: none
//author: 甜甜的大香瓜
//email: 897503845@qq.com
//QQ group 香瓜BLE之CC2541(127442605)
//changetime: 2016.12.08
//******************************************************************************
void GUA_RF_Communication_Process(GUA_U8 *npGUA_Receive, GUA_U16 *npGUA_Event)
{GUA_U8 nGUA_Func = *(npGUA_Receive + 2);//判断功能码switch(nGUA_Func){ //led开关的功能码case FUNC_GUA_LED_ON_OFF:{*npGUA_Event = SBP_GUA_LED_ON_OFF_EVT;break; }//功能码无效default:{*npGUA_Event = SBP_GUA_RF_COMMUNICAION_COMMAND_ERR_EVT;break; } }
}
注意本文件的事件要从应用层复制过来,保证事件是一样的。
2)写一个通信协议驱动的头文件 GUA_RF_Communication.h (存放在“……\BLE-CC254x-1.4.0\Projects\ble\SimpleBLEPeripheral\Source\GUA”路径下)
//******************************************************************************
//name: GUA_RF_Communication.h
//introduce: 香瓜的通信协议的头文件
//author: 甜甜的大香瓜
//email: 897503845@qq.com
//QQ group 香瓜BLE之CC2541(127442605)
//changetime: 2016.12.08
//******************************************************************************
#ifndef _GUA_RF_COMMUNICATION_H_
#define _GUA_RF_COMMUNICATION_H_/*********************宏定义************************/
#ifndef GUA_U8
typedef unsigned char GUA_U8;
#endif #ifndef GUA_U16
typedef unsigned short GUA_U16;
#endif #ifndef GUA_U32
typedef unsigned long GUA_U32;
#endif #define GUA_RF_COMMUNICATION_JUDGMENT_FALSE 0
#define GUA_RF_COMMUNICATION_JUDGMENT_TRUE 1/*********************外部函数声明************************/
extern GUA_U8 GUA_RF_Communication_Judgment(GUA_U8 *npGUA_Receive);
extern void GUA_RF_Communication_DataPackage_Send(GUA_U16 nGUA_ConnHandle, GUA_U8 nGUA_Func, GUA_U8 *npGUA_ValidData, GUA_U8 nGUA_ValidData_Len);
extern void GUA_RF_Communication_Process(GUA_U8 *npGUA_Receive, unsigned short *npGUA_Event);#endif
3)工程中添加GUA_RF_Communication.c
4)在IAR设置中添加按键驱动源文件路径
$PROJ_DIR$\..\..\SimpleBLEPeripheral\Source\GUA
2、应用层中调用
1)添加通信协议驱动头文件(SimpleBLEPeripheral.c中)
#include "GUA_RF_Communication.h"
2)修改应用层的simple服务的回调函数(SimpleBLEPeripheral.c中)
//******************************************************************************
//name: simpleProfileChangeCB
//introduce: simple服务的回调函数
//parameter: paramID: 特征值ID
//return: none
//author: 甜甜的大香瓜
//email: 897503845@qq.com
//QQ group 香瓜BLE之CC2541(127442605)
//changetime: 2016.12.08
//******************************************************************************
static void simpleProfileChangeCB( uint8 paramID )
{//通过特征值ID来分发特征值处理switch( paramID ){//char6的处理case SIMPLEPROFILE_CHAR6: {//启动RF通信处理事件osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_GUA_RF_COMMUNICAION_PROCESS_EVT, 0 ); break; } default:break;}
}
3)添加“ 通信处理事件 、通信数据出错事件、led开关事件 ”
①定义“通信处理事件、通信数据出错事件、led开关事件”(SimpleBLEPeripheral.c中)
//通信处理事件if(events & SBP_GUA_RF_COMMUNICAION_PROCESS_EVT){uint16 nGUA_Event;uint8 nGUA_Ret; uint8 nbGUA_Char6[SIMPLEPROFILE_CHAR6_LEN] = {0}; //读取特征值6的数值SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR6, nbGUA_Char6);//判断接收到的RF值是否正确nGUA_Ret = GUA_RF_Communication_Judgment(nbGUA_Char6); //数据正确,则执行对应事件if(nGUA_Ret == GUA_RF_COMMUNICATION_JUDGMENT_TRUE){//根据功能码判断该执行什么事件GUA_RF_Communication_Process(nbGUA_Char6, &nGUA_Event); //定时器执行对应的功能事件osal_start_timerEx(simpleBLEPeripheral_TaskID, nGUA_Event, 0); }//数据不正确,则反馈报错 else{//定时器执行RF通信数据出错事件osal_start_timerEx(simpleBLEPeripheral_TaskID, SBP_GUA_RF_COMMUNICAION_COMMAND_ERR_EVT, 0); }return (events ^ SBP_GUA_RF_COMMUNICAION_PROCESS_EVT);}//通信数据出错事件if (events & SBP_GUA_RF_COMMUNICAION_COMMAND_ERR_EVT){ uint16 nGUA_ConnHandle; uint8 nGUA_Func; uint8 nbGUA_ValidData[16]; uint8 nGUA_ValidData_Len;//获得连接句柄GAPRole_GetParameter(GAPROLE_CONNHANDLE, &nGUA_ConnHandle);//功能码填充 nGUA_Func = 0x80; //有效数据填充//nbGUA_ValidData[0] = 0;//有效数据的长度nGUA_ValidData_Len = 0;//发送数据 GUA_RF_Communication_DataPackage_Send(nGUA_ConnHandle, nGUA_Func, nbGUA_ValidData, nGUA_ValidData_Len); return (events ^ SBP_GUA_RF_COMMUNICAION_COMMAND_ERR_EVT);} //功能码00 led开关事件if ( events & SBP_GUA_LED_ON_OFF_EVT ){uint16 nGUA_ConnHandle; uint8 nGUA_Func; uint8 nbGUA_ValidData[16]; uint8 nGUA_ValidData_Len;uint8 nbGUA_Char6[SIMPLEPROFILE_CHAR6_LEN] = {0}; /*****************处理指令************************///读出RF接收到的数据到缓冲区SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR6, nbGUA_Char6);//如果为0则关灯switch(nbGUA_Char6[3]){//关灯case 0x00:{P1_1 = 0; //拉低P11 P1SEL &= ~(1 << 1); //设置P11为IO口 P1DIR |= (1 << 1); //设置P11为输出 break;}//开灯case 0x01:{P1_1 = 1; //拉高P11 P1SEL &= ~(1 << 1); //设置P11为IO口 P1DIR |= (1 << 1); //设置P11为输出 break;}//其它default:break;}/*****************应答************************///获得连接句柄GAPRole_GetParameter(GAPROLE_CONNHANDLE, &nGUA_ConnHandle);//功能码填充 nGUA_Func = 0x00; //有效数据填充//nbGUA_ValidData[0] = 0;//有效数据的长度nGUA_ValidData_Len = 0;//发送数据 GUA_RF_Communication_DataPackage_Send(nGUA_ConnHandle, nGUA_Func, nbGUA_ValidData, nGUA_ValidData_Len); return (events ^ SBP_GUA_LED_ON_OFF_EVT);}
②定义“通信处理事件、通信数据出错事件、led开关事件”的宏 (替换SimpleBLEPeripheral.h中原来的事件宏)
// Simple BLE Peripheral Task Events
#define SBP_START_DEVICE_EVT 0x0001
#define SBP_PERIODIC_EVT 0x0002
#define SBP_GUA_RF_COMMUNICAION_PROCESS_EVT 0x0004 //通信处理事件
#define SBP_GUA_RF_COMMUNICAION_COMMAND_ERR_EVT 0x0008 //通信数据出错事件#define SBP_GUA_LED_ON_OFF_EVT 0x0040 //led开关事件
七、实验结果
仿真并全速运行,手机端使用truthblue连接并使用char6通道进行通信控制。
1、通信指令收发如下图
红框为开灯与开灯应答,蓝框为关灯与关灯应答,紫框为错误指令与报错应答。
2、开发板现象
1)发送关灯指令时
2)发送开灯指令时
实现了指令控制led的亮灭。
因此,实验成功。