
simpleBLEBroadcaster.c
// GAP - Advertisement data (max size = 31 bytes, though this is
// best kept short to conserve power while advertisting)
static uint8 advertData[] =
{
// Flags; this sets the device to use limited discoverable
// mode (advertises for 30 seconds at a time) instead of general
// discoverable mode (advertises indefinitely)
0x02, // length of this data
GAP_ADTYPE_FLAGS,
GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,
// three-byte broadcast of the data "1 2 3"
0x04, // length of this data including the data type byte
GAP_ADTYPE_MANUFACTURER_SPECIFIC, // manufacturer specific advertisement data type
1,
2,
3
};
修改下面关键字
E2C56DB5-DFFB-48D2-B060-D0F5A71096E01 (0x0001)1 (0x0001)-59 (0xc5)// GAP - Advertisement data (max size = 31 bytes, though this is
// best kept short to conserve power while advertisting)
static uint8 advertData[] =
{
// 25 byte ibeacon advertising data
// Preamble: 0x4c000215
// UUID: E2C56DB5-DFFB-48D2-B060-D0F5A71096E0
// Major: 1 (0x0001)
// Minor: 1 (0x0001)
// Measured Power: -59 (0xc5)
0x1A, // length of this data including the data type byte
GAP_ADTYPE_MANUFACTURER_SPECIFIC, // manufacturer specific advertisement data type
0x4c,
0x00,
0x02,
0x15,
0xe2,
0xc5,
0x6d,
0xb5,
0xdf,
0xfb,
0x48,
0xd2,
0xb0,
0x60,
0xd0,
0xf5,
0xa7,
0x10,
0x96,
0xe0,
0x00,
0x01,
0x00,
0x01,
0xc5
};
接下来修改广播类型,将下面代码
//uint8 advType = GAP_ADTYPE_ADV_NONCONN_IND;// use non-connectable advertisements uint8 advType = GAP_ADTYPE_ADV_DISCOVER_IND; // use scannable unidirected advertisements
修改为
uint8 advType = GAP_ADTYPE_ADV_NONCONN_IND; // use non-connectable advertisements //uint8 advType = GAP_ADTYPE_ADV_DISCOVER_IND; // use scannable unidirected advertisements
接下来修改 GAP
// Set the GAP Role Parameters GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &initial_advertising_enable ); GAPRole_SetParameter( GAPROLE_ADVERT_OFF_TIME, sizeof( uint16 ), &gapRole_AdvertOffTime ); GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof ( scanRspData ), scanRspData ); GAPRole_SetParameter( GAPROLE_ADVERT_DATA, sizeof( advertData ), advertData ); GAPRole_SetParameter( GAPROLE_ADV_EVENT_TYPE, sizeof( uint8 ), &advType );
因为 iBeacon 必须不间断广播,并且不响应任何数据请求,所以我们要修改 GAPROLE_ADVERT_OFF_TIME 和 GAPROLE_SCAN_RSP_DATA。
// Set the GAP Role Parameters GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &initial_advertising_enable ); //GAPRole_SetParameter( GAPROLE_ADVERT_OFF_TIME, sizeof( uint16 ), &gapRole_AdvertOffTime ); //GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof ( scanRspData ), scanRspData ); GAPRole_SetParameter( GAPROLE_ADVERT_DATA, sizeof( advertData ), advertData ); GAPRole_SetParameter( GAPROLE_ADV_EVENT_TYPE, sizeof( uint8 ), &advType );
保存工程后,进行编译,并通过 CCDebugger 下载程序到开发板中。
1.iBeacon的前世今生
![]()
苹果公司,其产品的开发对外历来都是神秘的,正当三星和诺基亚大力推进NFC应用的时候,苹果却没有跟进,这是为何?在WWDC2013上,苹果发布了全新颠覆性的iOS系统:iOS 7。除了全新的扁平化外观UI设计之外,苹果还发布了许多iOS7的新特性。作为iOS7中最重要的新特性之一,iBeacon引起了各大科技巨头的注意。
美国老牌商场梅西百货(Macy)已经开始在纽约和旧金山的门店中部署iBeacon传感器,在同应用程序 Shopkick配合使用后,顾客将会在进店的同时感受到新技术所带来的便捷,因为他们可以在不同楼层的不同商铺即时获取到不同的优惠信息。此外,苹果上周也宣布在全美254家苹果零售店中部署iBeacon技术。
在国内, 各种 iBeacon应用正如雨后春笋一样冒出来,相信,这一次,我们电子工程师大有作为。
1.1 iBeacon的技术原理
通过使用低功耗蓝牙技术(BluetoothLowEnergy,也就是通常所说的Bluetooth4.0或者Bluetooth Smart),iBeacon基站可以创建一个信号区域,当设备进入该区域时,相应的应用程序便会提示用户是否需要接入这个信号网络。通过能够放置在任何物体中的小型无线传感器和低功耗蓝牙技术,用户便能使用iPhone来传输数据。
2.iBeacon的应用方向
综合了一下,iBeacon的应用目前主要有如下:
【1】, 零售业, 当客户进入 iBeacon信号区域是推送相关信息
【2】, 球馆和演唱会馆等,指引客户找到座位和出入口洗手间等
【3】, 车库汽车定位,当你走进车库, iBeacon会指引你找到你的爱车再也不用到处找了。
【4】, 学生上课点名,别笑哦,一款名为BeHere的基于iBeacon 的应用 已经在AppStore 免费上架,iPad、iPhone和 iPod touch 都可以下载使用,该应用还具有“求助”功能,要是我当年上学的时候学校用这个来点名那我当年要睡少很多懒觉哦。
【5】,苹果将用iBeacon实现短距离支付,替换NFC,只是不知鹿死谁手短期肩部了分晓哦。
【6】,............
3.需要的开发环境
3.1硬件环境
【1】SmartRF开发板一套
【2】cc debugger 或smartRF04eb仿真器
【3】 cc2540 usb dongle 协议分析仪或 用 cc debugger 或 smartRF04eb 仿真器加
SmartRF开发板 实现的分析仪。(可选,但非常必要选)
3.2软件环境
【1】SmartRF FlashProgrammer 下载工具软件(可选)
【2】IAR8.10.3
【3】Texas Instruments PacketSniffer BLE协议分析仪
4.实战实践
iBeacon 基站的实现, 实际上除了硬件以外,在软件上仅表现为周期性地发送特定的数据包, 而这个数据包的格式,可以通过网络抓包破解分析出来。
对于一个UUID是E2C56DB5-DFFB-48D2-B060-D0F5A71096E0,major是0,minjor是0
的iBeacon,此时的Tx的信号是-59RSSI,他的BLE的广播包如下:
d6 be 89 8e 40 24 05 a2 17 6e 3d 71 02 01 1a 1a ff 4c 00 02 15 e2 c5 6d b5 df fb 48 d2 b0 60 d0
f5 a7 10 96 e0 00 00 00 00 c5 52 ab 8d 38a5
以上协议包拆解内容如下:
d6 be 89 8e # Access address for advertising data (this is always the same fixedvalue)
40 # Advertising Channel PDU Header byte0. Contains: (type = 0), (tx add = 1), (rx add =0)
24 # Advertising Channel PDU Header byte 1. Contains: (length = total bytes of the advertising payload + 6 bytes for the BLE macaddress.)
05 a2 17 6e 3d 71 # Bluetooth Mac address (note this is a spoofedaddress)
02 01 1a 1a ff 4c 00 02 15 e2 c5 6d b5 df fb 48 d2 b0 60 d0 f5 a7 10 96 e0 00 00 00 00 c5#Bluetoothadvertisement
52 ab 8d 38 a5 #checksum
协议包中的关键部分就是蓝牙的广播部分,这些被分解为如下:
02 01 1a 1a ff 4c 00 0215 # Apple's fixed iBeacon advertisingprefix
e2 c5 6d b5 df fb 48 d2 b0 60 d0 f5 a7 10 96 e0 # iBeacon profileuuid
00 00 #major
00 00 #minor
c5 # The 2's complement of the calibrated TxPower
通过BLE设备发送这样的数据包,iOS收到后,即可实现iBeacon了。
4.1源码修改
好通过前面的协议分析,我们来修改一下源码,我们在《1.BLE入门与提高教程.pdf》的第 4 章 BLE 协议栈入门 里边已经验证过 SimpleBLEPeripheral作为从机时的功能,现在我们直接在这个TI官方的例程上修改来实现我们的iBeacon基站。
【1】修改广播数据:
![]()
4.2 用 iOS测试
笔者手机上装了很多Appstore上的蓝牙4.0BLE的软件,其中AirLocate是苹果公司推出iBeacon 的测试软件, Locate iBeacons 是一款第三方的软件, 能实现iBeacon的距离定位和校准, 下面我们来看看 Locate iBeacons 实现的距离显示和室内定位。
【1】, 手机上安装Locate iBeacons, 你的 iphone至少是4s 或以上, 系统必须是ios7.0
以上, iphone4s ios7.0 以后的系统才支持蓝牙4.0BLE。
![]()
【2】, 点击Locate iB 进去后如下图,
![]()
【3】, 点击 Locate iBeacons 进入如下界面,如果你的基站已经打开,即可看到如图所示的设备, 下图中 就直接显示了你的手机与 iBeacon 基站间的距离,这个距离可能随着不同的硬件设备而有所差异, 所以需要校准, 请看下一步如何校准。这里为什么一打开这个软件就实现了距离显示了呢,主要是该软件内默认添加了苹果公司发布的UUID,我们亦可以修改基站的uuid,然后在该软件中添加该uuid,同样也能实现该功能的,这个做起来就要深入开发了。
![]()
【4】,校准, 点击第一行 ,进入下一步。
![]()
【5】,校准提示,把你的iphone放到距离iBeacon基站约1米处,按下Calibrate ,并且保持30秒到1分钟,过程如下面图。
![]()
![]()
【6】, 校准完毕, 下面图显示聚焦校准完毕了, 你可以随意拿你的 iphone到处走,神奇的iBeacon就告诉你你所处的距离,如果有3个以上的iBeacon基站信号能够被收到,那么就可以实现比较真正的室内定位了。
![]()
【7】,显示距离如下。
![]()
4.3数据分析
好吧, 上述的iBeacon功能基本完成了,那么, 到底SmartRF开发板与iOS的数据交互如何的呢,这个时候就需要网络协议分析仪来抓包并分析数据了。
simpleBLEBroadcaster.c
// GAP - Advertisement data (max size = 31 bytes, though this is
// best kept short to conserve power while advertisting)
static uint8 advertData[] =
{
// Flags; this sets the device to use limited discoverable
// mode (advertises for 30 seconds at a time) instead of general
// discoverable mode (advertises indefinitely)
0x02, // length of this data
GAP_ADTYPE_FLAGS,
GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,
// three-byte broadcast of the data "1 2 3"
0x04, // length of this data including the data type byte
GAP_ADTYPE_MANUFACTURER_SPECIFIC, // manufacturer specific advertisement data type
1,
2,
3
};
修改下面关键字
E2C56DB5-DFFB-48D2-B060-D0F5A71096E01 (0x0001)1 (0x0001)-59 (0xc5)// GAP - Advertisement data (max size = 31 bytes, though this is
// best kept short to conserve power while advertisting)
static uint8 advertData[] =
{
// 25 byte ibeacon advertising data
// Preamble: 0x4c000215
// UUID: E2C56DB5-DFFB-48D2-B060-D0F5A71096E0
// Major: 1 (0x0001)
// Minor: 1 (0x0001)
// Measured Power: -59 (0xc5)
0x1A, // length of this data including the data type byte
GAP_ADTYPE_MANUFACTURER_SPECIFIC, // manufacturer specific advertisement data type
0x4c,
0x00,
0x02,
0x15,
0xe2,
0xc5,
0x6d,
0xb5,
0xdf,
0xfb,
0x48,
0xd2,
0xb0,
0x60,
0xd0,
0xf5,
0xa7,
0x10,
0x96,
0xe0,
0x00,
0x01,
0x00,
0x01,
0xc5
};
接下来修改广播类型,将下面代码
//uint8 advType = GAP_ADTYPE_ADV_NONCONN_IND;// use non-connectable advertisements uint8 advType = GAP_ADTYPE_ADV_DISCOVER_IND; // use scannable unidirected advertisements
修改为
uint8 advType = GAP_ADTYPE_ADV_NONCONN_IND; // use non-connectable advertisements //uint8 advType = GAP_ADTYPE_ADV_DISCOVER_IND; // use scannable unidirected advertisements
接下来修改 GAP
// Set the GAP Role Parameters GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &initial_advertising_enable ); GAPRole_SetParameter( GAPROLE_ADVERT_OFF_TIME, sizeof( uint16 ), &gapRole_AdvertOffTime ); GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof ( scanRspData ), scanRspData ); GAPRole_SetParameter( GAPROLE_ADVERT_DATA, sizeof( advertData ), advertData ); GAPRole_SetParameter( GAPROLE_ADV_EVENT_TYPE, sizeof( uint8 ), &advType );
因为 iBeacon 必须不间断广播,并且不响应任何数据请求,所以我们要修改 GAPROLE_ADVERT_OFF_TIME 和 GAPROLE_SCAN_RSP_DATA。
// Set the GAP Role Parameters GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &initial_advertising_enable ); //GAPRole_SetParameter( GAPROLE_ADVERT_OFF_TIME, sizeof( uint16 ), &gapRole_AdvertOffTime ); //GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof ( scanRspData ), scanRspData ); GAPRole_SetParameter( GAPROLE_ADVERT_DATA, sizeof( advertData ), advertData ); GAPRole_SetParameter( GAPROLE_ADV_EVENT_TYPE, sizeof( uint8 ), &advType );
保存工程后,进行编译,并通过 CCDebugger 下载程序到开发板中。
Self-portrait,anti-lost,anti-theft,voice recording device:
Product
Itag is a kind of bluetooth 4.0 low energy products which works through a Itracing App.Itag can chain user's easy-lost & valuable belongs together and works with smart phone to prevent lost.
Itag is also a remote control of your smart phone camera for self-portrait.
Itag can also provide a last seen pin-drop on map to help you recover your items and search your cars in parking site.
Specification:
Bluetooth version:Bluetooth 4.0 low energy consumption
Compatible device:iphone 4S/5/5S/5C/6/6Plus/6C, Ipad Mini, Itouch5,Ipad 3/4 adn android system,Bluetooth 4.0 smart phone(Android 4.3 version and upgrade version)
Working distance:<10 m(outdoor environment)
Battery:CR2032 Lithium Coin Battery,Last about half a year.
Package
User Manual

