当前位置:   article > 正文

沁恒蓝牙芯片CH58X蓝牙主机的使用_ch582主从服务

ch582主从服务

        在做的项目本身只是需要用到蓝牙从机就行,从机项目开发已基本要收尾了。考虑到要配合产线系统做自动化测试,因此需要一个配合从机的主机dongle供自动化测试系统使用。

        蓝牙主机的使用只要按主机和从机的通信流程来走的话各家的蓝牙软件流程基本差不多,都是围绕主机扫描----主机连接-----(主从交换mtu等phy参数)-------主机遍历从机的service------主机遍历所需要service下的char记录下需要char的handle值以及同时找出支持notify的char handler-----对支持notify/indicate的char进行使能-----------对所需要的char进行read write

代码上的大体流程主要如下

1、主机角色初始化,扫描连接及启动遍历service

  1. GAPRole_CentralInit();
  2. // Initialize GATT Client
  3. GATT_InitClient();
  4. //注册相关回调
  5. GAPRole_CentralStartDevice(centralTaskId, &centralBondCB, &centralRoleCB);
  6. 回调定义
  7. // GAP Role Callbacks
  8. static gapCentralRoleCB_t centralRoleCB = {
  9. centralRssiCB, // RSSI callback
  10. centralEventCB, // Event callback
  11. centralHciMTUChangeCB // MTU change callback
  12. };
  13. 和蓝牙通信连接相关的主要回调,扫描 连接等状态的切换主要都在该回调里
  14. static void centralEventCB(gapRoleEvent_t *pEvent)
  15. {
  16. switch(pEvent->gap.opcode)
  17. {
  18. case GAP_DEVICE_INIT_DONE_EVENT:
  19. {
  20. PRINT("Discovering...\n");
  21. GAPRole_CentralStartDiscovery(DEFAULT_DISCOVERY_MODE,
  22. DEFAULT_DISCOVERY_ACTIVE_SCAN,
  23. DEFAULT_DISCOVERY_WHITE_LIST);
  24. }
  25. break;
  26. case GAP_DEVICE_INFO_EVENT:
  27. {
  28. // Add device to list
  29. PRINT("Add device to list...\n");
  30. centralAddDeviceInfo(pEvent->deviceInfo.addr, pEvent->deviceInfo.addrType);
  31. }
  32. break;
  33. case GAP_DEVICE_DISCOVERY_EVENT:
  34. {
  35. uint8_t i;
  36. PRINT("centralScanRes:%d...\r\n",centralScanRes);
  37. // See if peer device has been discovered
  38. for(i = 0; i < centralScanRes; i++)
  39. {
  40. if(tmos_memcmp(PeerAddrDef, centralDevList[i].addr, B_ADDR_LEN))
  41. break;
  42. }
  43. // Peer device not found
  44. if(i == centralScanRes)
  45. {
  46. PRINT("Device not found...\n");
  47. centralScanRes = 0;
  48. GAPRole_CentralStartDiscovery(DEFAULT_DISCOVERY_MODE,
  49. DEFAULT_DISCOVERY_ACTIVE_SCAN,
  50. DEFAULT_DISCOVERY_WHITE_LIST);
  51. PRINT("Discovering...\n");
  52. }
  53. // Peer device found
  54. else
  55. {
  56. PRINT("Device found...\n");
  57. GAPRole_CentralEstablishLink(DEFAULT_LINK_HIGH_DUTY_CYCLE,
  58. DEFAULT_LINK_WHITE_LIST,
  59. centralDevList[i].addrType,
  60. centralDevList[i].addr);
  61. // Start establish link timeout event
  62. tmos_start_task(centralTaskId, ESTABLISH_LINK_TIMEOUT_EVT, ESTABLISH_LINK_TIMEOUT);
  63. PRINT("Connecting...\n");
  64. }
  65. }
  66. break;
  67. case GAP_LINK_ESTABLISHED_EVENT:
  68. {
  69. PRINT("GAP_LINK_ESTABLISHED_EVENT...\n");
  70. tmos_stop_task(centralTaskId, ESTABLISH_LINK_TIMEOUT_EVT);
  71. if(pEvent->gap.hdr.status == SUCCESS)
  72. {
  73. centralState = BLE_STATE_CONNECTED;
  74. centralConnHandle = pEvent->linkCmpl.connectionHandle;
  75. centralProcedureInProgress = TRUE;
  76. central_gattdiscover_start();//连接上后开始遍历serveice和char
  77. // Initiate service discovery
  78. tmos_start_task(centralTaskId, START_SVC_DISCOVERY_EVT, DEFAULT_SVC_DISCOVERY_DELAY);
  79. // See if initiate connect parameter update
  80. if(centralParamUpdate)
  81. {
  82. tmos_start_task(centralTaskId, START_PARAM_UPDATE_EVT, DEFAULT_PARAM_UPDATE_DELAY);
  83. }
  84. // See if initiate connect parameter update
  85. if(centralPhyUpdate)
  86. {
  87. tmos_start_task(centralTaskId, START_PHY_UPDATE_EVT, DEFAULT_PHY_UPDATE_DELAY);
  88. }
  89. // See if start RSSI polling
  90. if(centralRssi)
  91. {
  92. tmos_start_task(centralTaskId, START_READ_RSSI_EVT, DEFAULT_RSSI_PERIOD);
  93. }
  94. PRINT("Connected...\n");
  95. }
  96. else
  97. {
  98. PRINT("Connect Failed...Reason:%X\n", pEvent->gap.hdr.status);
  99. PRINT("Discovering...\n");
  100. centralScanRes = 0;
  101. GAPRole_CentralStartDiscovery(DEFAULT_DISCOVERY_MODE,
  102. DEFAULT_DISCOVERY_ACTIVE_SCAN,
  103. DEFAULT_DISCOVERY_WHITE_LIST);
  104. }
  105. }
  106. break;
  107. case GAP_LINK_TERMINATED_EVENT:
  108. {
  109. centralState = BLE_STATE_IDLE;
  110. centralConnHandle = GAP_CONNHANDLE_INIT;
  111. centralDiscState = BLE_DISC_STATE_IDLE;
  112. centralCharHdl = 0;
  113. centralScanRes = 0;
  114. centralProcedureInProgress = FALSE;
  115. tmos_stop_task(centralTaskId, START_READ_RSSI_EVT);
  116. PRINT("Disconnected...Reason:%x\n", pEvent->linkTerminate.reason);
  117. PRINT("Discovering...\n");
  118. GAPRole_CentralStartDiscovery(DEFAULT_DISCOVERY_MODE,
  119. DEFAULT_DISCOVERY_ACTIVE_SCAN,
  120. DEFAULT_DISCOVERY_WHITE_LIST);
  121. }
  122. break;
  123. case GAP_LINK_PARAM_UPDATE_EVENT:
  124. {
  125. PRINT("Param Update...\n");
  126. }
  127. break;
  128. case GAP_PHY_UPDATE_EVENT:
  129. {
  130. PRINT("PHY Update...\n");
  131. }
  132. break;
  133. case GAP_EXT_ADV_DEVICE_INFO_EVENT:
  134. {
  135. // Display device addr
  136. PRINT("AddrType:%d Recv ext adv - Addr %x %x %x %x %x %x \n", pEvent->deviceExtAdvInfo.addrType,pEvent->deviceExtAdvInfo.addr[0],
  137. pEvent->deviceExtAdvInfo.addr[1], pEvent->deviceExtAdvInfo.addr[2],
  138. pEvent->deviceExtAdvInfo.addr[3], pEvent->deviceExtAdvInfo.addr[4],
  139. pEvent->deviceExtAdvInfo.addr[5]);
  140. }
  141. break;
  142. case GAP_DIRECT_DEVICE_INFO_EVENT:
  143. {
  144. // Display device addr
  145. PRINT("AddrType:%d Recv direct adv - Addr %x %x %x %x %x %x \n", pEvent->deviceExtAdvInfo.addrType, pEvent->deviceExtAdvInfo.addr[0],
  146. pEvent->deviceExtAdvInfo.addr[1], pEvent->deviceExtAdvInfo.addr[2],
  147. pEvent->deviceExtAdvInfo.addr[3], pEvent->deviceExtAdvInfo.addr[4],
  148. pEvent->deviceExtAdvInfo.addr[5]);
  149. }
  150. break;
  151. default:
  152. break;
  153. }
  154. }

