简介:枚举全部服务需要按照下面三个步骤来进行,完整代码直接看第四点。

一.枚举出PrimaryServices的uuid和handle范围:

1.库函数

GATT_DiscAllPrimaryServices(centralConnHandle,centralTaskId );

2.从机返回数据处理

case BLE_DISC_STATE_SVC:
            // 处理服务发现结果
            if (pMsg->method == ATT_READ_BY_GRP_TYPE_RSP) {
                if (pMsg->msg.readByGrpTypeRsp.numGrps > 0) {
                    uint8_t len = pMsg->msg.readByGrpTypeRsp.len;
                    uint8_t *pData = pMsg->msg.readByGrpTypeRsp.pDataList;

                    for (uint8_t i = 0; i < pMsg->msg.readByGrpTypeRsp.numGrps; i++) {
                        uint16_t startHandle = BUILD_UINT16(pData[len * i], pData[len * i + 1]);
                        uint16_t endHandle = BUILD_UINT16(pData[len * i + 2], pData[len * i + 3]);
                        uint8_t uuidLen = len - 4;
                        uint8_t *uuid = &pData[len * i + 4];

                        PRINT("服务 #%d:\r\n", i+1);
                        PRINT("  起始句柄: 0x%04X\r\n", startHandle);
                        PRINT("  结束句柄: 0x%04X\r\n", endHandle);
                        PRINT("  UUID长度: %d 字节\r\n", uuidLen);
                        PRINT("  UUID: ");
                        hex_dump(uuid, uuidLen);

                        // 可选:检查特定服务UUID并存储句柄
                        if (uuidLen == 2 && uuid[0] == LO_UINT16(SIMPLEPROFILE_SERV_UUID) &&
                            uuid[1] == HI_UINT16(SIMPLEPROFILE_SERV_UUID)) {
                            centralSvcStartHdl = startHandle;
                            centralSvcEndHdl = endHandle;
                            PRINT("找到SimpleProfile服务!\r\n");
                        }
                    }
                }

                // 服务发现完成,开始发现特征
                if (pMsg->hdr.status == bleProcedureComplete) {
                    centralDiscState = BLE_DISC_STATE_CHAR;
                    uint16_t startHdl = 0x01;
                    uint16_t endHdl = 0xFFFF;
                    // 使用实际服务范围(优化:避免全范围搜索)
//                    uint16_t startHdl = (centralSvcStartHdl > 0) ? centralSvcStartHdl : 0x01;
//                    uint16_t endHdl = (centralSvcEndHdl > 0) ? centralSvcEndHdl : 0xFFFF;
                    result = GATT_DiscAllChars(centralConnHandle, startHdl, endHdl, centralTaskId);
                    PRINT("GATT_DiscAllChars = 0x%02X\r\n", result);

                    if (result != SUCCESS) {
                        PRINT("错误: 启动特征发现失败 (0x%02X)\r\n", result);
                        centralDiscState = BLE_DISC_STATE_IDLE;
                    }
                }
            } else if (pMsg->method == ATT_ERROR_RSP) {
                PRINT("错误: 服务发现失败 (0x%02X)\r\n", pMsg->hdr.status);
                centralDiscState = BLE_DISC_STATE_IDLE;
            }
            break;

3.代码输出详解

每次最多只能返回2个PrimaryServices,Peripheral例程有四个PrimaryServices,分两次获取到所有的四个PrimaryServices;分别获取到了每个PrimaryService的起始句柄,结束句柄和UUID。

GATT_DiscAllPrimaryServices = 0x00
服务 #1:
  起始句柄: 0x0001
  结束句柄: 0x0009
  UUID长度: 2 字节
  UUID: 00 18 
服务 #2:
  起始句柄: 0x000A
  结束句柄: 0x000D
  UUID长度: 2 字节
  UUID: 01 18 
服务 #1:
  起始句柄: 0x000E
  结束句柄: 0x0020
  UUID长度: 2 字节
  UUID: 0a 18 
服务 #2:
  起始句柄: 0x0021
  结束句柄: 0x0031
  UUID长度: 2 字节
  UUID: e0 ff 
找到SimpleProfile服务!
GATT_DiscAllChars = 0x00

二.枚举出每次主服务下的chars:

1.库函数

GATT_DiscAllChars(centralConnHandle,0x01,0xFFFF,centralTaskId);

2.从机返回数据处理