UUID,就是用来唯一识别一个特征值的ID.
handle,就是对应的attribute的一个句柄。
所有对特征值的操作,都是通过对UUID的搜索得到对应的handle之后,通过handle来操作特征值的。
添加新的特征值CHAR6
下面对主要几个文件进行修改
simpleGATTprofile.h文件添加以下定义
#define SIMPLEPROFILE_CHAR6
#define SIMPLEPROFILE_CHAR6_UUID
#define SIMPLEPROFILE_CHAR6_LEN
SIMPLEPROFILE_CHAR6

在simpleGATTprofile.c
1、
// Characteristic 6 UUID: 0xFFF6
CONST uint8 simpleProfilechar6UUID[ATT_BT_UUID_SIZE] =
{
LO_UINT16(SIMPLEPROFILE_CHAR6_UUID),
HI_UINT16(SIMPLEPROFILE_CHAR6_UUID) };
/**************#define HI_UINT16(a)
/**************#define LO_UINT16(a)

2、
// Simple Profile Characteristic 6 Properties
static
// Characteristic 6 Value
static uint8simpleProfileChar6[SIMPLEPROFILE_CHAR6_LEN] = { 0, 0, 0, 0, 0 };
// Simple Profile Characteristic 6 User Description
static uint8 simpleProfileChar6UserDe

3、
static gattAttribute_t simpleProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED]
这里要把数组改为
#define SERVAPP_NUM_ATTR_SUPPORTED
simpleProfileAttrTbl表中,可读可写属性都是3个数组,只有char4的通知是4组,多了个// Characteristic 4 configuration

并把CHAR6添加进去
// Characteristic Value 6

能列出来了但是 点进去会报错,还没设置读写参数simpleProfile_WriteAttrCB,
simpleProfile_ReadAttrCB
4、设置参数函数
bStatus_t SimpleProfile_SetParameter( uint8 param, uint8 len, void *value )中:
//即修改SimpleProfile_SetParameter();函数

添加以下代码:
case SIMPLEPROFILE_CHAR6:

4、
在bStatus_tSimpleProfile_GetParameter( uint8 param, void *value )中添加:
case
break;
//读取simpleProfileChar6的值放到*value中,char1是单个字节读取,为
*((uint8*)value) = simpleProfileChar1;

·
·
每当GATT层有数据发过来的时候,会调用simpleProfile_WriteAttrCB,
每当GATT层收到对方读取数据请求的时候,会调用simpleProfile_ReadAttrCB
这两个函数包含在gattServiceCBs_t类型的结构体里CONST gattServiceCBs_t simpleProfileCBs,
读simpleProfile_ReadAttrCB
这个设置后就能在lightblue里读出值,值为
simpleProfileChar6[SIMPLEPROFILE_CHAR6_LEN]={数组的数值(16进制显示)}
写simpleProfile_WriteAttrCB
读取被写进去的值
)
在static uint8 simpleProfile_ReadAttrCB( uint16 connHandle,
添加

添加单字节char7要在接char1或3后面,不能加break

在simpleProfile_WriteAttrCB()中添加(添加后发送过去就不会提示出错了)
(下面没用到)osal_memset为字符串集体赋同一数值
void
{
Return
}
if ( status == SUCCESS )
uint8 *pCurValue = (uint8 *)pAttr->pValue;
osal_memset(pCurValue, 0, SIMPLEPROFILE_CHAR6_LEN );
VOID osal_memcpy(pCurValue, pValue, SIMPLEPROFILE_CHAR6_LEN );

7 .在simpleBLEperipheral.c添加初始化值
在void SimpleBLEPeripheral_Init( uint8 task_id )函数中初始化参数

现在可以在手机设备中读取CHAR6的值为0x0102030405;
向char6写进0x3344556677
General Electrical Specification
Absolute Maximum Ratings:
| Ratings | Min. | Max. |
| Storage Temperature | -40 ℃ | +85 ℃ |
| Supply Voltage (VCHG) | -0.4V | 5.75V |
| Supply Voltage (VREG_ENABLE,VBAT_SENSE) | -0.4V | 4.2V |
| Supply Voltage (LED[2:0]) | -0.4V | 4.4V |
| Supply Voltage (PIO_POWER) | -0.4V | 3.6V |
Recommended Operating Condition:
| Operating Temperature range | -20 ℃ | +75 ℃ |
| Supply Voltage (VBAT) | 2.7V | 4.25V |
| Supply Voltage (VCHG) | 4.75V / 3.10 V | 5.25V |
| Supply Voltage (VREG_ENABLE,VBAT_SENSE) | 0V | 4.2V |
| Supply Voltage (LED[2:0]) | 1.10V | 4.25V |
| Supply Voltage (PIO_POWER)* | 1.7V | 3.6V |
1.8V Switch-mode Regulator :