2、遍历service和char

  1. //遍历所有service
  2. GATT_DiscAllPrimaryServices(centralConnHandle,centralTaskId );
  3. 遍历完成会通过centralProcessGATTMsg传递系统消息SYS_EVENT_MSG给用户层进行解析
  4. //如下从系统消息里解析出来遍历到需要的service hander值
  5. if( ( pMsg->method == ATT_READ_BY_GRP_TYPE_RSP) &&
  6. ( pMsg->msg.readByGrpTypeRsp.numGrps > 0 ) )
  7. {
  8. for(unsigned char i = 0 ; i < pMsg->msg.readByGrpTypeRsp.numGrps;i++)
  9. {
  10. uint8_t *p_uuid = &(pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i + 4]);
  11. uint8_t uuid_length = pMsg->msg.readByGrpTypeRsp.len - 4;
  12. if(uuid_length == sizeof(TheFind_ServiceUUID)){
  13. if(tmos_memcmp(TheFind_ServiceUUID,p_uuid,uuid_length)) {
  14. centralSvcStartHdl = BUILD_UINT16( pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i], \
  15. pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i + 1]);
  16. centralSvcEndHdl = BUILD_UINT16( pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i+2], \
  17. pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i + 3]);
  18. }
  19. }
  20. }
  21. }