case BLE_DISC_STATE_CHAR:
            // 处理特征发现结果
            if (pMsg->method == ATT_READ_BY_TYPE_RSP) {
                if (pMsg->msg.readByTypeRsp.numPairs > 0) {
                    uint8_t len = pMsg->msg.readByTypeRsp.len;
                    uint8_t *pData = pMsg->msg.readByTypeRsp.pDataList;

                    for (uint8_t i = 0; i < pMsg->msg.readByTypeRsp.numPairs; i++) {
                        uint8_t properties = pData[len * i + 2];
                        uint16_t valueHandle = BUILD_UINT16(pData[len * i + 3], pData[len * i + 4]);
                        uint8_t uuidLen = len - 5;
                        uint8_t *uuid = &pData[len * i + 5];

                        PRINT("特征 #%d:\r\n", i+1);
                        PRINT("  属性: 0x%02X\r\n", properties);
                        PRINT("  值句柄: 0x%04X\r\n", valueHandle);
                        PRINT("  UUID长度: %d 字节\r\n", uuidLen);
                        PRINT("  UUID: ");
                        hex_dump(uuid, uuidLen);

                        // 存储可写特征句柄
                        if (properties & (GATT_PROP_WRITE | GATT_PROP_WRITE_NO_RSP)) {
                            centralCharHdl = valueHandle;
                            PRINT("  可写特征句柄: 0x%04X\r\n", valueHandle);
                        }

                        // 存储可通知特征的CCCD句柄 (值句柄+1)
                        if (properties & GATT_PROP_NOTIFY) {
                            centralCCCDHdl = valueHandle + 1;
                            PRINT("  通知CCCD句柄: 0x%04X\r\n", centralCCCDHdl);
                        }
                    }
                }

                // 特征发现完成,开始发现描述符
                if (pMsg->hdr.status == bleProcedureComplete) {
                    centralDiscState = BLE_DISC_STATE_DESC;
                    uint16_t startHdl = 0x01;
                    uint16_t endHdl = 0xFFFF;

                    // 使用实际特征范围(优化:避免全范围搜索)
//                    uint16_t startHdl = (centralSvcStartHdl > 0) ? centralSvcStartHdl : 0x01;
//                    uint16_t endHdl = (centralSvcEndHdl > 0) ? centralSvcEndHdl : 0xFFFF;

                    result = GATT_DiscAllCharDescs(centralConnHandle, startHdl, endHdl, centralTaskId);
                    PRINT("GATT_DiscAllCharDescs = 0x%02X\r\n", result);

                    if (result != SUCCESS) {
                        PRINT("错误: 启动描述符发现失败 (0x%02X)\r\n", result);
                        centralDiscState = BLE_DISC_STATE_IDLE;
                    }
                }
            } else if (pMsg->method == ATT_ERROR_RSP) {
                PRINT("错误: 特征发现失败 (0x%02X)\r\n", pMsg->hdr.status);
                centralDiscState = BLE_DISC_STATE_IDLE;
            }
            break;

3.代码输出详解

每次最多只能返回3个Chars,Peripheral例程有19个Chars,分7次获取到所有的19个Chars;分别获取到了每个Char的属性,属性值句柄和UUID。

GATT_DiscAllChars = 0x00
PHY Update 0...
RSSI : -46 dB 
特征 #1:
  属性: 0x02
  值句柄: 0x0003
  UUID长度: 2 字节
  UUID: 00 2a 
特征 #2:
  属性: 0x02
  值句柄: 0x0005
  UUID长度: 2 字节
  UUID: 01 2a 
特征 #3:
  属性: 0x02
  值句柄: 0x0007
  UUID长度: 2 字节
  UUID: 04 2a 
特征 #1:
  属性: 0x02
  值句柄: 0x0009
  UUID长度: 2 字节
  UUID: a6 2a 
特征 #2:
  属性: 0x20
  值句柄: 0x000C
  UUID长度: 2 字节
  UUID: 05 2a 
特征 #3:
  属性: 0x02
  值句柄: 0x0010
  UUID长度: 2 字节
  UUID: 23 2a 
特征 #1:
  属性: 0x02
  值句柄: 0x0012
  UUID长度: 2 字节
  UUID: 24 2a 
特征 #2:
  属性: 0x02
  值句柄: 0x0014
  UUID长度: 2 字节
  UUID: 25 2a 
特征 #3:
  属性: 0x02
  值句柄: 0x0016
  UUID长度: 2 字节
  UUID: 26 2a 
PHY Update...
特征 #1:
  属性: 0x02
  值句柄: 0x0018
  UUID长度: 2 字节
  UUID: 27 2a 
