- void Central_Init()
- {
- centralTaskId = TMOS_ProcessEventRegister(Central_ProcessEvent);
- // Setup GAP
- GAP_SetParamValue(TGAP_DISC_SCAN, DEFAULT_SCAN_DURATION);
- GAP_SetParamValue(TGAP_CONN_EST_INT_MIN, DEFAULT_MIN_CONNECTION_INTERVAL);
- GAP_SetParamValue(TGAP_CONN_EST_INT_MAX, DEFAULT_MAX_CONNECTION_INTERVAL);
- GAP_SetParamValue(TGAP_CONN_EST_SUPERV_TIMEOUT, DEFAULT_CONNECTION_TIMEOUT);
- // Setup the GAP Bond Manager
- {
- uint32_t passkey = DEFAULT_PASSCODE;
- uint8_t pairMode = DEFAULT_PAIRING_MODE;
- uint8_t mitm = DEFAULT_MITM_MODE;
- uint8_t ioCap = DEFAULT_IO_CAPABILITIES;
- uint8_t bonding = DEFAULT_BONDING_MODE;
- GAPBondMgr_SetParameter(GAPBOND_CENT_DEFAULT_PASSCODE, sizeof(uint32_t), &passkey);
- GAPBondMgr_SetParameter(GAPBOND_CENT_PAIRING_MODE, sizeof(uint8_t), &pairMode);
- GAPBondMgr_SetParameter(GAPBOND_CENT_MITM_PROTECTION, sizeof(uint8_t), &mitm);
- GAPBondMgr_SetParameter(GAPBOND_CENT_IO_CAPABILITIES, sizeof(uint8_t), &ioCap);
- GAPBondMgr_SetParameter(GAPBOND_CENT_BONDING_ENABLED, sizeof(uint8_t), &bonding);
- }
- // Init Connection Item
- centralInitConnItem(centralTaskId, centralConnList);
- // Initialize GATT Client
- GATT_InitClient();
- // Register to receive incoming ATT Indications/Notifications
- GATT_RegisterForInd(centralTaskId);
- // Setup a delayed profile startup
- tmos_set_event(centralTaskId, START_DEVICE_EVT);
- }
wch的BLE协议实现好像都是基于TMOS的,在Central_Init这个我们看到最后一行代码这里tmos_set_event(centralTaskId, START_DEVICE_EVT)直接启动设备启动事件,我们直接看事件回调函数Central_ProcessEvent里面的START_DEVICE_EVT- uint16_t Central_ProcessEvent(uint8_t task_id, uint16_t events)
- {
- if(events & SYS_EVENT_MSG)
- {
- uint8_t *pMsg;
- if((pMsg = tmos_msg_receive(centralTaskId)) != NULL)
- {
- central_ProcessTMOSMsg((tmos_event_hdr_t *)pMsg);
- // Release the TMOS message
- tmos_msg_deallocate(pMsg);
- }
- // return unprocessed events
- return (events ^ SYS_EVENT_MSG);
- }
- if(events & START_DEVICE_EVT)
- {
- // Start the Device
- GAPRole_CentralStartDevice(centralTaskId, ¢ralBondCB, ¢ralRoleCB);
- return (events ^ START_DEVICE_EVT);
- }
- }
在GAPRole_CentralStartDevice(centralTaskId, ¢ralBondCB, ¢ralRoleCB)里面又实现了
绑定管理回调函数:
- // Bond Manager Callbacks
- static gapBondCBs_t centralBondCB = {
- centralPasscodeCB,
- centralPairStateCB
- };
以及GAP角色回调函数
- // GAP Role Callbacks
- static gapCentralRoleCB_t centralRoleCB = {
- centralRssiCB, // RSSI callback
- centralEventCB, // Event callback
- centralHciMTUChangeCB // MTU change callback
- };
centralEventCB这个事件回调函数里面全是GAP连接相关的事件的处理,GAP连接相关的事件可以CH58xBLE_LIB.h里面找到- #define GAP_DEVICE_INIT_DONE_EVENT 0x00 //!< Sent when the Device Initialization is complete. This event is sent as an tmos message defined as gapDeviceInitDoneEvent_t.
- #define GAP_DEVICE_DISCOVERY_EVENT 0x01 //!< Sent when the Device Discovery Process is complete. This event is sent as an tmos message defined as gapDevDiscEvent_t.
- #define GAP_ADV_DATA_UPDATE_DONE_EVENT 0x02 //!< Sent when the Advertising Data or SCAN_RSP Data has been updated. This event is sent as an tmos message defined as gapAdvDataUpdateEvent_t.
- #define GAP_MAKE_DISCOVERABLE_DONE_EVENT 0x03 //!< Sent when the Make Discoverable Request is complete. This event is sent as an tmos message defined as gapMakeDiscoverableRspEvent_t.
- #define GAP_END_DISCOVERABLE_DONE_EVENT 0x04 //!< Sent when the Advertising has ended. This event is sent as an tmos message defined as gapEndDiscoverableRspEvent_t.
- #define GAP_LINK_ESTABLISHED_EVENT 0x05 //!< Sent when the Establish Link Request is complete. This event is sent as an tmos message defined as gapEstLinkReqEvent_t.
- #define GAP_LINK_TERMINATED_EVENT 0x06 //!< Sent when a connection was terminated. This event is sent as an tmos message defined as gapTerminateLinkEvent_t.
- #define GAP_LINK_PARAM_UPDATE_EVENT 0x07 //!< Sent when an Update Parameters Event is received. This event is sent as an tmos message defined as gapLinkUpdateEvent_t.
我们在GAP_DEVICE_INFO_EVENT里面过滤一下"Simple Peripheral"广播的peripheral如下代码:
- case GAP_DEVICE_INFO_EVENT:
- {
- // Add device to list
- if(strstr(pEvent->deviceInfo.pEvtData,"Simple Peripheral")!=NULL)
- {
- PRINT("%s\r\n",pEvent->deviceInfo.pEvtData);
- centralAddDeviceInfo(pEvent->deviceInfo.addr, pEvent->deviceInfo.addrType);
- }
- // // Add device to list
- // centralAddDeviceInfo(pEvent->deviceInfo.addr, pEvent->deviceInfo.addrType);
- }
这样MultiCentral就只添加Simple Peripheral了。
接着修改对端设备地址,根据MAC连接的,并且我们只需要2个外设设备,所以这里修改一下对端设备地址和连接数:
- #ifndef CENTRAL_MAX_CONNECTION
- #define CENTRAL_MAX_CONNECTION 2
- #endif
- // Peer device address
- static peerAddrDefItem_t PeerAddrDef[CENTRAL_MAX_CONNECTION] = {
- {0x3d, 0x61, 0x85, 0x26, 0x3b, 0x38 },
- {0x34, 0x53, 0x24, 0x7b, 0x54, 0x50 }
- };
GAP_LINK_ESTABLISHED_EVENT是建立连接的事件,在这里wch已经实现了连接0的了,如下:- // 连接0
- if(connItem == CONNECT0_ITEM)
- {
- centralConnList[connItem].procedureInProgress = TRUE;
- // Initiate service discovery
- tmos_start_task(centralConnList[connItem].taskID, START_SVC_DISCOVERY_EVT, DEFAULT_SVC_DISCOVERY_DELAY);
- // Initiate connect parameter update
- tmos_start_task(centralConnList[connItem].taskID, START_PARAM_UPDATE_EVT, DEFAULT_PARAM_UPDATE_DELAY);
- // Start RSSI polling
- tmos_start_task(centralConnList[connItem].taskID, START_READ_RSSI_EVT, DEFAULT_RSSI_PERIOD);
- }
这里直接复制连接0的即可:- // 连接1
- else if(connItem == CONNECT1_ITEM)
- {
- centralConnList[connItem].procedureInProgress = TRUE;
- // Initiate service discovery
- tmos_start_task(centralConnList[connItem].taskID, START_SVC_DISCOVERY_EVT, DEFAULT_SVC_DISCOVERY_DELAY);
- // Initiate connect parameter update
- tmos_start_task(centralConnList[connItem].taskID, START_PARAM_UPDATE_EVT, DEFAULT_PARAM_UPDATE_DELAY);
- // Start RSSI polling
- tmos_start_task(centralConnList[connItem].taskID, START_READ_RSSI_EVT, DEFAULT_RSSI_PERIOD);
- }
我们可以看到,这里启动了发现服务,参数更新,RSSI任务,那我们对应的也需要修改一下。连接0的是connect0_ProcessEvent处理的,那么我们直接复制修改如下:
- static uint16_t connect1_ProcessEvent(uint8_t task_id, uint16_t events)
- {
- if(events & START_SVC_DISCOVERY_EVT)
- {
- // start service discovery
- centralConnIistStartDiscovery_1();
- return (events ^ START_SVC_DISCOVERY_EVT);
- }
- if(events & START_READ_OR_WRITE_EVT)
- {
- if(centralConnList[CONNECT1_ITEM].procedureInProgress == FALSE)
- {
- if(centralDoWrite)
- {
- // Do a write
- attWriteReq_t req;
- req.cmd = FALSE;
- req.sig = FALSE;
- req.handle = centralConnList[CONNECT1_ITEM].charHdl;
- req.len = 1;
- req.pValue = GATT_bm_alloc(centralConnList[CONNECT1_ITEM].connHandle, ATT_WRITE_REQ, req.len, NULL, 0);
- if(req.pValue != NULL)
- {
- *req.pValue = centralCharVal;
- if(GATT_WriteCharValue(centralConnList[CONNECT1_ITEM].connHandle, &req, centralTaskId) == SUCCESS)
- {
- centralConnList[CONNECT1_ITEM].procedureInProgress = TRUE;
- centralDoWrite = !centralDoWrite;
- tmos_start_task(centralConnList[CONNECT1_ITEM].taskID, START_READ_OR_WRITE_EVT, DEFAULT_READ_OR_WRITE_DELAY);
- }
- else
- {
- GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
- }
- }
- }
- else
- {
- // Do a read
- attReadReq_t req;
- req.handle = centralConnList[CONNECT1_ITEM].charHdl;
- if(GATT_ReadCharValue(centralConnList[CONNECT1_ITEM].connHandle, &req, centralTaskId) == SUCCESS)
- {
- centralConnList[CONNECT1_ITEM].procedureInProgress = TRUE;
- centralDoWrite = !centralDoWrite;
- }
- }
- }
- return (events ^ START_READ_OR_WRITE_EVT);
- }
- if(events & START_PARAM_UPDATE_EVT)
- {
- // start connect parameter update
- GAPRole_UpdateLink(centralConnList[CONNECT1_ITEM].connHandle,
- DEFAULT_UPDATE_MIN_CONN_INTERVAL,
- DEFAULT_UPDATE_MAX_CONN_INTERVAL,
- DEFAULT_UPDATE_SLAVE_LATENCY,
- DEFAULT_UPDATE_CONN_TIMEOUT);
- return (events ^ START_PARAM_UPDATE_EVT);
- }
- if(events & START_WRITE_CCCD_EVT)
- {
- if(centralConnList[CONNECT1_ITEM].procedureInProgress == FALSE)
- {
- // Do a write
- attWriteReq_t req;
- req.cmd = FALSE;
- req.sig = FALSE;
- req.handle = centralConnList[CONNECT1_ITEM].cccHdl;
- req.len = 2;
- req.pValue = GATT_bm_alloc(centralConnList[CONNECT1_ITEM].connHandle, ATT_WRITE_REQ, req.len, NULL, 0);
- if(req.pValue != NULL)
- {
- req.pValue[0] = 1;
- req.pValue[1] = 0;
- if(GATT_WriteCharValue(centralConnList[CONNECT1_ITEM].connHandle, &req, centralTaskId) == SUCCESS)
- {
- centralConnList[CONNECT1_ITEM].procedureInProgress = TRUE;
- }
- else
- {
- GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
- }
- }
- }
- return (events ^ START_WRITE_CCCD_EVT);
- }
- if(events & START_READ_RSSI_EVT)
- {
- GAPRole_ReadRssiCmd(centralConnList[CONNECT1_ITEM].connHandle);
- tmos_start_task(centralConnList[CONNECT1_ITEM].taskID, START_READ_RSSI_EVT, DEFAULT_RSSI_PERIOD);
- return (events ^ START_READ_RSSI_EVT);
- }
- // Discard unknown events
- return 0;
- }
把CONNECT0_ITEM改成CONNECT1_ITEM,编译一下会发现centralConnIistStartDiscovery_1还没实现,这里也是复制粘贴修改
- static void centralConnIistStartDiscovery_1(void)
- {
- uint8_t uuid[ATT_BT_UUID_SIZE] = {LO_UINT16(SIMPLEPROFILE_SERV_UUID),
- HI_UINT16(SIMPLEPROFILE_SERV_UUID)};
- // Initialize cached handles
- centralConnList[CONNECT1_ITEM].svcStartHdl = centralConnList[CONNECT1_ITEM].svcEndHdl = centralConnList[CONNECT1_ITEM].charHdl = 0;
- centralConnList[CONNECT1_ITEM].discState = BLE_DISC_STATE_SVC;
- // Discovery simple BLE service
- GATT_DiscPrimaryServiceByUUID(centralConnList[CONNECT1_ITEM].connHandle,
- uuid,
- ATT_BT_UUID_SIZE,
- centralTaskId);
- }
然后回到,Central_ProcessEvent添加调用
- // 连接1的任务处理
- else if(task_id == centralConnList[CONNECT1_ITEM].taskID)
- {
- return connect1_ProcessEvent(task_id, events);
- }
如果直接编译下载的话,估计跟我第一次修改实现的一样,还是只能接收先连接的,只有一个外设的noti,
因为我还差了一步:
- /*********************************************************************
- * @fn centralGATTDiscoveryEvent
- *
- * [url=home.php?mod=space&uid=247401]@brief[/url] Process GATT discovery event
- *
- * [url=home.php?mod=space&uid=266161]@return[/url] none
- */
- static void centralGATTDiscoveryEvent(uint8_t connItem, gattMsgEvent_t *pMsg)
- {
- attReadByTypeReq_t req;
- // 连接0的枚举
- if(connItem == CONNECT0_ITEM)
- {
- if(centralConnList[connItem].discState == BLE_DISC_STATE_SVC)
- {
- // Service found, store handles
- if(pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP &&
- pMsg->msg.findByTypeValueRsp.numInfo > 0)
- {
- centralConnList[connItem].svcStartHdl = ATT_ATTR_HANDLE(pMsg->msg.findByTypeValueRsp.pHandlesInfo, 0);
- centralConnList[connItem].svcEndHdl = ATT_GRP_END_HANDLE(pMsg->msg.findByTypeValueRsp.pHandlesInfo, 0);
- // Display Profile Service handle range
- PRINT("Found Profile Service handle : %x ~ %x \n", centralConnList[connItem].svcStartHdl, centralConnList[connItem].svcEndHdl);
- }
- // If procedure complete
- if((pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP &&
- pMsg->hdr.status == bleProcedureComplete) ||
- (pMsg->method == ATT_ERROR_RSP))
- {
- if(centralConnList[connItem].svcStartHdl != 0)
- {
- // Discover characteristic
- centralConnList[connItem].discState = BLE_DISC_STATE_CHAR;
- req.startHandle = centralConnList[connItem].svcStartHdl;
- req.endHandle = centralConnList[connItem].svcEndHdl;
- req.type.len = ATT_BT_UUID_SIZE;
- req.type.uuid[0] = LO_UINT16(SIMPLEPROFILE_CHAR1_UUID);
- req.type.uuid[1] = HI_UINT16(SIMPLEPROFILE_CHAR1_UUID);
- GATT_ReadUsingCharUUID(centralConnList[connItem].connHandle, &req, centralTaskId);
- }
- }
- }
- else if(centralConnList[connItem].discState == BLE_DISC_STATE_CHAR)
- {
- // Characteristic found, store handle
- if(pMsg->method == ATT_READ_BY_TYPE_RSP &&
- pMsg->msg.readByTypeRsp.numPairs > 0)
- {
- centralConnList[connItem].charHdl = BUILD_UINT16(pMsg->msg.readByTypeRsp.pDataList[0],
- pMsg->msg.readByTypeRsp.pDataList[1]);
- centralConnList[connItem].procedureInProgress = FALSE;
- // Start do read or write
- tmos_start_task(centralConnList[connItem].taskID, START_READ_OR_WRITE_EVT, DEFAULT_READ_OR_WRITE_DELAY);
- // Display Characteristic 1 handle
- PRINT("Found Characteristic 1 handle : %x \n", centralConnList[0].charHdl);
- }
- if((pMsg->method == ATT_READ_BY_TYPE_RSP &&
- pMsg->hdr.status == bleProcedureComplete) ||
- (pMsg->method == ATT_ERROR_RSP))
- {
- // Discover characteristic
- centralConnList[connItem].discState = BLE_DISC_STATE_CCCD;
- req.startHandle = centralConnList[connItem].svcStartHdl;
- req.endHandle = centralConnList[connItem].svcEndHdl;
- req.type.len = ATT_BT_UUID_SIZE;
- req.type.uuid[0] = LO_UINT16(GATT_CLIENT_CHAR_CFG_UUID);
- req.type.uuid[1] = HI_UINT16(GATT_CLIENT_CHAR_CFG_UUID);
- GATT_ReadUsingCharUUID(centralConnList[connItem].connHandle, &req, centralTaskId);
- }
- }
- else if(centralConnList[connItem].discState == BLE_DISC_STATE_CCCD)
- {
- // Characteristic found, store handle
- if(pMsg->method == ATT_READ_BY_TYPE_RSP &&
- pMsg->msg.readByTypeRsp.numPairs > 0)
- {
- centralConnList[connItem].cccHdl = BUILD_UINT16(pMsg->msg.readByTypeRsp.pDataList[0],
- pMsg->msg.readByTypeRsp.pDataList[1]);
- centralConnList[connItem].procedureInProgress = FALSE;
- // Start do write CCCD
- tmos_start_task(centralConnList[connItem].taskID, START_WRITE_CCCD_EVT, DEFAULT_WRITE_CCCD_DELAY);
- // Display Characteristic 1 handle
- PRINT("Found client characteristic configuration handle : %x \n", centralConnList[connItem].cccHdl);
- }
- centralConnList[connItem].discState = BLE_DISC_STATE_IDLE;
- }
- }
- // 连接1的枚举
- else if(connItem == CONNECT1_ITEM)
- {
- if(centralConnList[connItem].discState == BLE_DISC_STATE_SVC)
- {
- // Service found, store handles
- if(pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP &&
- pMsg->msg.findByTypeValueRsp.numInfo > 0)
- {
- centralConnList[connItem].svcStartHdl = ATT_ATTR_HANDLE(pMsg->msg.findByTypeValueRsp.pHandlesInfo, 0);
- centralConnList[connItem].svcEndHdl = ATT_GRP_END_HANDLE(pMsg->msg.findByTypeValueRsp.pHandlesInfo, 0);
- // Display Profile Service handle range
- PRINT("Found Profile Service handle : %x ~ %x \n", centralConnList[connItem].svcStartHdl, centralConnList[connItem].svcEndHdl);
- }
- // If procedure complete
- if((pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP &&
- pMsg->hdr.status == bleProcedureComplete) ||
- (pMsg->method == ATT_ERROR_RSP))
- {
- if(centralConnList[connItem].svcStartHdl != 0)
- {
- // Discover characteristic
- centralConnList[connItem].discState = BLE_DISC_STATE_CHAR;
- req.startHandle = centralConnList[connItem].svcStartHdl;
- req.endHandle = centralConnList[connItem].svcEndHdl;
- req.type.len = ATT_BT_UUID_SIZE;
- req.type.uuid[0] = LO_UINT16(SIMPLEPROFILE_CHAR1_UUID);
- req.type.uuid[1] = HI_UINT16(SIMPLEPROFILE_CHAR1_UUID);
- GATT_ReadUsingCharUUID(centralConnList[connItem].connHandle, &req, centralTaskId);
- }
- }
- }
- else if(centralConnList[connItem].discState == BLE_DISC_STATE_CHAR)
- {
- // Characteristic found, store handle
- if(pMsg->method == ATT_READ_BY_TYPE_RSP &&
- pMsg->msg.readByTypeRsp.numPairs > 0)
- {
- centralConnList[connItem].charHdl = BUILD_UINT16(pMsg->msg.readByTypeRsp.pDataList[0],
- pMsg->msg.readByTypeRsp.pDataList[1]);
- centralConnList[connItem].procedureInProgress = FALSE;
- // Start do read or write
- tmos_start_task(centralConnList[connItem].taskID, START_READ_OR_WRITE_EVT, DEFAULT_READ_OR_WRITE_DELAY);
- // Display Characteristic 1 handle
- PRINT("Found Characteristic 1 handle : %x \n", centralConnList[0].charHdl);
- }
- if((pMsg->method == ATT_READ_BY_TYPE_RSP &&
- pMsg->hdr.status == bleProcedureComplete) ||
- (pMsg->method == ATT_ERROR_RSP))
- {
- // Discover characteristic
- centralConnList[connItem].discState = BLE_DISC_STATE_CCCD;
- req.startHandle = centralConnList[connItem].svcStartHdl;
- req.endHandle = centralConnList[connItem].svcEndHdl;
- req.type.len = ATT_BT_UUID_SIZE;
- req.type.uuid[0] = LO_UINT16(GATT_CLIENT_CHAR_CFG_UUID);
- req.type.uuid[1] = HI_UINT16(GATT_CLIENT_CHAR_CFG_UUID);
- GATT_ReadUsingCharUUID(centralConnList[connItem].connHandle, &req, centralTaskId);
- }
- }
- else if(centralConnList[connItem].discState == BLE_DISC_STATE_CCCD)
- {
- // Characteristic found, store handle
- if(pMsg->method == ATT_READ_BY_TYPE_RSP &&
- pMsg->msg.readByTypeRsp.numPairs > 0)
- {
- centralConnList[connItem].cccHdl = BUILD_UINT16(pMsg->msg.readByTypeRsp.pDataList[0],
- pMsg->msg.readByTypeRsp.pDataList[1]);
- centralConnList[connItem].procedureInProgress = FALSE;
- // Start do write CCCD
- tmos_start_task(centralConnList[connItem].taskID, START_WRITE_CCCD_EVT, DEFAULT_WRITE_CCCD_DELAY);
- // Display Characteristic 1 handle
- PRINT("Found client characteristic configuration handle : %x \n", centralConnList[connItem].cccHdl);
- }
- centralConnList[connItem].discState = BLE_DISC_STATE_IDLE;
- }
- }
- // 连接2的枚举
- else if(connItem == CONNECT2_ITEM)
- {
- }
- }
要在这个函数里面实现连接1的枚举。
最后可以看到multicentrl是有接收两个设备的noti