赞
踩
在做的项目本身只是需要用到蓝牙从机就行,从机项目开发已基本要收尾了。考虑到要配合产线系统做自动化测试,因此需要一个配合从机的主机dongle供自动化测试系统使用。
蓝牙主机的使用只要按主机和从机的通信流程来走的话各家的蓝牙软件流程基本差不多,都是围绕主机扫描----主机连接-----(主从交换mtu等phy参数)-------主机遍历从机的service------主机遍历所需要service下的char记录下需要char的handle值以及同时找出支持notify的char handler-----对支持notify/indicate的char进行使能-----------对所需要的char进行read write
代码上的大体流程主要如下
1、主机角色初始化,扫描连接及启动遍历service
- GAPRole_CentralInit();
- // Initialize GATT Client
- GATT_InitClient();
- //注册相关回调
- GAPRole_CentralStartDevice(centralTaskId, ¢ralBondCB, ¢ralRoleCB);
-
-
- 回调定义
- // GAP Role Callbacks
- static gapCentralRoleCB_t centralRoleCB = {
- centralRssiCB, // RSSI callback
- centralEventCB, // Event callback
- centralHciMTUChangeCB // MTU change callback
- };
-
-
- 和蓝牙通信连接相关的主要回调,扫描 连接等状态的切换主要都在该回调里
- static void centralEventCB(gapRoleEvent_t *pEvent)
- {
- switch(pEvent->gap.opcode)
- {
- case GAP_DEVICE_INIT_DONE_EVENT:
- {
- PRINT("Discovering...\n");
- GAPRole_CentralStartDiscovery(DEFAULT_DISCOVERY_MODE,
- DEFAULT_DISCOVERY_ACTIVE_SCAN,
- DEFAULT_DISCOVERY_WHITE_LIST);
- }
- break;
-
- case GAP_DEVICE_INFO_EVENT:
- {
- // Add device to list
- PRINT("Add device to list...\n");
- centralAddDeviceInfo(pEvent->deviceInfo.addr, pEvent->deviceInfo.addrType);
- }
- break;
-
- case GAP_DEVICE_DISCOVERY_EVENT:
- {
- uint8_t i;
- PRINT("centralScanRes:%d...\r\n",centralScanRes);
- // See if peer device has been discovered
- for(i = 0; i < centralScanRes; i++)
- {
- if(tmos_memcmp(PeerAddrDef, centralDevList[i].addr, B_ADDR_LEN))
- break;
- }
-
- // Peer device not found
- if(i == centralScanRes)
- {
- PRINT("Device not found...\n");
- centralScanRes = 0;
- GAPRole_CentralStartDiscovery(DEFAULT_DISCOVERY_MODE,
- DEFAULT_DISCOVERY_ACTIVE_SCAN,
- DEFAULT_DISCOVERY_WHITE_LIST);
- PRINT("Discovering...\n");
- }
-
- // Peer device found
- else
- {
- PRINT("Device found...\n");
- GAPRole_CentralEstablishLink(DEFAULT_LINK_HIGH_DUTY_CYCLE,
- DEFAULT_LINK_WHITE_LIST,
- centralDevList[i].addrType,
- centralDevList[i].addr);
-
- // Start establish link timeout event
- tmos_start_task(centralTaskId, ESTABLISH_LINK_TIMEOUT_EVT, ESTABLISH_LINK_TIMEOUT);
- PRINT("Connecting...\n");
- }
- }
- break;
-
- case GAP_LINK_ESTABLISHED_EVENT:
- {
- PRINT("GAP_LINK_ESTABLISHED_EVENT...\n");
- tmos_stop_task(centralTaskId, ESTABLISH_LINK_TIMEOUT_EVT);
- if(pEvent->gap.hdr.status == SUCCESS)
- {
- centralState = BLE_STATE_CONNECTED;
- centralConnHandle = pEvent->linkCmpl.connectionHandle;
- centralProcedureInProgress = TRUE;
-
- central_gattdiscover_start();//连接上后开始遍历serveice和char
-
- // Initiate service discovery
- tmos_start_task(centralTaskId, START_SVC_DISCOVERY_EVT, DEFAULT_SVC_DISCOVERY_DELAY);
-
- // See if initiate connect parameter update
- if(centralParamUpdate)
- {
- tmos_start_task(centralTaskId, START_PARAM_UPDATE_EVT, DEFAULT_PARAM_UPDATE_DELAY);
- }
- // See if initiate connect parameter update
- if(centralPhyUpdate)
- {
- tmos_start_task(centralTaskId, START_PHY_UPDATE_EVT, DEFAULT_PHY_UPDATE_DELAY);
- }
- // See if start RSSI polling
- if(centralRssi)
- {
- tmos_start_task(centralTaskId, START_READ_RSSI_EVT, DEFAULT_RSSI_PERIOD);
- }
-
- PRINT("Connected...\n");
- }
- else
- {
- PRINT("Connect Failed...Reason:%X\n", pEvent->gap.hdr.status);
- PRINT("Discovering...\n");
- centralScanRes = 0;
- GAPRole_CentralStartDiscovery(DEFAULT_DISCOVERY_MODE,
- DEFAULT_DISCOVERY_ACTIVE_SCAN,
- DEFAULT_DISCOVERY_WHITE_LIST);
- }
- }
- break;
-
- case GAP_LINK_TERMINATED_EVENT:
- {
- centralState = BLE_STATE_IDLE;
- centralConnHandle = GAP_CONNHANDLE_INIT;
- centralDiscState = BLE_DISC_STATE_IDLE;
- centralCharHdl = 0;
- centralScanRes = 0;
- centralProcedureInProgress = FALSE;
- tmos_stop_task(centralTaskId, START_READ_RSSI_EVT);
- PRINT("Disconnected...Reason:%x\n", pEvent->linkTerminate.reason);
- PRINT("Discovering...\n");
- GAPRole_CentralStartDiscovery(DEFAULT_DISCOVERY_MODE,
- DEFAULT_DISCOVERY_ACTIVE_SCAN,
- DEFAULT_DISCOVERY_WHITE_LIST);
- }
- break;
-
- case GAP_LINK_PARAM_UPDATE_EVENT:
- {
- PRINT("Param Update...\n");
- }
- break;
-
- case GAP_PHY_UPDATE_EVENT:
- {
- PRINT("PHY Update...\n");
- }
- break;
-
- case GAP_EXT_ADV_DEVICE_INFO_EVENT:
- {
- // Display device addr
- PRINT("AddrType:%d Recv ext adv - Addr %x %x %x %x %x %x \n", pEvent->deviceExtAdvInfo.addrType,pEvent->deviceExtAdvInfo.addr[0],
- pEvent->deviceExtAdvInfo.addr[1], pEvent->deviceExtAdvInfo.addr[2],
- pEvent->deviceExtAdvInfo.addr[3], pEvent->deviceExtAdvInfo.addr[4],
- pEvent->deviceExtAdvInfo.addr[5]);
- }
- break;
-
- case GAP_DIRECT_DEVICE_INFO_EVENT:
- {
- // Display device addr
- PRINT("AddrType:%d Recv direct adv - Addr %x %x %x %x %x %x \n", pEvent->deviceExtAdvInfo.addrType, pEvent->deviceExtAdvInfo.addr[0],
- pEvent->deviceExtAdvInfo.addr[1], pEvent->deviceExtAdvInfo.addr[2],
- pEvent->deviceExtAdvInfo.addr[3], pEvent->deviceExtAdvInfo.addr[4],
- pEvent->deviceExtAdvInfo.addr[5]);
- }
- break;
-
- default:
- break;
- }
- }
-
-
-
2、遍历service和char
- //遍历所有service
- GATT_DiscAllPrimaryServices(centralConnHandle,centralTaskId );
-
- 遍历完成会通过centralProcessGATTMsg传递系统消息SYS_EVENT_MSG给用户层进行解析
-
- //如下从系统消息里解析出来遍历到需要的service hander值
- 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++)
- {
- uint8_t *p_uuid = &(pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i + 4]);
- uint8_t uuid_length = pMsg->msg.readByGrpTypeRsp.len - 4;
-
-
- if(uuid_length == sizeof(TheFind_ServiceUUID)){
- if(tmos_memcmp(TheFind_ServiceUUID,p_uuid,uuid_length)) {
- centralSvcStartHdl = BUILD_UINT16( pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i], \
- pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i + 1]);
- centralSvcEndHdl = BUILD_UINT16( pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i+2], \
- pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i + 3]);
- }
- }
-
-
- }
- }
-
-
-
找到service后开始遍历char
- //遍历所有char找到自己要用的char handler值
- GATT_DiscAllChars(centralConnHandle,centralSvcStartHdl,centralSvcEndHdl,centralTaskId);
-
- //同样也是通过系统消息传递遍历后的结果
- if ( pMsg->method == ATT_READ_BY_TYPE_RSP ){
- if(pMsg->msg.readByTypeRsp.numPairs > 0 ){
-
- for(unsigned char i = 0; i < pMsg->msg.readByTypeRsp.numPairs ; i++){
- 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
- uint8_t char_uuid_length = pMsg->msg.readByGrpTypeRsp.len - 5;
-
- //uuid
- uint8_t *chat_uuid = &(pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i + 5]);
- if(sizeof(TheFind_CharUUID) == char_uuid_length){
- if(tmos_memcmp(TheFind_CharUUID,chat_uuid,char_uuid_length)){
- TheFind_CharUUID = char_value_handle;
- }
- }
- }
- }
- }
-
3、遍历支持notify的char handler
- req.startHandle = centralSvcStartHdl;
- req.endHandle = centralSvcEndHdl;
- 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( centralConnHandle, &req, centralTaskId );
4、读写char
- void WriteCharHandler(uint8_t* data,uint8_t datalen,uint16_t Handler)
- {
- attWriteReq_t req;
- req.cmd = FALSE;
- req.sig = FALSE;
- req.handle = Handler;
- req.len = datalen;
- req.pValue = GATT_bm_alloc(centralConnHandle, ATT_WRITE_REQ, req.len, NULL, 0);
- if(req.pValue != NULL)
- {
- tmos_memcpy(req.pValue,data,datalen);
- if(GATT_WriteCharValue(centralConnHandle, &req, centralTaskId) == SUCCESS)
- {
- centralDoWrite = FALSE;
- }
- else
- {
- GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
- }
- }
- }
-
-
- void ReadCharHandler(uint16_t handle)
- {
- attReadReq_t req;
- req.handle = handle;
- GATT_ReadCharValue(centralConnHandle, &req, centralTaskId);
- }
-
-
5、接收notify以及read响应
- //接收读写回应以及notify indicate都是通过系统消息进来给用户
-
- static void centralProcessGATTMsg(gattMsgEvent_t *pMsg)
- {
- if(centralState != BLE_STATE_CONNECTED)
- {
- // In case a GATT message came after a connection has dropped,
- // ignore the message
- GATT_bm_free(&pMsg->msg, pMsg->method);
- return;
- }
-
- if((pMsg->method == ATT_EXCHANGE_MTU_RSP) ||
- ((pMsg->method == ATT_ERROR_RSP) &&
- (pMsg->msg.errorRsp.reqOpcode == ATT_EXCHANGE_MTU_REQ)))
- {
- if(pMsg->method == ATT_ERROR_RSP)
- {
- uint8_t status = pMsg->msg.errorRsp.errCode;
-
- PRINT("Exchange MTU Error: %x\n", status);
- }
- centralProcedureInProgress = FALSE;
- }
-
- if(pMsg->method == ATT_MTU_UPDATED_EVENT)
- {
- PRINT("MTU: %x\n", pMsg->msg.mtuEvt.MTU);
- }
-
- if((pMsg->method == ATT_READ_RSP) ||
- ((pMsg->method == ATT_ERROR_RSP) &&
- (pMsg->msg.errorRsp.reqOpcode == ATT_READ_REQ)))
- {
- if(pMsg->method == ATT_ERROR_RSP)
- {
- uint8_t status = pMsg->msg.errorRsp.errCode;
-
- PRINT("Read Error: %x\n", status);
- }
- else
- {
- // After a successful read, display the read value
- PRINT("Read rsp: %x\n", *pMsg->msg.readRsp.pValue);
-
- }
- centralProcedureInProgress = FALSE;
- }
- else if((pMsg->method == ATT_WRITE_RSP) ||
- ((pMsg->method == ATT_ERROR_RSP) &&
- (pMsg->msg.errorRsp.reqOpcode == ATT_WRITE_REQ)))
- {
- if(pMsg->method == ATT_ERROR_RSP)
- {
- uint8_t status = pMsg->msg.errorRsp.errCode;
-
- PRINT("Write Error: %x\n", status);
- }
- else
- {
- // Write success
- PRINT("Write success \n");
-
- }
-
- centralProcedureInProgress = FALSE;
- }
- else if(pMsg->method == ATT_HANDLE_VALUE_NOTI)
- {
- PRINT("Receive noti: %x\n", *pMsg->msg.handleValueNoti.pValue);
- }
- else if(centralDiscState != BLE_DISC_STATE_IDLE)
- {
- //centralGATTDiscoveryEvent(pMsg);
- }
-
- GATT_bm_free(&pMsg->msg, pMsg->method);
- }
对蓝牙主从连接以及服务特性发现流程稍微了解下后再来按着流程来理解软件上的流程基本都能很快用起来。
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。