特征 #2:
  属性: 0x02
  值句柄: 0x001A
  UUID长度: 2 字节
  UUID: 28 2a 
特征 #3:
  属性: 0x02
  值句柄: 0x001C
  UUID长度: 2 字节
  UUID: 29 2a 
特征 #1:
  属性: 0x02
  值句柄: 0x001E
  UUID长度: 2 字节
  UUID: 2a 2a 
特征 #2:
  属性: 0x02
  值句柄: 0x0020
  UUID长度: 2 字节
  UUID: 50 2a 
特征 #3:
  属性: 0x0A
  值句柄: 0x0023
  UUID长度: 2 字节
  UUID: e1 ff 
  可写特征句柄: 0x0023
特征 #1:
  属性: 0x02
  值句柄: 0x0026
  UUID长度: 2 字节
  UUID: e2 ff 
特征 #2:
  属性: 0x08
  值句柄: 0x0029
  UUID长度: 2 字节
  UUID: e3 ff 
  可写特征句柄: 0x0029
特征 #3:
  属性: 0x10
  值句柄: 0x002C
  UUID长度: 2 字节
  UUID: e4 ff 
  通知CCCD句柄: 0x002D
RSSI : -49 dB 
Param Update...
特征 #1:
  属性: 0x02
  值句柄: 0x0030
  UUID长度: 2 字节
  UUID: e5 ff 

三.枚举处每个char的Declarations和Descriptors:

1.库函数

GATT_DiscAllCharDescs(centralConnHandle,0x01,0xFFFF,centralTaskId);

2.从机返回数据处理

case BLE_DISC_STATE_DESC:
            // 处理描述符发现结果
            if (pMsg->method == ATT_FIND_INFO_RSP) {
                if (pMsg->msg.findInfoRsp.numInfo > 0) {
                    uint16_t numInfo = pMsg->msg.findInfoRsp.numInfo;
                    uint8_t format = pMsg->msg.findInfoRsp.format;
                    uint8_t *pInfo = pMsg->msg.findInfoRsp.pInfo;

                    PRINT("找到 %d 个描述符\r\n", numInfo);
                    PRINT("找到 %d 个描述符\r\n", format);
                    // 验证格式和数据长度
                    uint8_t entrySize = (format == 0x01) ? 4 : 18; // 16位或128位UUID
                    if (1) {
                        for (uint16_t i = 0; i < numInfo; i++) {
                            uint16_t handle = BUILD_UINT16(pInfo[i * entrySize], pInfo[i * entrySize + 1]);

                            PRINT("描述符 #%d:\r\n", i+1);
                            PRINT("  句柄: 0x%04X\r\n", handle);

                            if (format == 0x01) { // 16位UUID
                                uint16_t uuid = BUILD_UINT16(pInfo[i * entrySize + 2], pInfo[i * entrySize + 3]);
                                PRINT("  UUID: 0x%04X\r\n", uuid);

                                // 检查是否为CCCD (0x2902)
                                if (uuid == GATT_CLIENT_CHAR_CFG_UUID) {
                                    PRINT("  找到CCCD描述符!\r\n");
                                    centralCCCDHdl = handle; // 更新CCCD句柄
                                }
                            } else { // 128位UUID
                                PRINT("  UUID: 128位 (省略显示)\r\n");
                                // 可扩展:添加128位UUID处理逻辑
                            }
                        }
                    } else {
                        PRINT("错误: 描述符数据长度不匹配!\r\n");
                    }
                }

                // 描述符发现完成
                if (pMsg->hdr.status == bleProcedureComplete) {
                    PRINT("描述符发现完成!\r\n");
                    centralDiscState = BLE_DISC_STATE_COMPLETE;

                    // 启动下一步操作(例如启用通知)仅是演示,当服务中发现多个centralCCCDHdl时只会开启最后一个
                    if (centralCCCDHdl != 0) {
                        tmos_start_task(centralTaskId, START_WRITE_CCCD_EVT, 1600);
                    }
                }
            } else if (pMsg->method == ATT_ERROR_RSP) {
                PRINT("错误: 描述符发现失败 (0x%02X)\r\n", pMsg->hdr.status);
                centralDiscState = BLE_DISC_STATE_IDLE;
            }
            break;

        default:
            break;
    }

3.代码输出详解

每次最多只能返回5个描述符,Peripheral例程有49个Chars,分8次获取到所有的49个Chars;分别获取到了每个描述符的句柄和UUID。

