蓝牙协议栈主从机之间发送数据

桃扇骨 2022-06-11 03:53 536阅读 0赞
  1. 蓝牙协议栈主从机之间发送数据,先讲主机给从机发送数据。然后是从机给主机发送数据。
  2. 1.Initialize GATT attributes (初始化GATT属性表)
  3. SimpleProfile_AddService( GATT_ALL_SERVICES ); // Simple GATT Profile
  4. ---->
  5. 2.注册属性列表 and 回调函数 simpleProfileCBs 这是GATT Server App干的事。
  6. // Register GATT attribute list and CBs with GATT Server App
  7. status = GATTServApp_RegisterService( simpleProfileAttrTbl,
  8. GATT_NUM_ATTRS( simpleProfileAttrTbl ),
  9. &simpleProfileCBs );
  10. ---->
  11. 3.属性表simpleProfileAttrTbl,根据自己需要自己添加需要的UUID,及修改具体项的值。
  12. ---->
  13. 4.simpleProfileCBs
  14. // Simple Profile Service Callbacks
  15. CONST gattServiceCBs_t simpleProfileCBs =
  16. {
  17. simpleProfile_ReadAttrCB, // Read callback function pointer
  18. simpleProfile_WriteAttrCB, // Write callback function pointer
  19. NULL // Authorization callback function pointer
  20. };
  21. ---->
  22. 5.simpleProfile_WriteAttrCB,主机给从机发送数据,会进入这个函数。通过不同的特征值通道发送数据,会进入switch下,不同的uuid,做不同处理。
  23. 特别注意的是:GATT_CLIENT_CHAR_CFG_UUID。当从机给主机发送数据之前,要先打开通知,而这个GATT_CLIENT_CHAR_CFG_UUID,就是主机打开通知进入的通道。
  24. ble tool软件,有一个选择要通知/读的。。按钮,一单击这个按钮,主机就会给从机发送,打开通知的数据,就会进入GATT_CLIENT_CHAR_CFG_UUID
  25. simpleProfile_WriteAttrCB函数里面,最后一段代码,是通知APPpfnSimpleProfileChange,某个uuid通道有值过来了。
  26. // If a charactersitic value changed then callback function to notify application of change
  27. if ( (notifyApp != 0xFF ) && simpleProfile_AppCBs && simpleProfile_AppCBs->pfnSimpleProfileChange )
  28. {
  29. simpleProfile_AppCBs->pfnSimpleProfileChange( notifyApp );
  30. }
  31. {
  32. // If attribute permissions require authorization to write, return error
  33. if ( gattPermitAuthorWrite( pAttr->permissions ) )
  34. {
  35. // Insufficient authorization
  36. return ( ATT_ERR_INSUFFICIENT_AUTHOR );
  37. }
  38. if ( pAttr->type.len == ATT_BT_UUID_SIZE )
  39. {
  40. // 16-bit UUID
  41. uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);
  42. switch ( uuid )
  43. {
  44. case SIMPLEPROFILE_CHAR1_UUID:
  45. ...
  46. break;
  47. case SIMPLEPROFILE_CHAR2_UUID:
  48. ...
  49. break;
  50. case SIMPLEPROFILE_CHAR3_UUID:
  51. ...
  52. break;
  53. case SIMPLEPROFILE_CHAR4_UUID:
  54. ...
  55. break;
  56. case SIMPLEPROFILE_CHAR5_UUID:
  57. ...
  58. break;
  59. case SIMPLEPROFILE_CHAR6_UUID:
  60. ...
  61. break;
  62. case GATT_CLIENT_CHAR_CFG_UUID:
  63. {
  64. //status = ATT_ERR_INVALID_HANDLE;
  65. status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len,
  66. offset, GATT_CLIENT_CFG_NOTIFY );
  67. }
  68. break;
  69. default:
  70. // Should never get here! (characteristics 2 and 4 do not have write permissions)
  71. status = ATT_ERR_ATTR_NOT_FOUND;
  72. break;
  73. }
  74. }
  75. else
  76. {
  77. // 128-bit UUID
  78. status = ATT_ERR_INVALID_HANDLE;
  79. }
  80. // If a charactersitic value changed then callback function to notify application of change
  81. if ( (notifyApp != 0xFF ) && simpleProfile_AppCBs && simpleProfile_AppCBs->pfnSimpleProfileChange )
  82. {
  83. simpleProfile_AppCBs->pfnSimpleProfileChange( notifyApp );
  84. }
  85. }
  86. ---->
  87. 6.simpleProfileChangeCB,就是上面的回调函数,看这个函数的代码。
  88. 上层(APP层)收到数据后的操作,是把接受到的数据再发送回去,即从机接受到主机发送过来的数据,再把数据,发送给主机。
  89. 我们知道从机发送给主机的函数调用的是GATT_Notification()。这个函数GUA_SimpleGATTprofile_Char6_Notify(nGUA_ConnHandle, nbGUA_Char6, 20);是经过封装过的。它里面有函数GATT_Notification()。
  90. static void simpleProfileChangeCB( uint8 paramID )
  91. {
  92. uint8 newValue;
  93. uint16 nGUA_ConnHandle;
  94. uint8 nbGUA_Char6[20] = {0};
  95. switch( paramID )
  96. {
  97. case SIMPLEPROFILE_CHAR1:
  98. SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR1, &newValue );
  99. //获取连接句柄
  100. GAPRole_GetParameter(GAPROLE_CONNHANDLE, &nGUA_ConnHandle);
  101. //读取char6的数值
  102. SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR1, &newValue);
  103. //发送数据
  104. GUA_SimpleGATTprofile_Char1_Notify(nGUA_ConnHandle, &newValue, 1);
  105. #if (defined HAL_LCD) && (HAL_LCD == TRUE)
  106. HalLcdWriteStringValue( "Char 1:", (uint16)(newValue), 10, HAL_LCD_LINE_3 );
  107. #endif // (defined HAL_LCD) && (HAL_LCD == TRUE)
  108. break;
  109. case SIMPLEPROFILE_CHAR3:
  110. SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR3, &newValue );
  111. #if (defined HAL_LCD) && (HAL_LCD == TRUE)
  112. HalLcdWriteStringValue( "Char 3:", (uint16)(newValue), 10, HAL_LCD_LINE_3 );
  113. #endif // (defined HAL_LCD) && (HAL_LCD == TRUE)
  114. break;
  115. //char6
  116. case SIMPLEPROFILE_CHAR6:
  117. {
  118. //获取连接句柄
  119. GAPRole_GetParameter(GAPROLE_CONNHANDLE, &nGUA_ConnHandle);
  120. //读取char6的数值
  121. SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR6, &nbGUA_Char6);
  122. //发送数据
  123. GUA_SimpleGATTprofile_Char6_Notify(nGUA_ConnHandle, nbGUA_Char6, 20);
  124. break;
  125. }
  126. default:
  127. // should not reach here!
  128. break;
  129. }
  130. }
  131. --->
  132. --->
  133. 总结:
  134. 主机给从机发送数据,调用的是函数simpleProfile_WriteAttrCB(),从机给主机发送数据,调用的是函数GATT_Notification()。当然从机在给主机发送数据的时候,要填充数据。GUA_SimpleGATTprofile_Char6_Notify()实现过程如下:
  135. void GUA_SimpleGATTprofile_Char6_Notify(uint16 nGUA_ConnHandle, uint8 *pGUA_Value, uint8 nGUA_Len)
  136. {
  137. attHandleValueNoti_t stGUA_Noti;
  138. uint16 nGUA_Return;
  139. //读出CCC的值
  140. nGUA_Return = GATTServApp_ReadCharCfg(nGUA_ConnHandle, simpleProfileChar6Config);
  141. //判断是否打开通知开关,打开了则发送数据
  142. if (nGUA_Return & GATT_CLIENT_CFG_NOTIFY)
  143. {
  144. //填充数据
  145. stGUA_Noti.handle = simpleProfileAttrTbl[20].handle;
  146. aa_tmp = simpleProfileAttrTbl[20].handle;
  147. stGUA_Noti.len = nGUA_Len;
  148. osal_memcpy(stGUA_Noti.value, pGUA_Value, nGUA_Len);
  149. //发送数据
  150. GATT_Notification(nGUA_ConnHandle, &stGUA_Noti, FALSE);
  151. }
  152. }

发表评论

表情:
评论列表 (有 0 条评论,536人围观)

还没有评论,来说两句吧...

相关阅读