【WCH蓝牙系列芯片】-基于CH585开发板—蓝牙主机直接获取蓝牙从机的handle,建立通信

------------------------------------------------------------------------------------------------------------------------------------ 

  在蓝牙主机程序上,默认的例程中是用的通过对比设备MAC地址之后,进行酶具有蓝牙从机的UUID服务,然后通过枚举的服务来得到handle值,从而通过通过handle值来建立通信。在这个基础上,对例程的handle值进行修改,可以枚举出蓝牙从机的整个UUID的服务,通过查看UUID直接获取到对应的hanlde值,然后直接由hanldela来发起读写数据的任务事件操作。

image

  在默认的例程中,centralStartDiscovery函数中,将主机的“发现状态机”切换到 BLE_DISC_STATE_SVC(正在发现主服务)状态,然后直接利用GATT_DiscAllPrimaryServices函数对蓝牙从机的所有服务进行读取。并且将函数返回值打印出来,这个可以通过返回值判断,是否枚举成功,如果枚举不成功,就重新再开启TMOS任务事件,再从头开启枚举。

  在centralGATTDiscoveryEvent函数中,替换成下面新的函数

static void centralGATTDiscoveryEvent(gattMsgEvent_t *pMsg)
{
    attReadByTypeReq_t req;
    uint8_t result;
    if(centralDiscState == BLE_DISC_STATE_SVC)   //判断当前的中央设备的状态是否为服务发现状态
    {
        // Service found, store handles
        PRINT("method1=%x numGrps1=%04x \n", pMsg->method, pMsg->msg.readByGrpTypeRsp.numGrps);

      //判断接收到的消息是否是按组类型读取响应(ATT_READ_BY_GRP_TYPE_RSP),并且返回的组数量大于0
        if(pMsg->method == ATT_READ_BY_GRP_TYPE_RSP &&pMsg->msg.readByGrpTypeRsp.numGrps > 0)
        {
            for(unsigned char i = 0 ; i < pMsg->msg.readByGrpTypeRsp.numGrps;i++)
            {

                // Attribute LEN   当前属性的长度
                PRINT("current att len:%04d\r\n",pMsg->msg.readByGrpTypeRsp.len);

                // Attribute start Handle  当前属性的起始句柄
                PRINT("current att start handle:%04x\r\n",
                      BUILD_UINT16( pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i], \
                            pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i + 1]));

                // Attribute End Group Handle  当前属性的结束句柄
                PRINT("current att end  handle:%04x\r\n",
                      BUILD_UINT16(   pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i+2], \
                            pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i + 3]));

                //Primary Service UUID Length  当前服务UUID的长度
                PRINT("current service uuid len:%04d\r\n",pMsg->msg.readByGrpTypeRsp.len - 4);

                // uuid  打印UUID
                PRINT("uuid:");

                //指向当前UUID的指针位置
                uint8_t *p_uuid = &(pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i + 4]);

                //计算UUID的长度
                uint8_t uuid_length = pMsg->msg.readByGrpTypeRsp.len - 4;

                //打印UUID的内容
                hex_dump(p_uuid,uuid_length);
                printf("\r\n");

            }
        }
        // If procedure complete
        PRINT("method=%x status=%x centralSvcStartHdl=%x\r\n",pMsg->method,pMsg->hdr.status,centralSvcStartHdl);
        //收到的消息是否是按组类型读取响应(ATT_READ_BY_GRP_TYPE_RSP)
        //过程状态为完成状态(bleProcedureComplete)
        //消息的方法为错误响应(ATT_ERROR_RSP)
        if((pMsg->method == ATT_READ_BY_GRP_TYPE_RSP &&
            pMsg->hdr.status == bleProcedureComplete) ||
           (pMsg->method == ATT_ERROR_RSP))
        {
                // Discover characteristic  即将开始发现特征
                centralDiscState = BLE_DISC_STATE_CHAR;
                //发现所有特征
                result = GATT_DiscAllChars(centralConnHandle,0x01,0xFFFF,centralTaskId);
                PRINT("GATT_DiscAllChars:%02x\r\n",result);
         }
    }
    else if(centralDiscState == BLE_DISC_STATE_CHAR)  //是否为特征发现状态
    {
        // Characteristic found, store handle

      //检查收到的消息是否是按类型读取响应(ATT_READ_BY_TYPE_RSP)并且消息中包含的特征数量大于0
        if(pMsg->method == ATT_READ_BY_TYPE_RSP &&
           pMsg->msg.readByTypeRsp.numPairs > 0)
        {
            for(unsigned char i = 0; i < pMsg->msg.readByTypeRsp.numPairs ; i++)
            {

                //characteristic properties
                //提取特征的属性,例如读、写、通知
                uint8_t char_properties = pMsg->msg.readByTypeRsp.pDataList[pMsg->msg.readByTypeRsp.len * i + 2];
                //提取特征的值句柄
                uint16_t char_value_handle = BUILD_UINT16(pMsg->msg.readByTypeRsp.pDataList[pMsg->msg.readByTypeRsp.len * i+3], \
                                             pMsg->msg.readByTypeRsp.pDataList[pMsg->msg.readByTypeRsp.len * i + 4]);


                //characteristic uuid length  特征UUID的长度
                uint8_t char_uuid_length = pMsg->msg.readByGrpTypeRsp.len - 5;

                //uuid  提取特征UUID的值
                uint8_t *char_uuid = &(pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i + 5]);

                //如果具有写属性,则打印"write handle"
                PRINT("char_properties  :%02x,%s\r\n",char_properties,(char_properties&(GATT_PROP_WRITE|GATT_PROP_WRITE_NO_RSP))?"wite handle":"");
                PRINT("char_value_handle:%04x\r\n",char_value_handle);  //特征的值句柄
                PRINT("char_uuid_length :%02d\r\n",char_uuid_length);  //特征UUID的长度
                PRINT("char_uuid        :");  //打印特征UUID的值
                hex_dump(char_uuid,char_uuid_length);


                //对写和读属性
                if (char_value_handle == 0x26)
                {
                  centralCharHdl = 0x26;
                  centralProcedureInProgress = FALSE;
                  tmos_start_task(centralTaskId, START_READ_OR_WRITE_EVT, 1600);
                }

                //具有通知属性
                if (char_value_handle == 0x23)
                {
                  centralCCCDHdl = char_value_handle+1;
                  centralProcedureInProgress = FALSE;
                  PRINT("notify handle:%04x\r\n",char_value_handle);
                  tmos_start_task(centralTaskId, START_WRITE_CCCD_EVT, 1600);
                }
                printf("\r\n");
            }

        }
    }
}

  在前面调用了 GATT_DiscAllPrimaryServices (寻找所有服务)后,这段函数将服务中的么据特征值全部打印出来,底层协议栈拿到从机发来的数据,就会不断地触发这个回调函数

  这两个部分修改完之后,可以利用BLE_UART的程序进行配合使用,通过打印可以看到,

image

 

image

image

  通过打印可以看到可以看到枚举BLE_UART中的读写数据的服务对应的服务和对应的hanlde值,这样可以直接对handle值来开启任务。

image

image

  这样就可以让主机对从机进行操作,在这个基础上,下次可以保存这个成功枚举到的handle值,如果下次再次连接同一个设备,可以直接拿这个handle值进行操作,可以省去这个枚举服务的流程。

 

 

posted on 2026-04-29 23:12  凡仕  阅读(26)  评论(0)    收藏  举报