GATT_DiscAllCharDescs = 0x00
找到 5 个描述符
找到 1 个描述符
描述符 #1:
  句柄: 0x0001
  UUID: 0x2800
描述符 #2:
  句柄: 0x0002
  UUID: 0x2803
描述符 #3:
  句柄: 0x0003
  UUID: 0x2A00
描述符 #4:
  句柄: 0x0004
  UUID: 0x2803
描述符 #5:
  句柄: 0x0005
  UUID: 0x2A01
找到 5 个描述符
找到 1 个描述符
描述符 #1:
  句柄: 0x0006
  UUID: 0x2803
描述符 #2:
  句柄: 0x0007
  UUID: 0x2A04
描述符 #3:
  句柄: 0x0008
  UUID: 0x2803
描述符 #4:
  句柄: 0x0009
  UUID: 0x2AA6
描述符 #5:
  句柄: 0x000A
  UUID: 0x2800
找到 5 个描述符
找到 1 个描述符
描述符 #1:
  句柄: 0x000B
  UUID: 0x2803
描述符 #2:
  句柄: 0x000C
  UUID: 0x2A05
描述符 #3:
  句柄: 0x000D
  UUID: 0x2902
  找到CCCD描述符!
描述符 #4:
  句柄: 0x000E
  UUID: 0x2800
描述符 #5:
  句柄: 0x000F
  UUID: 0x2803
找到 5 个描述符
找到 1 个描述符
描述符 #1:
  句柄: 0x0010
  UUID: 0x2A23
描述符 #2:
  句柄: 0x0011
  UUID: 0x2803
描述符 #3:
  句柄: 0x0012
  UUID: 0x2A24
描述符 #4:
  句柄: 0x0013
  UUID: 0x2803
描述符 #5:
  句柄: 0x0014
  UUID: 0x2A25
找到 5 个描述符
找到 1 个描述符
描述符 #1:
  句柄: 0x0015
  UUID: 0x2803
描述符 #2:
  句柄: 0x0016
  UUID: 0x2A26
描述符 #3:
  句柄: 0x0017
  UUID: 0x2803
描述符 #4:
  句柄: 0x0018
  UUID: 0x2A27
描述符 #5:
  句柄: 0x0019
  UUID: 0x2803
找到 5 个描述符
找到 1 个描述符
描述符 #1:
  句柄: 0x001A
  UUID: 0x2A28
描述符 #2:
  句柄: 0x001B
  UUID: 0x2803
描述符 #3:
  句柄: 0x001C
  UUID: 0x2A29
描述符 #4:
  句柄: 0x001D
  UUID: 0x2803
描述符 #5:
  句柄: 0x001E
  UUID: 0x2A2A
找到 5 个描述符
找到 1 个描述符
描述符 #1:
  句柄: 0x001F
  UUID: 0x2803
描述符 #2:
  句柄: 0x0020
  UUID: 0x2A50
描述符 #3:
  句柄: 0x0021
  UUID: 0x2800
描述符 #4:
  句柄: 0x0022
  UUID: 0x2803
描述符 #5:
  句柄: 0x0023
  UUID: 0xFFE1
找到 5 个描述符
找到 1 个描述符
描述符 #1:
  句柄: 0x0024
  UUID: 0x2901
描述符 #2:
  句柄: 0x0025
  UUID: 0x2803
描述符 #3:
  句柄: 0x0026
  UUID: 0xFFE2
描述符 #4:
  句柄: 0x0027
  UUID: 0x2901
描述符 #5:
  句柄: 0x0028
  UUID: 0x2803
RSSI : -46 dB 
找到 5 个描述符
找到 1 个描述符
描述符 #1:
  句柄: 0x0029
  UUID: 0xFFE3
描述符 #2:
  句柄: 0x002A
  UUID: 0x2901
描述符 #3:
  句柄: 0x002B
  UUID: 0x2803
描述符 #4:
  句柄: 0x002C
  UUID: 0xFFE4
描述符 #5:
  句柄: 0x002D
  UUID: 0x2902
  找到CCCD描述符!
找到 4 个描述符
找到 1 个描述符
描述符 #1:
  句柄: 0x002E
  UUID: 0x2901
描述符 #2:
  句柄: 0x002F
  UUID: 0x2803
描述符 #3:
  句柄: 0x0030
  UUID: 0xFFE5
描述符 #4:
  句柄: 0x0031
  UUID: 0x2901
描述符发现完成!

四.完整代码展示:

将下面两个函数直接替换主机例程里的同名函数便可使用,hex_dump为方便打印输出的函数,