找到service后开始遍历char

  1. //遍历所有char找到自己要用的char handler值
  2. GATT_DiscAllChars(centralConnHandle,centralSvcStartHdl,centralSvcEndHdl,centralTaskId);
  3. //同样也是通过系统消息传递遍历后的结果
  4. if ( pMsg->method == ATT_READ_BY_TYPE_RSP ){
  5. if(pMsg->msg.readByTypeRsp.numPairs > 0 ){
  6. for(unsigned char i = 0; i < pMsg->msg.readByTypeRsp.numPairs ; i++){
  7. uint16_t char_value_handle = BUILD_UINT16(pMsg->msg.readByTypeRsp.pDataList[pMsg->msg.readByTypeRsp.len * i+3], \
  8. pMsg->msg.readByTypeRsp.pDataList[pMsg->msg.readByTypeRsp.len * i + 4]);
  9. //characteristic uuid length
  10. uint8_t char_uuid_length = pMsg->msg.readByGrpTypeRsp.len - 5;
  11. //uuid
  12. uint8_t *chat_uuid = &(pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i + 5]);
  13. if(sizeof(TheFind_CharUUID) == char_uuid_length){
  14. if(tmos_memcmp(TheFind_CharUUID,chat_uuid,char_uuid_length)){
  15. TheFind_CharUUID = char_value_handle;
  16. }
  17. }
  18. }
  19. }
  20. }

3、遍历支持notify的char handler

  1. req.startHandle = centralSvcStartHdl;
  2. req.endHandle = centralSvcEndHdl;
  3. req.type.len = ATT_BT_UUID_SIZE;
  4. req.type.uuid[0] = LO_UINT16(GATT_CLIENT_CHAR_CFG_UUID);
  5. req.type.uuid[1] = HI_UINT16(GATT_CLIENT_CHAR_CFG_UUID);
  6. GATT_ReadUsingCharUUID( centralConnHandle, &req, centralTaskId );

