This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

关于CC2541蓝牙从模块数据通信问题

Other Parts Discussed in Thread: CC2540

江湖救急:

   请问蓝牙CC2540从模块的数据接收函数simpleProfileChangeCB,默认一次接收一个字节数据,怎样设置一次性接收多个字节数据,谢谢。

  • hi:

       1、你设置成一个数组就可以了,像下面这样:

    {
    { ATT_BT_UUID_SIZE, characterUUID },
    GATT_PERMIT_READ,
    0,
    &userDefCharProps
    },

    // user defined Characteristic UUID
    {
    { ATT_UUID_SIZE, userDefUUID },
    GATT_PERMIT_READ|GATT_PERMIT_WRITE ,
    0,
    (uint8 *)&userDefVal 
    },

    2、希望可以帮到你,祝你早日解决问题,并分享一下解决问题的方法,谢谢!

  • HI:mark xu1

    很高兴能收到您的回复,关于您说的设置成一个数组,我这样处理不知行不行:

    1 特征值设置成一个数组:

    2,设置特征参数

     

    3读取特征值

    4 写入特征值

     

    5  读数据

     

    6  读数据子函数

     

    mark xu1  您好,以上就是我为读取多字节的数据所做的修改,用官方安卓APP给蓝牙从模块发送一个数据,蓝牙能收到,但发送多个字节数据时,APP显示 ERROR:13,不知这样修改正确与否,刚接触蓝牙不久,期待您的回复,谢谢

  • 大体看了一下,应该没什么问题,可以试一下

  • 好的,谢谢,用手机APP不行,只能发送一个自己,准备用central主模块试下

  • 另外,请取特征值的地方是不是应该这样写:

  • 你好,应该怎么写,不是很懂你的意思。

  • mark xu1:

    你好,还是不能解决,仍然只能收到一个字节,是不是哪里设置不正确呢?谢谢

  • 1、我profile配置如下所示:

    // 自定义的UUID的属性
    static uint8 testCharProps = (GATT_PROP_READ | GATT_PROP_WRITE);
    // 该数组一定要初始化
    static uint8 testVal[TEST_VAL_LEN] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

    // 自定义的UUID的属性
    static uint8 othersCharProps = (GATT_PROP_READ | GATT_PROP_WRITE);
    static uint8 othersVal=0;

    // User defined Service Atttribute Table
    static gattAttribute_t eCigAttrTbl[] =
    {
    // primary service
    {
    {ATT_BT_UUID_SIZE, primaryServiceUUID }, /* type */
    GATT_PERMIT_READ, /* permissions */
    0, /* handle */
    (uint8 *)&userDefService /* pValue */
    },

    //---------------------------test UUID-----------------------------------
    // Characteristic Declaration for test UUID
    {
    { ATT_BT_UUID_SIZE, characterUUID },
    GATT_PERMIT_READ,
    0,
    &testCharProps
    },

    // Characteristic Test UUID
    {
    { ATT_UUID_SIZE, setdevnameUUID },
    GATT_PERMIT_READ|GATT_PERMIT_WRITE ,
    0,
    (uint8 *)&testVal
    },

    //---------------------------others UUID-----------------------------------
    // Characteristic Declaration for test UUID
    {
    { ATT_BT_UUID_SIZE, characterUUID },
    GATT_PERMIT_READ,
    0,
    &othersCharProps
    },

    // Characteristic others UUID
    {
    { ATT_UUID_SIZE, othersUUID },
    GATT_PERMIT_READ|GATT_PERMIT_WRITE ,
    0,
    &testVal
    },


    };


    /*********************************************************************
    * LOCAL FUNCTIONS
    */
    static uint8 userDef_ReadAttrCB( uint16 connHandle, gattAttribute_t *pAttr,
    uint8 *pValue, uint8 *pLen, uint16 offset, uint8 maxLen );
    static bStatus_t userDef_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr,
    uint8 *pValue, uint8 len, uint16 offset );

    static void userDef_HandleConnStatusCB( uint16 connHandle, uint8 changeType );


    /*********************************************************************
    * PROFILE CALLBACKS
    */
    // User Service Callbacks
    CONST gattServiceCBs_t userDef_CBs =
    {
    userDef_ReadAttrCB, // Read callback function pointer
    userDef_WriteAttrCB, // Write callback function pointer
    NULL // Authorization callback function pointer
    };

    /*********************************************************************
    * PUBLIC FUNCTIONS
    */
    /*********************************************************************
    * @fn userDef_AddService
    *
    * @brief Initializes the Simple Key service by registering
    * GATT attributes with the GATT server.
    *
    * @param services - services to add. This is a bit map and can
    * contain more than one service.
    *
    * @return Success or Failure
    */
    bStatus_t eCig_AddService( uint32 services )
    {
    uint8 status = SUCCESS;

    // Initialize Client Characteristic Configuration attributes
    // 这一句可以不要,除非你想配置成notify等属性
    // GATTServApp_InitCharCfg( INVALID_CONNHANDLE, userKeyConfig );

    // Register with Link DB to receive link status change callback
    VOID linkDB_Register( userDef_HandleConnStatusCB );

    if( services & PP_ELE_CIG_SERVICE)
    {
    // Register attribute list and CBs with GATT Server App
    status = GATTServApp_RegisterService( userDefAttrTbl,
    GATT_NUM_ATTRS( userDefAttrTbl ),
    &userDef_CBs );
    }

    return ( status );
    }


    /*********************************************************************
    * @fn userDef_RegisterAppCBs
    *
    * @brief Register a callback function with the xx Service.
    *
    * @param pfnServiceCB - Callback function.
    *
    * @return None.
    */
    bStatus_t eCuserDef_RegisterAppCBs(CigCBs_t *pfnServiceCB)
    {
    if ( pfnServiceCB )
    {
    userDefServiceCB = pfnServiceCB;
    return ( SUCCESS );
    }
    else
    {
    return ( bleAlreadyInRequestedMode );
    }
    }


    /*********************************************************************
    * @fn userDef_SetParameter
    *
    * @brief Set a Eletronic cigarette Profile parameter.
    *
    * @param param - Profile parameter ID
    * @param len - length of data to write
    * @param pValue - pointer to data to write. This is dependent on
    * the parameter ID and WILL be cast to the appropriate
    * data type (example: data type of uint16 will be cast to
    * uint16 pointer).
    *
    * @return bStatus_t
    */
    bStatus_t userDef_SetParameter( uint8 param, uint8 len, void *pValue )
    {
    bStatus_t ret = SUCCESS;
    switch ( param )
    {
    case PP_TEST_UUID_ATTR:
    {
    osal_memset( testVal, 0, TEST_VAL_LEN); // 先把数组清零
    osal_memcpy(testVal, pValue, TEST_VAL_LEN); // 再把设置的值放进去
    }
    break;

    case PP_OTHERS_UUID_ATTR : // 设置单个数据的也举个例子吧
    {
    if ( len == sizeof ( uint8 ) )
    {
    othersVal = *((uint8*)pValue);
    }
    else
    {
    ret = bleInvalidRange;
    }
    }
    break;

    default :{ ret = INVALIDPARAMETER; }
    break;
    }

    return ( ret );
    }


    /*********************************************************************
    * @fn userDef_GetParameter
    *
    * @brief Get a userDef Profile parameter.
    *
    * @param param - Profile parameter ID
    * @param pValue - pointer to data to put. This is dependent on
    * the parameter ID and WILL be cast to the appropriate
    * data type (example: data type of uint16 will be cast to
    * uint16 pointer).
    *
    * @return bStatus_t
    */
    bStatus_t userDef_GetParameter( uint8 param, void *pValue )
    {
    bStatus_t ret = SUCCESS;
    switch ( param )
    {
    case PP_TEST_UUID_ATTR: // get test UUID value
    memcpy(pValue,testVal,sizeof(testVal));
    break;

    case PP_OTHERS_UUID_ATTR: // get others UUID vale
    *((uint8*)pValue) = othersVal;
    break;


    default:
    ret = INVALIDPARAMETER;
    break;
    }

    return ( ret );
    }


    /*********************************************************************
    * @fn userDef_ReadAttrCB
    *
    * @brief Read an attribute.
    *
    * @param connHandle - connection message was received on
    * @param pAttr - pointer to attribute
    * @param pValue - pointer to data to be read
    * @param pLen - length of data to be read
    * @param offset - offset of the first octet to be read
    * @param maxLen - maximum length of data to be read
    *
    * @return Success or Failure
    */
    static uint8 userDef_ReadAttrCB( uint16 connHandle, gattAttribute_t *pAttr,
    uint8 *pValue, uint8 *pLen, uint16 offset, uint8 maxLen )
    {
    bStatus_t status = SUCCESS;

    if ( pAttr->type.len == ATT_UUID_SIZE )
    {
    // 128-bit UUID
    // Convert the 128 bits uuid
    uint16 my_uuid = UUID128_CONVER(pAttr->type.uuid); // 这是我自定义的函数

    switch ( my_uuid )
    {
    case UUID_TEST:
    {
    // verify offset
    if (offset >= sizeof(testVal))
    {
    status = ATT_ERR_INVALID_OFFSET;
    }
    else
    {
    // determine read length
    *pLen = MIN(maxLen, (sizeof(testVal) - offset));

    // copy data
    memcpy(pValue, &testVal[offset], *pLen);
    }
    }
    break;

    case UUID_OTHERS:
    {
    // verify offset
    if (offset > 0)
    {
    status = ATT_ERR_INVALID_OFFSET;
    }
    else{
    *pLen = 1;
    pValue[0] = othersVal;
    }
    }
    break;
    default:
    {
    // Should never get here!
    *pLen = 0;
    status = ATT_ERR_ATTR_NOT_FOUND;
    }
    break;
    }
    }
    else
    {
    // 16-bit UUID
    *pLen = 0;
    status = SUCCESS;
    }

    return ( status );
    }


    /*********************************************************************
    * @fn userDef_WriteAttrCB
    *
    * @brief Validate attribute data prior to a write operation
    *
    * @param connHandle - connection message was received on
    * @param pAttr - pointer to attribute
    * @param pValue - pointer to data to be written
    * @param len - length of data
    * @param offset - offset of the first octet to be written
    * @param complete - whether this is the last packet
    * @param oper - whether to validate and/or write attribute value
    *
    * @return Success or Failure
    */

    static bStatus_t userDef_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr,
    uint8 *pValue, uint8 len, uint16 offset )
    {
    bStatus_t status = SUCCESS;
    if ( pAttr->type.len == ATT_UUID_SIZE )
    {
    // 128-bit UUID
    // Convert the 128 bits uuid
    uint16 my_uuid = UUID128_CONVER(pAttr->type.uuid); // 这是我自定义的函数

    switch ( my_uuid )
    {
    case UUID_TEST: // device name
    {
    // verify offset
    if (offset > 0)
    {
    status = ATT_ERR_INVALID_OFFSET;
    }
    else
    {
    // copy data
    uint8 i;
    for(i=0;i < TEST_VAL_LEN; i++)
    testVal[i] = 0;

    memcpy(testVal, pValue, MIN(len, TEST_VAL_LEN));
    }

    if ( userDefServiceCB )
    userDefServiceCB->pfnAttrChange(TEST_UUID_VAL_CHG); // 这一句一定要写,不然系统不知道更改了
    }
    break;
    case UUID_OTHERS: // set output power mode
    {
    // verify offset
    if (offset > 0)
    {
    status = ATT_ERR_INVALID_OFFSET;
    }
    else
    {
    othersVal = pValue[0];
    }

    if ( userDefServiceCB )
    {
    userDefServiceCB->pfnAttrChange(OTHERS_UUID_VAL_SET);
    }
    }
    break;

    default:
    // Should never get here!
    status = ATT_ERR_ATTR_NOT_FOUND;
    break;
    }
    }
    else
    {
    // 16-bit UUID
    uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);

    switch ( uuid )
    {
    case GATT_CLIENT_CHAR_CFG_UUID:
    status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len,
    offset, GATT_CLIENT_CFG_NOTIFY );
    /*callback ualertServiceCB()*/
    break;

    default:
    // Should never get here!
    status = ATT_ERR_ATTR_NOT_FOUND;
    break;
    }
    }
    return ( status );
    }

    /*********************************************************************
    * @fn userDef_HandleConnStatusCB
    *
    * @brief Profile link status change handler function.
    *
    * @param connHandle - connection handle
    * @param changeType - type of change
    *
    * @return none
    */

    static void userDef_HandleConnStatusCB( uint16 connHandle, uint8 changeType )
    {
    // Make sure this is not loopback connection
    if ( connHandle != LOOPBACK_CONNHANDLE )
    {
    // Reset Client Char Config if connection has dropped
    if ( ( changeType == LINKDB_STATUS_UPDATE_REMOVED ) ||
    ( ( changeType == LINKDB_STATUS_UPDATE_STATEFLAGS ) &&
    ( !linkDB_Up( connHandle ) ) ) )
    {
    GATTServApp_InitCharCfg( connHandle, XXConfig ); // 如果要设置成notify,则这样写,可以参看TI例程中按键及电池电量的写法
    // 这里就不详述了
    }
    }
    }

    2、附上附件,

        

    3、希望可以帮到你,祝你早日解决问题,并分享一下解决问题的方法,谢谢!(也可以加群:422240210)