void hex_dump(uint8_t* data,uint32_t length) {
    for(uint32_t i=0;i<length;i++) {
        PRINT("%02x ",*data);
        data++;
    }
    PRINT("\r\n");
}

static void centralStartDiscovery(void)
{
    uint8_t result;

    // 初始化缓存的句柄
    centralSvcStartHdl = centralSvcEndHdl = centralCharHdl = 0;
    centralCCCDHdl = 0; // 新增CCCD句柄初始化
    centralDiscState = BLE_DISC_STATE_SVC;

    // 发现所有主服务
    result = GATT_DiscAllPrimaryServices(centralConnHandle, centralTaskId);
    PRINT("GATT_DiscAllPrimaryServices = 0x%02X\r\n", result);

    if (result != SUCCESS) {
        PRINT("错误: 启动服务发现失败 (0x%02X)\r\n", result);
        centralDiscState = BLE_DISC_STATE_IDLE;
    }
}

static void centralGATTDiscoveryEvent(gattMsgEvent_t *pMsg)
{
    uint8_t result;

    if (pMsg == NULL) return; //检查空指针

    switch (centralDiscState) {
        case BLE_DISC_STATE_SVC:
            // 处理服务发现结果
            if (pMsg->method == ATT_READ_BY_GRP_TYPE_RSP) {
                if (pMsg->msg.readByGrpTypeRsp.numGrps > 0) {
                    uint8_t len = pMsg->msg.readByGrpTypeRsp.len;
                    uint8_t *pData = pMsg->msg.readByGrpTypeRsp.pDataList;

                    for (uint8_t i = 0; i < pMsg->msg.readByGrpTypeRsp.numGrps; i++) {
                        uint16_t startHandle = BUILD_UINT16(pData[len * i], pData[len * i + 1]);
                        uint16_t endHandle = BUILD_UINT16(pData[len * i + 2], pData[len * i + 3]);
                        uint8_t uuidLen = len - 4;
                        uint8_t *uuid = &pData[len * i + 4];

                        PRINT("服务 #%d:\r\n", i+1);
                        PRINT("  起始句柄: 0x%04X\r\n", startHandle);
                        PRINT("  结束句柄: 0x%04X\r\n", endHandle);
                        PRINT("  UUID长度: %d 字节\r\n", uuidLen);
                        PRINT("  UUID: ");
                        hex_dump(uuid, uuidLen);

                        // 可选:检查特定服务UUID并存储句柄
                        if (uuidLen == 2 && uuid[0] == LO_UINT16(SIMPLEPROFILE_SERV_UUID) &&
                            uuid[1] == HI_UINT16(SIMPLEPROFILE_SERV_UUID)) {
                            centralSvcStartHdl = startHandle;
                            centralSvcEndHdl = endHandle;
                            PRINT("找到SimpleProfile服务!\r\n");
                        }
                    }
                }

                // 服务发现完成,开始发现特征
                if (pMsg->hdr.status == bleProcedureComplete) {
                    centralDiscState = BLE_DISC_STATE_CHAR;
                    uint16_t startHdl = 0x01;
                    uint16_t endHdl = 0xFFFF;
                    // 使用实际服务范围(优化:避免全范围搜索)
//                    uint16_t startHdl = (centralSvcStartHdl > 0) ? centralSvcStartHdl : 0x01;
//                    uint16_t endHdl = (centralSvcEndHdl > 0) ? centralSvcEndHdl : 0xFFFF;
                    result = GATT_DiscAllChars(centralConnHandle, startHdl, endHdl, centralTaskId);
                    PRINT("GATT_DiscAllChars = 0x%02X\r\n", result);

                    if (result != SUCCESS) {
                        PRINT("错误: 启动特征发现失败 (0x%02X)\r\n", result);
                        centralDiscState = BLE_DISC_STATE_IDLE;
                    }
                }
            } else if (pMsg->method == ATT_ERROR_RSP) {
                PRINT("错误: 服务发现失败 (0x%02X)\r\n", pMsg->hdr.status);
                centralDiscState = BLE_DISC_STATE_IDLE;
            }
            break;

        case BLE_DISC_STATE_CHAR:
            // 处理特征发现结果
            if (pMsg->method == ATT_READ_BY_TYPE_RSP) {
                if (pMsg->msg.readByTypeRsp.numPairs > 0) {
                    uint8_t len = pMsg->msg.readByTypeRsp.len;
                    uint8_t *pData = pMsg->msg.readByTypeRsp.pDataList;

                    for (uint8_t i = 0; i < pMsg->msg.readByTypeRsp.numPairs; i++) {
                        uint8_t properties = pData[len * i + 2];
                        uint16_t valueHandle = BUILD_UINT16(pData[len * i + 3], pData[len * i + 4]);
                        uint8_t uuidLen = len - 5;
                        uint8_t *uuid = &pData[len * i + 5];

                        PRINT("特征 #%d:\r\n", i+1);
                        PRINT("  属性: 0x%02X\r\n", properties);
                        PRINT("  值句柄: 0x%04X\r\n", valueHandle);
                        PRINT("  UUID长度: %d 字节\r\n", uuidLen);
                        PRINT("  UUID: ");
                        hex_dump(uuid, uuidLen);

                        // 存储可写特征句柄
                        if (properties & (GATT_PROP_WRITE | GATT_PROP_WRITE_NO_RSP)) {
                            centralCharHdl = valueHandle;
                            PRINT("  可写特征句柄: 0x%04X\r\n", valueHandle);
                        }

                        // 存储可通知特征的CCCD句柄 (值句柄+1)
                        if (properties & GATT_PROP_NOTIFY) {
                            centralCCCDHdl = valueHandle + 1;
                            PRINT("  通知CCCD句柄: 0x%04X\r\n", centralCCCDHdl);
                        }
                    }
                }

                // 特征发现完成,开始发现描述符
                if (pMsg->hdr.status == bleProcedureComplete) {
                    centralDiscState = BLE_DISC_STATE_DESC;
                    uint16_t startHdl = 0x01;
                    uint16_t endHdl = 0xFFFF;

                    // 使用实际特征范围(优化:避免全范围搜索)
//                    uint16_t startHdl = (centralSvcStartHdl > 0) ? centralSvcStartHdl : 0x01;
//                    uint16_t endHdl = (centralSvcEndHdl > 0) ? centralSvcEndHdl : 0xFFFF;

                    result = GATT_DiscAllCharDescs(centralConnHandle, startHdl, endHdl, centralTaskId);
                    PRINT("GATT_DiscAllCharDescs = 0x%02X\r\n", result);

                    if (result != SUCCESS) {
                        PRINT("错误: 启动描述符发现失败 (0x%02X)\r\n", result);
                        centralDiscState = BLE_DISC_STATE_IDLE;
                    }
                }
            } else if (pMsg->method == ATT_ERROR_RSP) {
                PRINT("错误: 特征发现失败 (0x%02X)\r\n", pMsg->hdr.status);
                centralDiscState = BLE_DISC_STATE_IDLE;
            }
            break;

        case BLE_DISC_STATE_DESC:
            // 处理描述符发现结果
            if (pMsg->method == ATT_FIND_INFO_RSP) {
                if (pMsg->msg.findInfoRsp.numInfo > 0) {
                    uint16_t numInfo = pMsg->msg.findInfoRsp.numInfo;
                    uint8_t format = pMsg->msg.findInfoRsp.format;
                    uint8_t *pInfo = pMsg->msg.findInfoRsp.pInfo;

                    PRINT("找到 %d 个描述符\r\n", numInfo);
                    PRINT("找到 %d 个描述符\r\n", format);
                    // 验证格式和数据长度
                    uint8_t entrySize = (format == 0x01) ? 4 : 18; // 16位或128位UUID
                    if (1) {
                        for (uint16_t i = 0; i < numInfo; i++) {
                            uint16_t handle = BUILD_UINT16(pInfo[i * entrySize], pInfo[i * entrySize + 1]);

                            PRINT("描述符 #%d:\r\n", i+1);
                            PRINT("  句柄: 0x%04X\r\n", handle);

                            if (format == 0x01) { // 16位UUID
                                uint16_t uuid = BUILD_UINT16(pInfo[i * entrySize + 2], pInfo[i * entrySize + 3]);
                                PRINT("  UUID: 0x%04X\r\n", uuid);

                                // 检查是否为CCCD (0x2902)
                                if (uuid == GATT_CLIENT_CHAR_CFG_UUID) {
                                    PRINT("  找到CCCD描述符!\r\n");
                                    centralCCCDHdl = handle; // 更新CCCD句柄
                                }
                            } else { // 128位UUID
                                PRINT("  UUID: 128位 (省略显示)\r\n");
                                // 可扩展:添加128位UUID处理逻辑
                            }
                        }
                    } else {
                        PRINT("错误: 描述符数据长度不匹配!\r\n");
                    }
                }

                // 描述符发现完成
                if (pMsg->hdr.status == bleProcedureComplete) {
                    PRINT("描述符发现完成!\r\n");
                    centralDiscState = BLE_DISC_STATE_COMPLETE;

                    // 启动下一步操作(例如启用通知)仅是演示,当服务中发现多个centralCCCDHdl时只会开启最后一个
                    if (centralCCCDHdl != 0) {
                        tmos_start_task(centralTaskId, START_WRITE_CCCD_EVT, 1600);
                    }
                }
            } else if (pMsg->method == ATT_ERROR_RSP) {
                PRINT("错误: 描述符发现失败 (0x%02X)\r\n", pMsg->hdr.status);
                centralDiscState = BLE_DISC_STATE_IDLE;
            }
            break;

        default:
            break;
    }
}

 五.完整的打印输出