4、读写char

  1. void WriteCharHandler(uint8_t* data,uint8_t datalen,uint16_t Handler)
  2. {
  3. attWriteReq_t req;
  4. req.cmd = FALSE;
  5. req.sig = FALSE;
  6. req.handle = Handler;
  7. req.len = datalen;
  8. req.pValue = GATT_bm_alloc(centralConnHandle, ATT_WRITE_REQ, req.len, NULL, 0);
  9. if(req.pValue != NULL)
  10. {
  11. tmos_memcpy(req.pValue,data,datalen);
  12. if(GATT_WriteCharValue(centralConnHandle, &req, centralTaskId) == SUCCESS)
  13. {
  14. centralDoWrite = FALSE;
  15. }
  16. else
  17. {
  18. GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
  19. }
  20. }
  21. }
  22. void ReadCharHandler(uint16_t handle)
  23. {
  24. attReadReq_t req;
  25. req.handle = handle;
  26. GATT_ReadCharValue(centralConnHandle, &req, centralTaskId);
  27. }

5、接收notify以及read响应

  1. //接收读写回应以及notify indicate都是通过系统消息进来给用户
  2. static void centralProcessGATTMsg(gattMsgEvent_t *pMsg)
  3. {
  4. if(centralState != BLE_STATE_CONNECTED)
  5. {
  6. // In case a GATT message came after a connection has dropped,
  7. // ignore the message
  8. GATT_bm_free(&pMsg->msg, pMsg->method);
  9. return;
  10. }
  11. if((pMsg->method == ATT_EXCHANGE_MTU_RSP) ||
  12. ((pMsg->method == ATT_ERROR_RSP) &&
  13. (pMsg->msg.errorRsp.reqOpcode == ATT_EXCHANGE_MTU_REQ)))
  14. {
  15. if(pMsg->method == ATT_ERROR_RSP)
  16. {
  17. uint8_t status = pMsg->msg.errorRsp.errCode;
  18. PRINT("Exchange MTU Error: %x\n", status);
  19. }
  20. centralProcedureInProgress = FALSE;
  21. }
  22. if(pMsg->method == ATT_MTU_UPDATED_EVENT)
  23. {
  24. PRINT("MTU: %x\n", pMsg->msg.mtuEvt.MTU);
  25. }
  26. if((pMsg->method == ATT_READ_RSP) ||
  27. ((pMsg->method == ATT_ERROR_RSP) &&
  28. (pMsg->msg.errorRsp.reqOpcode == ATT_READ_REQ)))
  29. {
  30. if(pMsg->method == ATT_ERROR_RSP)
  31. {
  32. uint8_t status = pMsg->msg.errorRsp.errCode;
  33. PRINT("Read Error: %x\n", status);
  34. }
  35. else
  36. {
  37. // After a successful read, display the read value
  38. PRINT("Read rsp: %x\n", *pMsg->msg.readRsp.pValue);
  39. }
  40. centralProcedureInProgress = FALSE;
  41. }
  42. else if((pMsg->method == ATT_WRITE_RSP) ||
  43. ((pMsg->method == ATT_ERROR_RSP) &&
  44. (pMsg->msg.errorRsp.reqOpcode == ATT_WRITE_REQ)))
  45. {
  46. if(pMsg->method == ATT_ERROR_RSP)
  47. {
  48. uint8_t status = pMsg->msg.errorRsp.errCode;
  49. PRINT("Write Error: %x\n", status);
  50. }
  51. else
  52. {
  53. // Write success
  54. PRINT("Write success \n");
  55. }
  56. centralProcedureInProgress = FALSE;
  57. }
  58. else if(pMsg->method == ATT_HANDLE_VALUE_NOTI)
  59. {
  60. PRINT("Receive noti: %x\n", *pMsg->msg.handleValueNoti.pValue);
  61. }
  62. else if(centralDiscState != BLE_DISC_STATE_IDLE)
  63. {
  64. //centralGATTDiscoveryEvent(pMsg);
  65. }
  66. GATT_bm_free(&pMsg->msg, pMsg->method);
  67. }

对蓝牙主从连接以及服务特性发现流程稍微了解下后再来按着流程来理解软件上的流程基本都能很快用起来。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/933191
推荐阅读
相关标签
  

闽ICP备14008679号