本帖最后由 sujingliang 于 2024-10-30 12:36 编辑
本文大部分内容为搬砖,阅读SDK时都或多或少会遇到相关概念有助理解。
一、蓝牙协议栈
1、PHY层
1Mbps自适应跳频GFSK(高斯频移键控),运行在免证的2.4GHz。
2、LL层
LL层为RF控制器,控制设备处于准备(standby)、广播、监听/扫描(scan)、初始化、连接,这五种状态中一种。五种状态切换描述为:未连接时,设备广播信息,另外一个设备一直监听或按需扫描,两个设备连接初始化,设备连接上了。发起聊天的设备为主设备,接受聊天的设备为从设备,同一次聊天只能有一个意见领袖,即主设备和从设备不能切换。
3、HCI层
HCI层为接口层,向上为主机提供软件应用程序接口(API),对外为外部硬件控制接口,可以通过串口、SPI、USB来实现设备控制。
4、L2CAP层
L2CAP层提供数据封装服务,允许逻辑上的点对点通讯。
5、SM层
SM层提供配对和密匙分发,实现安全连接和数据交换。
6、ATT层
ATT层负责数据检索,允许设备向另外一个设备展示一块特定的数据称之为属性,在ATT环境中,展示属性的设备称之为服务器,与它配对的设备称之为客户端。链路层的主机从机和这里的服务器、客服端是两种概念,主设备既可以是服务器,也可以是客户端。从设备毅然。
7、GATT层
GATT层定义了使用 ATT 的服务框架和配置文件(profiles)的结构。BLE 中所有的数据通信都需要经过 GATT。GATT负责处理向上与应用打交道,其关键工作是把为检索工作提供合适的profile结构,而profile由检索关键词(characteristics)组成。
8、GAP层
GAP直接与应用程序或配置文件(profiles)通信的接口,处理设备发现和连接相关服务。另外还处理安全特性的初始化。对上级,提供应用程序接口,对下级,管理各级职能部门,尤其是指示LL层控制室五种状态切换,指导保卫处做好机要工作。
二、从机源码分析,应该可以实现一个蓝牙点灯
从机源码位于phy6222_v313_0512\example\ble_peripheral\simpleBlePeripheral
顺藤摸瓜先抓个特征值(characteristics)分析,理清SDK实现头绪,至于GATT层、GAP层一般变化不大,暂且放下吧。
1、特征值(characteristics)定义(sbpProfile_ota.h)
源码中定义了7个特征值
- // Profile Parameters
- #define SIMPLEPROFILE_CHAR1 0 // RW uint8 - Profile Characteristic 1 value
- #define SIMPLEPROFILE_CHAR2 1 // RW uint8 - Profile Characteristic 2 value
- #define SIMPLEPROFILE_CHAR3 2 // RW uint8 - Profile Characteristic 3 value
- #define SIMPLEPROFILE_CHAR4 3 // RW uint8 - Profile Characteristic 4 value
- #define SIMPLEPROFILE_CHAR5 4 // RW uint8 - Profile Characteristic 4 value
- #define SIMPLEPROFILE_CHAR6 5 // RW uint8 - Profile Characteristic 4 value
- #define SIMPLEPROFILE_CHAR7 6 // RW uint8 - Profile Characteristic 4 value
- // Key Pressed UUID
- #define SIMPLEPROFILE_CHAR1_UUID 0xFFF1
- #define SIMPLEPROFILE_CHAR2_UUID 0xFFF2
- #define SIMPLEPROFILE_CHAR3_UUID 0xFFF3
- #define SIMPLEPROFILE_CHAR4_UUID 0xFFF4
- #define SIMPLEPROFILE_CHAR5_UUID 0xFFF5
- #define SIMPLEPROFILE_CHAR6_UUID 0xFFF6
- #define SIMPLEPROFILE_CHAR7_UUID 0xFFF7
复制代码 2、UUID的定义(sbpProfile_ota.c)
UUID转换一个形式:
- // Characteristic 4 UUID: 0xFFF4
- CONST uint8 simpleProfilechar4UUID[ATT_BT_UUID_SIZE] =
- {
- LO_UINT16(SIMPLEPROFILE_CHAR4_UUID), HI_UINT16(SIMPLEPROFILE_CHAR4_UUID)
- };
- // Characteristic 5 UUID: 0xFFF5
- CONST uint8 simpleProfilechar5UUID[ATT_BT_UUID_SIZE] =
- {
- LO_UINT16(SIMPLEPROFILE_CHAR5_UUID), HI_UINT16(SIMPLEPROFILE_CHAR5_UUID)
- };
复制代码 3、属性(sbpProfile_ota.c)
特征值的属性:可读、可写、值变量、说明......
- // Simple Profile Characteristic 4 Properties
- static uint8 simpleProfileChar4Props = GATT_PROP_READ | GATT_PROP_WRITE;
- // Characteristic 4 Value
- static uint8 simpleProfileChar4 = 0;
- // Simple Profile Characteristic 4 Configuration Each client has its own
- // instantiation of the Client Characteristic Configuration. Reads of the
- // Client Characteristic Configuration only shows the configuration for
- // that client and writes only affect the configuration of that client.
- static gattCharCfg_t simpleProfileChar4Config[GATT_MAX_NUM_CONN];
- // Simple Profile Characteristic 4 User Description
- static uint8 simpleProfileChar4UserDesp[] = "Power\0";
复制代码 4、属性表(sbpProfile_ota.c)
所有的特征值凑在一起,准备被初始化
- static gattAttribute_t simpleProfileAttrTbl[] =
- {
- ......
- // Characteristic 4 Declaration
- {
- { ATT_BT_UUID_SIZE, characterUUID },
- GATT_PERMIT_READ,
- 0,
- &simpleProfileChar4Props
- },
- // Characteristic Value 4
- {
- { ATT_BT_UUID_SIZE, simpleProfilechar4UUID },
- GATT_PERMIT_READ | GATT_PERMIT_WRITE,
- 0,
- (uint8*)& simpleProfileChar4
- },
- // Characteristic 4 User Description
- {
- { ATT_BT_UUID_SIZE, charUserDescUUID },
- GATT_PERMIT_READ,
- 0,
- simpleProfileChar4UserDesp
- },
- ......
- }
复制代码 5、属性设置操作(sbpProfile_ota.c)
本地设置特征值(characteristics)的value:simpleProfileChar4
- bStatus_t SimpleProfile_SetParameter( uint8 param, uint8 len, void* value )
- {
- ......
- case SIMPLEPROFILE_CHAR4:
- if ( len == sizeof ( uint8 ) )
- {
- simpleProfileChar4 = *((uint8*)value);
- // See if Notification has been enabled
- //GATTServApp_ProcessCharCfg( simpleProfileChar4Config, &simpleProfileChar4, FALSE,
- // simpleProfileAttrTbl, GATT_NUM_ATTRS( simpleProfileAttrTbl ),
- // INVALID_TASK_ID );
- }
- else
- {
- ret = bleInvalidRange;
- }
- break;
- ......
- }
复制代码 6、属性获取操作(sbpProfile_ota.c)
- bStatus_t SimpleProfile_GetParameter( uint8 param, void* value )
- {
- ......
- case SIMPLEPROFILE_CHAR4:
- *((uint8*)value) = simpleProfileChar4;
- //*((uint16*)value) = simpleProfileChar4;
- break;
- .......
- }
复制代码 7、属性读操作(sbpProfile_ota.c)
- static uint8 simpleProfile_ReadAttrCB( uint16 connHandle, gattAttribute_t* pAttr,
- uint8* pValue, uint16* pLen, uint16 offset, uint8 maxLen )
- {
- ......
- case SIMPLEPROFILE_CHAR4_UUID:
- *pLen = 1;
- pValue[0] = *pAttr->pValue;
- break;
- ......
- }
复制代码
8、属性写操作(sbpProfile_ota.c)
- static bStatus_t simpleProfile_WriteAttrCB( uint16 connHandle, gattAttribute_t* pAttr,
- uint8* pValue, uint16 len, uint16 offset )
- {
- .......
- case SIMPLEPROFILE_CHAR4_UUID:
- //Validate the value
- // Make sure it's not a blob oper
- if ( offset == 0 )
- {
- if ( len != 1 )
- {
- status = ATT_ERR_INVALID_VALUE_SIZE;
- }
- }
- else
- {
- status = ATT_ERR_ATTR_NOT_LONG;
- }
- //Write the value
- if ( status == SUCCESS )
- {
- uint8* pCurValue = (uint8*)pAttr->pValue;
- *pCurValue = pValue[0];
- if( uuid == SIMPLEPROFILE_CHAR4_UUID )
- {
- notifyApp = SIMPLEPROFILE_CHAR4;
- }
- }
- break;
- .......
- }
复制代码
9、simpleBLEPeripheral.c
simpleProfileChangeCB()特征值改变时的回调函数,当主机给从机发送数据时,从机就会回调这个函数来告知应用层有数据送达。
static void simpleProfileChangeCB( uint8 paramID )函数的switch中关于CHAR4的判断
如果回调函数输入为SIMPLEPROFILE_CHAR4,通过SimpleProfile_GetParameter读取特征值,判断是否为0x01,如果为真,点亮LED_GPIO。
- static void simpleProfileChangeCB( uint8 paramID )
- {
- uint8 newValue[IBEACON_ATT_LONG_PKT];
- uint8 newValue1;
- switch( paramID )
- {
- case SIMPLEPROFILE_CHAR4:
- SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR4,&newValue1);
- if(newValue1==0x01)
- {
- hal_gpio_write(LED_GPIO, 0);
- }
- else{
- hal_gpio_write(LED_GPIO, 1);
- }
- break;
- }
- }
复制代码 上面只有第9步需要手工加入点灯的步骤,其他都是源码自带的。
今天没有条件验证。应该可以是通过BLE蓝牙调试助手APP(主机)通过BLE连接PB03F(从机),主机发送0x01给SIMPLEPROFILE_CHAR4_UUID点亮LED。
补充一下:
1、用手机BLE调试助手发现目标:BUMBLE-FFFFFFFF,连接
2、连接成功后,发现3个服务,UNKNOWN SERVICE是自定义的服务,因为不是SIG标准服务,所以显示为UNKNOWN
3、向特征值FFF4,发送HEX格式的0x01。
4、蓝牙收到0x01后点亮LED
5、板子背面。设计粗糙,见笑了。
两个飞线是VCC、GND。因为PB03F没有RST引脚,将VCC、GND飞出来可以手动控制模块上电,便于烧录,重启。
|