GATT_DiscAllPrimaryServices = 0x00
服务 #1:
  起始句柄: 0x0001
  结束句柄: 0x0009
  UUID长度: 2 字节
  UUID: 00 18 
服务 #2:
  起始句柄: 0x000A
  结束句柄: 0x000D
  UUID长度: 2 字节
  UUID: 01 18 
服务 #1:
  起始句柄: 0x000E
  结束句柄: 0x0020
  UUID长度: 2 字节
  UUID: 0a 18 
服务 #2:
  起始句柄: 0x0021
  结束句柄: 0x0031
  UUID长度: 2 字节
  UUID: e0 ff 
找到SimpleProfile服务!
GATT_DiscAllChars = 0x00
PHY Update 0...
RSSI : -46 dB 
特征 #1:
  属性: 0x02
  值句柄: 0x0003
  UUID长度: 2 字节
  UUID: 00 2a 
特征 #2:
  属性: 0x02
  值句柄: 0x0005
  UUID长度: 2 字节
  UUID: 01 2a 
特征 #3:
  属性: 0x02
  值句柄: 0x0007
  UUID长度: 2 字节
  UUID: 04 2a 
特征 #1:
  属性: 0x02
  值句柄: 0x0009
  UUID长度: 2 字节
  UUID: a6 2a 
