UUID, 就是用来唯一识别一个特征值的ID.
handle,就是对应的attribute 的一个句柄。
所有对特征值的操作,都是通过对UUID 的搜索得到对应的handle之后,通过handle来操作特征值的。
添加新的特征值
CHAR6
下面对主要几个文件进行修改
simpleGATTprofile.h 文件添加以下定义
#define SIMPLEPROFILE_CHAR6 5
#define SIMPLEPROFILE_CHAR6_UUID 0xFFF6
#define SIMPLEPROFILE_CHAR6_LEN 5 (单字节没这句)
SIMPLEPROFILE_CHAR6 全大写 case 参数用到 如 case SIMPLEPROFILE_CHAR6:
在simpleGATTprofile.c
1、 添加特征值UUID
// 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) (((a) >> 8) & 0xFF)*******
/**************#define LO_UINT16(a) ((a) & 0xFF)*******
2、 设置属性
// Simple Profile Characteristic 6 Properties 可读可写 (声明而已,只是能让lightblue在列表中显示为可读可写或通知,真正要改在属性表那里改。Props= Properties,Desp =Description,)
static uint8 simpleProfileChar6Props = GATT_PROP_READ | GATT_PROP_WRITE;
// Characteristic 6 Value // simpleProfileChar6是个5位数组,接收数据后存在这
static uint8 simpleProfileChar6[SIMPLEPROFILE_CHAR6_LEN] = { 0, 0, 0, 0, 0 };
// Simple Profile Characteristic 6 User Description
static uint8 simpleProfileChar6UserDesp[17] = "Characteristic 6\0";
3、 属性表 (Profile Attributes - Table)最重要,添加了这个才会在lightblue中列表出来
static gattAttribute_t simpleProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED]
这里要把数组改为
#define SERVAPP_NUM_ATTR_SUPPORTED 20 原来是17
(//添加了3组结构体数组 CHAR6)
simpleProfileAttrTbl表中,可读可写属性都是3个数组,只有char4的通知是4组,多了个// Characteristic 4 configuration
并把 CHAR6 添加进去
// Characteristic 6 Declaration (声明,没加这个lightblue属性表找不到)
{ ATT_BT_UUID_SIZE, characterUUID },
GATT_PERMIT_READ,
&simpleProfileChar6Props
// Characteristic Value 6 (特征值)!!!
{ ATT_BT_UUID_SIZE, simpleProfilechar6UUID },
GATT_PERMIT_READ | GATT_PERMIT_WRITE, //设置可读可写
simpleProfileChar6 //由于值是5位数组,不用&,一个字节就用
// Characteristic 6 User Description //描述
{ ATT_BT_UUID_SIZE, charUserDescUUID },
GATT_PERMIT_READ,
simpleProfileChar6UserDesp
能列出来了但是 点进去会报错,还没设置读写参数simpleProfile_WriteAttrCB, 和
simpleProfile_ReadAttrCB
4、设置参数函数 (SimpleProfile_SetParameter函数)
bStatus_t SimpleProfile_SetParameter( uint8 param, uint8 len, void *value )中:
// 即修改SimpleProfile_SetParameter();函数
添加以下代码:
case SIMPLEPROFILE_CHAR6:
if ( len == SIMPLEPROFILE_CHAR6_LEN ) //特征值赋值到数组
VOID osal_memcpy(simpleProfileChar6, value, SIMPLEPROFILE_CHAR6_LEN );
//把要改写的数据写到simpleProfileChar6数组来
ret = bleInvalidRange;
break;
4、 获取参数函数 {SimpleProfile_GetParameter(UUID,获取到的值)函数}
实际上就是把被新进的值simpleProfileChar6放进value数组
在bStatus_t SimpleProfile_GetParameter( uint8 param, void *value )中添加:
case SIMPLEPROFILE_CHAR6:
VOID osal_memcpy( value, simpleProfileChar6, SIMPLEPROFILE_CHAR6_LEN );
break;
//读取simpleProfileChar6的值放到*value 中,char1是单个字节读取,为
*((uint8*)value) = simpleProfileChar1;
· 6、读写特征值函数(2个回调函数
· 这个两个是注册到GATT层的回调函数, 在GATT初始化的时候注册的. 这部分代码封装在库里面.
每当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,
gattAttribute_t *pAttr,
uint8 *pValue,
uint8 *pLen,
uint16 offset,
uint8 maxLen )中:
添加 case SIMPLEPROFILE_CHAR6_UUID:
*pLen = SIMPLEPROFILE_CHAR6_LEN;
VOID osal_memcpy(pValue, pAttr->pValue, SIMPLEPROFILE_CHAR6_LEN );
break; //读:
pAttr->pValue
的内容复制到pValue
添加单字节char7要在接char1或3后面,不能加break
在simpleProfile_WriteAttrCB()中添加(添加后发送过去就不会提示出错了)
case SIMPLEPROFILE_CHAR6_UUID:
//Validate the value 检测输入数据是否合法
// Make sure it's not a blob oper
if ( offset == 0 ) //是第一字节
if ( len != SIMPLEPROFILE_CHAR6_LEN )
status = ATT_ERR_INVALID_VALUE_SIZE;
} //若输入长度不对,status为
status = ATT_ERR_ATTR_NOT_LONG;//不是第一字节
//Write the value 一开始定义了status == SUCCESS,若上述条件不符,不会运行到这里。
osal_memcpy
(目的A
,源地址B
,长度)复制B
内容到A
if ( status == SUCCESS )
VOID osal_memcpy( pAttr->pValue, pValue, SIMPLEPROFILE_CHAR6_LEN );
notifyApp = SIMPLEPROFILE_CHAR6;
} //写:
pValue
的内容复制到pAttr->pValue
(别弄反了)
break;
(下面没用到)osal_memset为字符串集体赋同一数值 return目的存储区地址
void *osal_memset(void *dest, uint8 value , intlen)
Return memset(dest,value,len);
if ( status == SUCCESS )
uint8 *pCurValue = (uint8 *)pAttr->pValue;
osal_memset(pCurValue, 0, SIMPLEPROFILE_CHAR6_LEN );
//为新数组pCurValue赋值N个0
VOID osal_memcpy(pCurValue, pValue, SIMPLEPROFILE_CHAR6_LEN );
//
复制
pValue
内容到新数组
pCurValue notifyApp = SIMPLEPROFILE_CHAR6;
break;
7 .在simpleBLEperipheral.c添加初始化值
在 void SimpleBLEPeripheral_Init( uint8 task_id )函数中初始化参数
现在可以在手机设备中读取CHAR6的值为0x0102030405;
向char6写进0x3344556677 再读取值已经改写为0x3344556677
这是一个非常基本的
蓝牙
低功耗(
BLE
)心率监测应用程序,它说明了Apple的CoreBluetooth的用法,并概述了CBCentralManager和CBPeripheral的用法。 为了测试该应用程序,可以通过模拟心率监测器使用非常方便的工具名称LightBlue。 用户界面非常准,因为这仅是出于演示目的。
注–需要在文件HeartRateDevice.swift中定义的结构HeartRateDevice上替换设备
uuid
。 确保结构中的其余属性具有适当的设备特定值。
该应用程序显示两个特征,即心率和放置传感器的位置。
什么是
蓝牙
蓝牙
,是一种支持设备短距离通信(一般10m内)的无线电技术,能在包括移动电话、PDA、无线耳机、笔记本电脑、相关外设等众多设备之间进行无线信息交换。利用“
蓝牙
”技术,能够有效地简化移动通信终端设备之间的通信,也能够成功地简化设备与因特网Internet之间的通信,从而使数据传输变得更加迅速高效,为无线通信拓宽道路。
简单说,
蓝牙
就是一种使用无线电通信的技术去完成设备与设备间通讯与数据交换。 而我们通常使用的那些
蓝牙
耳机、
蓝牙
打印机、
蓝牙
手环、
蓝牙
鼠标等等设备,都是基于
蓝牙
通信技术对外提供某种(或
这个配置或者说任务, 让这个
蓝牙
设备成为了一个简单的
BLE
外设.
这里定义了外设的广播数据, 以及最重要,
char
被改变之后的回调, 引出后来的coreHandler里面的, ack 以及写e2prom.
/*************************************************************************************...
最近用NRF52832
蓝牙
SOC做了一个车用测速的板子,由于目前还没有安卓编程的基础,做不了
蓝牙
控制APP,后来想到在学校的时候使用App inventor做了一个
蓝牙
APP来控制小车,想着这里也可以做来搞搞,没想到
蓝牙
一直连接报错507,查阅网上不少资料才知道,App inventor本身的
蓝牙
组件支持
蓝牙
2.0和3.0,但NRF52832是
蓝牙
5.0,所以没法用。那么需要安装
BLE
扩展组件,才能使用,而且我发现,除了
蓝牙
组件,还有其他的MQTT组件,这意味着我们可以自制APP通过WIFI控制
simpleBLEPeripheral
.c的第339行
uint8 pairMode =
GAPBOND_PAIRING_MODE_WAIT_FOR_REQ;//如果有配对请求或者安全性有要求那就配对(默认)
uint8 pairMode = GAPBOND_PAIRING_MODE_INITIATE;
//手机首次连接后需要配对
uint8 pairMode =
GAPBO
2.配对数据设置
3.Initialize GATT attributes (加服务)
4.Setup the SimpleProfile
Char
acteristic Values(设置特征值)
5.注册回调函数
6.设置事件
SimpleBLEPeripheral
_Init()
当main函数启动osal系统之后会跳到
simpleBLEPeripheral
.c中执行。
simpleBLEPeripheral
.c中一开始是一些宏定义,参数、数组、函数声明。
// How often to perform periodic event
#define SBP_PE
一、通过Simple
BLE
Central工程分析CC2541作为主机时是如何发现从机的服务和特征值的,以及读取特征值的具体过程
二、服务和特征值1、一个工程可以有多个服务,比如按键服务、心率计服务、温度计服务。(服务都是自己定义的,如
新
增的服务simpleprofile)2、一个服务可以有多个特征值,特征值是主从机传输数据的媒介,像运人渡河的小船3、如果主机要想获得按键服务的特征值,必须先发现按键...
上篇博客粗略讲了一下App Inventor的运用,现在来看看
蓝牙
连接的实现。
首先我们要导入一个
蓝牙
BLE
模块,点下面这个链接下载http://iot.appinventor.mit.edu/assets/resources/edu.mit.appinventor.
ble
.aix
之后看App Inventor组件面板最下方有一个Extension
点Import extension,之后选择文...
参考链接:
c2541
simpleBLEPeripheral
工程 应用层协议栈分析
CC2541之
SimpleBLEPeripheral
程序流程分析 – 01.启动和事件轮询
CC2541之
SimpleBLEPeripheral
程序流程分析 – 02.App层初始化
CC2541之
SimpleBLEPeripheral
程序流程分析 – 03.App层事务处理
CC2541之
SimpleBLEPeripheral
程序流程分析 – 04.按键处理 .
SimplePeripheral.c代码注释版: