BLE 协议栈之透传从机"Write error 13" 小忧伤

             从机接收主机来的数据并不像网上大部分博客说的那么简单,当然过程是很esay,如果只接收一个字节的数据而且不需要处理的话也很简单,但是涉及到多字节收发的时候,需要注意和处理的地方就很多了。我在调试透传功能时,由于没有合适的调试工具,只能引出串口看当前的数据,所以走了不少弯路,崩溃了近三天之后终于能稳定透传了。          

           在主机端配置好后,最大的疑惑莫过于当发送的字节数大于1时,主机直接返回的就是Write error 13 。开始以为是主机端有发送字节限制,但看遍代码仍旧没有找到字节限制的define。随后在从机里找错误信息,终于找到居然是从机接收有字节限制!!!定睛一看,simpleBLEperipheral例程给的代码里charac 1只能接收一个字节。OMG~~~~~~

         先说write error 13 ,其实是在simpleGATTprofile.csimpleProfile_WriteAttrCB函数中返回的。

 //Validate the value
        // Make sure it's not a blob oper
        if ( offset == 0 )
        {
          if ( len != 1 )
          { status = ATT_ERR_INVALID_VALUE_SIZE; }
        }
        else
        {
          status = ATT_ERR_ATTR_NOT_LONG;
        }

  Error 13 的定义#define ATT_ERR_INVALID_VALUE_SIZE  0x0d //!< The attribute value length is invalid for the operation 属性值的长度超了!!!

解决方法:

simpleGATTprofile.c中加入

#define SIMPLEPROFILE_CHAR1_LEN   20

static uint8 simpleProfileChar1[SIMPLEPROFILE_CHAR1_LEN] = {0};

2  static gattAttribute_t simpleProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED] 中改为:

 // Characteristic Value 1

      { 

        { ATT_BT_UUID_SIZE, simpleProfilechar1UUID },

        GATT_PERMIT_READ | GATT_PERMIT_WRITE, 

        0, 

        simpleProfileChar1

      },

3  替换下面的函数

1)

static bStatus_t simpleProfile_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset )

{
  bStatus_t status = SUCCESS;
  uint8 notifyApp = 0xFF;
  
  // If attribute permissions require authorization to write, return error
  if ( gattPermitAuthorWrite( pAttr->permissions ) )
  {
    // Insufficient authorization
    return ( ATT_ERR_INSUFFICIENT_AUTHOR );
  }
  
  if ( pAttr->type.len == ATT_BT_UUID_SIZE )
  {
    // 16-bit UUID
    uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);
    switch ( uuid )
    {
      case SIMPLEPROFILE_CHAR1_UUID:
      case SIMPLEPROFILE_CHAR3_UUID:

        //Validate the value
        // Make sure it's not a blob oper
        	/************************* 更改 ********************************/ 
        if ( offset == 0 )
        {
        	#if 0
			if ( len != SIMPLEPROFILE_CHAR1_LEN )  
			{				  						
				status = ATT_ERR_INVALID_VALUE_SIZE;
			}
			#else
			if ( len > SIMPLEPROFILE_CHAR1_LEN )  
			{				  					
				status = ATT_ERR_INVALID_VALUE_SIZE;
			}
			#endif
        }
        else
        {
          status = ATT_ERR_ATTR_NOT_LONG;
        }        
        //Write the value
        if ( status == SUCCESS )
        {        
          uint8 *pCurValue = (uint8 *)pAttr->pValue;
		  osal_memset(pCurValue,0,SIMPLEPROFILE_CHAR1_LEN);	
		  VOID osal_memcpy( pCurValue, pValue, len );
          if( pAttr->pValue == simpleProfileChar1 )		
          {
            notifyApp = SIMPLEPROFILE_CHAR1;     
          }
          else

          {
            notifyApp = SIMPLEPROFILE_CHAR3;
          }
        }
        break;
        /*************************** 更改结束 ***********************************/

      case GATT_CLIENT_CHAR_CFG_UUID:		
        status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len,
                                                 offset, GATT_CLIENT_CFG_NOTIFY );
        break;
        
      default:
        // Should never get here! (characteristics 2 and 4 do not have write permissions)
        status = ATT_ERR_ATTR_NOT_FOUND;
        break;
    }
  }
  else
  {
    // 128-bit UUID
    status = ATT_ERR_INVALID_HANDLE;
  }

  // If a charactersitic value changed then callback function to notify application of change
  if ( (notifyApp != 0xFF ) && simpleProfile_AppCBs && simpleProfile_AppCBs->pfnSimpleProfileChange )
  {
    simpleProfile_AppCBs->pfnSimpleProfileChange( notifyApp );  //调用回调函数 simpleProfileChangeCB()
  }
  
  return ( status );
}


2)

2)
bStatus_t SimpleProfile_GetParameter( uint8 param, void *value )
{
  bStatus_t ret = SUCCESS;
  switch ( param )
  {
    case SIMPLEPROFILE_CHAR1:

	   VOID osal_memcpy( value, simpleProfileChar1, SIMPLEPROFILE_CHAR1_LEN );  //simpleProfileChar1 是数组名

      break;

    case SIMPLEPROFILE_CHAR2:
      *((uint8*)value) = simpleProfileChar2;
      break;      

    case SIMPLEPROFILE_CHAR3:
      *((uint8*)value) = simpleProfileChar3;
      break;  
    case SIMPLEPROFILE_CHAR4:
      *((uint8*)value) = simpleProfileChar4;
      break;

    case SIMPLEPROFILE_CHAR5:
      VOID osal_memcpy( value, simpleProfileChar5, SIMPLEPROFILE_CHAR5_LEN );
      break;      
      
    default:
      ret = INVALIDPARAMETER;
      break;
  }  
  return ( ret );
}


通过上面操作,属性配置就算是完成了。这样进行接收的时候就不会出现错误了。

 

 

 

二,从机接收主机数据:

对于从机接收主机发来的数据同样需要在GATT层产生一个GATT ProFile Callback的调用,

// Simple GATT Profile Callbacks

static simpleProfileCBs_t simpleBLEPeripheral_SimpleProfileCBs =

{

  simpleProfileChangeCB    // Charactersitic value change callback

};  

它的注册是在// Register callback with SimpleGATTprofile   :  

VOID SimpleProfile_RegisterAppCBs( &simpleBLEPeripheral_SimpleProfileCBs )

操作设置步骤:

   在simpleProfileChangeCB里加入

uint8 newValueBuf[20]={0};
 case SIMPLEPROFILE_CHAR1:
    SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR1, newValueBuf );  	
       	    Uart0Send_String (newValueBuf, 20);
      break;

通过上面的设置即可接收到主机发送来的信息了 ,并且信息储存在了newValueBuf中


三,从机给主机发送数据:

从机给主机发数据:
使用GATT_Notification函数
void sbpSerialAppSendNoti(uint8 *pBuffer,uint16 length)
{
  uint8 len;
  if(length > 20)
    len = 20;
  else
    len = length;  
  static attHandleValueNoti_t pReport;
  pReport.handle=0x2E;
  pReport.len = len;
  osal_memcpy(pReport.value, pBuffer, len);
  GATT_Notification( 0, &pReport, FALSE );
}

开始觉得挺麻烦,写写博客其实也挺简单的,唉~~~~~


 

 


 

 

你可能感兴趣的:(BLE 协议栈之透传从机"Write error 13" 小忧伤)