特征 #2:
  属性: 0x20
  值句柄: 0x000C
  UUID长度: 2 字节
  UUID: 05 2a 
特征 #3:
  属性: 0x02
  值句柄: 0x0010
  UUID长度: 2 字节
  UUID: 23 2a 
特征 #1:
  属性: 0x02
  值句柄: 0x0012
  UUID长度: 2 字节
  UUID: 24 2a 
特征 #2:
  属性: 0x02
  值句柄: 0x0014
  UUID长度: 2 字节
  UUID: 25 2a 
特征 #3:
  属性: 0x02
  值句柄: 0x0016
  UUID长度: 2 字节
  UUID: 26 2a 
PHY Update...
特征 #1:
  属性: 0x02
  值句柄: 0x0018
  UUID长度: 2 字节
  UUID: 27 2a 
特征 #2:
  属性: 0x02
  值句柄: 0x001A
  UUID长度: 2 字节
  UUID: 28 2a 
特征 #3:
  属性: 0x02
  值句柄: 0x001C
  UUID长度: 2 字节
  UUID: 29 2a 
特征 #1:
  属性: 0x02
  值句柄: 0x001E
  UUID长度: 2 字节
  UUID: 2a 2a 
特征 #2:
  属性: 0x02
  值句柄: 0x0020
  UUID长度: 2 字节
  UUID: 50 2a 
特征 #3:
  属性: 0x0A
  值句柄: 0x0023
  UUID长度: 2 字节
  UUID: e1 ff 
  可写特征句柄: 0x0023
特征 #1:
  属性: 0x02
  值句柄: 0x0026
  UUID长度: 2 字节
  UUID: e2 ff 
特征 #2:
  属性: 0x08
  值句柄: 0x0029
  UUID长度: 2 字节
  UUID: e3 ff 
  可写特征句柄: 0x0029
特征 #3:
  属性: 0x10
  值句柄: 0x002C
  UUID长度: 2 字节
  UUID: e4 ff 
  通知CCCD句柄: 0x002D
RSSI : -49 dB 
Param Update...
特征 #1:
  属性: 0x02
  值句柄: 0x0030
  UUID长度: 2 字节
  UUID: e5 ff 
GATT_DiscAllCharDescs = 0x00
找到 5 个描述符
找到 1 个描述符
描述符 #1:
  句柄: 0x0001
  UUID: 0x2800
描述符 #2:
  句柄: 0x0002
  UUID: 0x2803
描述符 #3:
  句柄: 0x0003
  UUID: 0x2A00
描述符 #4:
  句柄: 0x0004
  UUID: 0x2803
描述符 #5:
  句柄: 0x0005
  UUID: 0x2A01
找到 5 个描述符
找到 1 个描述符
描述符 #1:
  句柄: 0x0006
  UUID: 0x2803
描述符 #2:
  句柄: 0x0007
  UUID: 0x2A04
描述符 #3:
  句柄: 0x0008
  UUID: 0x2803
描述符 #4:
  句柄: 0x0009
  UUID: 0x2AA6
描述符 #5:
  句柄: 0x000A
  UUID: 0x2800
找到 5 个描述符
找到 1 个描述符
描述符 #1:
  句柄: 0x000B
  UUID: 0x2803
描述符 #2:
  句柄: 0x000C
  UUID: 0x2A05
描述符 #3:
  句柄: 0x000D
  UUID: 0x2902
  找到CCCD描述符!
描述符 #4:
  句柄: 0x000E
  UUID: 0x2800
描述符 #5:
  句柄: 0x000F
  UUID: 0x2803
找到 5 个描述符
找到 1 个描述符
描述符 #1:
  句柄: 0x0010
  UUID: 0x2A23
描述符 #2:
  句柄: 0x0011
  UUID: 0x2803
描述符 #3:
  句柄: 0x0012
  UUID: 0x2A24
描述符 #4:
  句柄: 0x0013
  UUID: 0x2803
描述符 #5:
  句柄: 0x0014
  UUID: 0x2A25
找到 5 个描述符
找到 1 个描述符
描述符 #1:
  句柄: 0x0015
  UUID: 0x2803
描述符 #2:
  句柄: 0x0016
  UUID: 0x2A26
描述符 #3:
  句柄: 0x0017
  UUID: 0x2803
描述符 #4:
  句柄: 0x0018
  UUID: 0x2A27
描述符 #5:
  句柄: 0x0019
  UUID: 0x2803
找到 5 个描述符
找到 1 个描述符
描述符 #1:
  句柄: 0x001A
  UUID: 0x2A28
描述符 #2:
  句柄: 0x001B
  UUID: 0x2803
描述符 #3:
  句柄: 0x001C
  UUID: 0x2A29
描述符 #4:
  句柄: 0x001D
  UUID: 0x2803
描述符 #5:
  句柄: 0x001E
  UUID: 0x2A2A
找到 5 个描述符
找到 1 个描述符
描述符 #1:
  句柄: 0x001F
  UUID: 0x2803
描述符 #2:
  句柄: 0x0020
  UUID: 0x2A50
描述符 #3:
  句柄: 0x0021
  UUID: 0x2800
描述符 #4:
  句柄: 0x0022
  UUID: 0x2803
描述符 #5:
  句柄: 0x0023
  UUID: 0xFFE1
找到 5 个描述符
找到 1 个描述符
描述符 #1:
  句柄: 0x0024
  UUID: 0x2901
描述符 #2:
  句柄: 0x0025
  UUID: 0x2803
描述符 #3:
  句柄: 0x0026
  UUID: 0xFFE2
描述符 #4:
  句柄: 0x0027
  UUID: 0x2901
描述符 #5:
  句柄: 0x0028
  UUID: 0x2803
RSSI : -46 dB 
找到 5 个描述符
找到 1 个描述符
描述符 #1:
  句柄: 0x0029
  UUID: 0xFFE3
描述符 #2:
  句柄: 0x002A
  UUID: 0x2901
描述符 #3:
  句柄: 0x002B
  UUID: 0x2803
描述符 #4:
  句柄: 0x002C
  UUID: 0xFFE4
描述符 #5:
  句柄: 0x002D
  UUID: 0x2902
  找到CCCD描述符!
找到 4 个描述符
找到 1 个描述符
描述符 #1:
  句柄: 0x002E
  UUID: 0x2901
描述符 #2:
  句柄: 0x002F
  UUID: 0x2803
描述符 #3:
  句柄: 0x0030
  UUID: 0xFFE5
描述符 #4:
  句柄: 0x0031
  UUID: 0x2901
描述符发现完成!
RSSI : -47 dB 
Write success 
Receive noti: 88
Receive noti: 88
RSSI : -47 dB 

 

posted on 2025-05-29 22:44  WCH蓝牙应用分享  阅读(109)  评论(0)    收藏  举报