打印
[蓝牙芯片]

CH577F-BLE Notihy

[复制链接]
3541|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
一、前言

最近玩了一下CH577的蓝牙,这里记录一下

二、准备

使用CH的EVT,从机用 BLE\Peripheral ,主机用 BLE\Central,注意使用官网最新的,因为一直有进行更新,我前段时间拿的,使能notify是没有对应的参考的。



使用特权

评论回复
沙发
木木guainv|  楼主 | 2021-9-6 15:05 | 只看该作者
三、程序
1、主机
对于主机,需要修改下面这些部分

MAC地址,注意这里的MAC和从机要相反!
// Peer device address
static uint8 PeerAddrDef[B_ADDR_LEN] = { 0x02,0x02,0x03,0xE4,0xC2,0x84 };


对于广播数据,MAC的发现,在下面函数中实现
/*********************************************************************
5. @fn      centralEventCB
6.  7. @brief   Central event callback function.
7.  9. @param   pEvent - pointer to event structure
8.  11. @return  none
*/
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
        centralAddDeviceInfo( pEvent->deviceInfo.addr, pEvent->deviceInfo.addrType );        
      }
      break;

      case GAP_DEVICE_DISCOVERY_EVENT:
      {
        uint8 i;        

        // See if peer device has been discovered
        for ( i = 0; i < centralScanRes; i++ )
        {
          if ( tmos_memcmp( PeerAddrDef, centralDevList.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.addrType,
                                        centralDevList.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:
      {
        tmos_stop_task( centralTaskId, ESTABLISH_LINK_TIMEOUT_EVT );
        if ( pEvent->gap.hdr.status == SUCCESS )
        {
          centralState = BLE_STATE_CONNECTED;
          centralConnHandle = pEvent->linkCmpl.connectionHandle;
          centralProcedureInProgress = TRUE;            

          // 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 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;

    default:
      break;
  }
}


使用特权

评论回复
板凳
木木guainv|  楼主 | 2021-9-6 15:06 | 只看该作者
对于GATT服务发现,在下面中完成,其实这里就是采用 GATT_ReadUsingCharUUID 来找特征的句柄 需要指定一下开头和结尾的HDL

需要注意:
(1). 若要发现多个服务,则要多建几个 centralDiscState 状态,在 pMsg->msg.readByTypeRsp.numPairs = 0时再切下一个状态
(2). 若要打开多个notify,需要调用多次 GATT_WriteCharValue ,这里必须采用任务来打开,不能马上打开,否则不生效,另外调用这些蓝牙的操作,不能在相同时间内操作多个,否则前面的也不生效
(3). 注意采用 GATT_ReadUsingCharUUID 方法(UUID已知)来发现特征值,得到的HDL,是特征值 数值的HDL
(4). 在采用 GATT_CLIENT_CHAR_CFG_UUID 这个UUID来获取CCC的时候,每读取完一个,需要 将当前的CCC的HDL+1作为 req.startHandle 来发现下一个CCC的HDL

/*********************************************************************
* @fn      centralGATTDiscoveryEvent
*
* @brief   Process GATT discovery event
*
* @return  none
*/
static void centralGATTDiscoveryEvent( gattMsgEvent_t *pMsg )
{
  attReadByTypeReq_t req;

  if ( centralDiscState == BLE_DISC_STATE_SVC )
  {
    // Service found, store handles
    if ( pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP &&
         pMsg->msg.findByTypeValueRsp.numInfo > 0 )
    {
      centralSvcStartHdl = ATT_ATTR_HANDLE(pMsg->msg.findByTypeValueRsp.pHandlesInfo,0);
      centralSvcEndHdl = ATT_GRP_END_HANDLE(pMsg->msg.findByTypeValueRsp.pHandlesInfo,0);

      // Display Profile Service handle range
      PRINT("Found Profile Service handle : %x ~ %x \n",centralSvcStartHdl,centralSvcEndHdl);

    }
    // If procedure complete
    if ( ( pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP  &&
           pMsg->hdr.status == bleProcedureComplete ) ||
         ( pMsg->method == ATT_ERROR_RSP ) )
    {
      if ( centralSvcStartHdl != 0 )
      {
        // Discover characteristic
        centralDiscState = BLE_DISC_STATE_CHAR;
        req.startHandle = centralSvcStartHdl;
        req.endHandle = centralSvcEndHdl;
        req.type.len = ATT_BT_UUID_SIZE;
        req.type.uuid[0] = LO_UINT16(SIMPLEPROFILE_CHAR1_UUID);
        req.type.uuid[1] = HI_UINT16(SIMPLEPROFILE_CHAR1_UUID);

        GATT_ReadUsingCharUUID( centralConnHandle, &req, centralTaskId );
      }
    }
  }
  else if ( centralDiscState == BLE_DISC_STATE_CHAR )
  {
    // Characteristic found, store handle
    if ( pMsg->method == ATT_READ_BY_TYPE_RSP &&
         pMsg->msg.readByTypeRsp.numPairs > 0 )
    {
      centralCharHdl = BUILD_UINT16( pMsg->msg.readByTypeRsp.pDataList[0],
                                       pMsg->msg.readByTypeRsp.pDataList[1] );

      // Start do read or write
      tmos_start_task( centralTaskId, START_READ_OR_WRITE_EVT, DEFAULT_READ_OR_WRITE_DELAY);

      // Display Characteristic 1 handle
      PRINT("Found Characteristic 1 handle : %x \n",centralCharHdl);      
    }
    if ( ( pMsg->method == ATT_READ_BY_TYPE_RSP  &&
           pMsg->hdr.status == bleProcedureComplete ) ||
         ( pMsg->method == ATT_ERROR_RSP ) )
                {
                        // Discover characteristic
                        centralDiscState = BLE_DISC_STATE_CCCD;
                        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 );
                }
  }   
  else if ( centralDiscState == BLE_DISC_STATE_CCCD )
  {
    // Characteristic found, store handle
    if ( pMsg->method == ATT_READ_BY_TYPE_RSP &&
         pMsg->msg.readByTypeRsp.numPairs > 0 )
    {
      centralCCCDHdl = BUILD_UINT16( pMsg->msg.readByTypeRsp.pDataList[0],
                                       pMsg->msg.readByTypeRsp.pDataList[1] );
      centralProcedureInProgress = FALSE;

      // Start do write CCCD
      tmos_start_task( centralTaskId, START_WRITE_CCCD_EVT, DEFAULT_WRITE_CCCD_DELAY);

      // Display Characteristic 1 handle
      PRINT("Found client characteristic configuration handle : %x \n",centralCCCDHdl);      

    }
    else
    {
        // Discover characteristic
        centralDiscState = BLE_DISC_STATE_CCCD;
        req.startHandle = centralCCCDHdl+1;//偏移来找....不然找到还是第一个....
        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 );
        centralDiscState = BLE_DISC_STATE_CCCD2;
    }

  }
  else if ( centralDiscState == BLE_DISC_STATE_CCCD2 )
  {
    // Characteristic found, store handle
    if ( pMsg->method == ATT_READ_BY_TYPE_RSP &&
         pMsg->msg.readByTypeRsp.numPairs > 0 )
    {
      centralCCCDHd2 = BUILD_UINT16( pMsg->msg.readByTypeRsp.pDataList[0],
                                       pMsg->msg.readByTypeRsp.pDataList[1] );
      centralProcedureInProgress = FALSE;

      // Start do write CCCD
      tmos_start_task( centralTaskId, START_WRITE_CCCD2_EVT, DEFAULT_WRITE_CCCD_DELAY);//注意换一个EVT。。上面第一个EVT 1600个时基后才写

      // Display Characteristic 1 handle
      PRINT("Found client characteristic configuration handle : %x \n",centralCCCDHd2);      

    }
    centralDiscState = BLE_DISC_STATE_IDLE;
  }

}


使用特权

评论回复
地板
木木guainv|  楼主 | 2021-9-6 15:07 | 只看该作者
对于用户定义的任务,在下面实现

/*********************************************************************
1. @fn      Central_ProcessEvent
2.  3. @brief   Central Application Task event processor.  This function
3.          is called to process all events for the task.  Events
4.          include timers, messages and any other user defined events.
5.  7. @param   task_id  - The TMOS assigned task ID.
6. @param   events - events to process.  This is a bit map and can
7.                   contain more than one event.
8.  11. @return  events not processed
*/
uint16 Central_ProcessEvent( uint8 task_id, uint16 events )
{
  if ( events & SYS_EVENT_MSG )
  {
    uint8 *pMsg;

    if ( (pMsg = tmos_msg_receive( centralTaskId )) != NULL )
    {
      central_ProcessTMOSMsg( (tmos_event_hdr_t *)pMsg );
      // Release the TMOS message
       tmos_msg_deallocate( pMsg );
    }
    // return unprocessed events
    return (events ^ SYS_EVENT_MSG);
  }

  if ( events & START_DEVICE_EVT )
  {
    // Start the Device
    GAPRole_CentralStartDevice( centralTaskId, &centralBondCB, &centralRoleCB );
    return ( events ^ START_DEVICE_EVT );
  }
       
  if ( events & ESTABLISH_LINK_TIMEOUT_EVT )
  {
                GAPRole_TerminateLink( INVALID_CONNHANDLE );
    return ( events ^ ESTABLISH_LINK_TIMEOUT_EVT );
  }

  if ( events & START_SVC_DISCOVERY_EVT )
  {
    // start service discovery
    centralStartDiscovery( );
    return ( events ^ START_SVC_DISCOVERY_EVT );
  }

  if ( events & START_PARAM_UPDATE_EVT )
  {
    // start connect parameter update
    GAPRole_UpdateLink( centralConnHandle,
                           DEFAULT_UPDATE_MIN_CONN_INTERVAL,
                           DEFAULT_UPDATE_MAX_CONN_INTERVAL,
                           DEFAULT_UPDATE_SLAVE_LATENCY,
                           DEFAULT_UPDATE_CONN_TIMEOUT );
    return ( events ^ START_PARAM_UPDATE_EVT );
  }

  if ( events & START_READ_OR_WRITE_EVT )
  {   
    if( centralProcedureInProgress == FALSE )
    {
      if( centralDoWrite )
      {
        // Do a write
        attWriteReq_t req;

        req.cmd = FALSE;
        req.sig = FALSE;
        req.handle = centralCharHdl;
        req.len = 1;
        req.pValue = GATT_bm_alloc(centralConnHandle,ATT_WRITE_REQ,req.len,NULL,0);
        if ( req.pValue != NULL )
        {
          *req.pValue = centralCharVal;

          if( GATT_WriteCharValue(centralConnHandle,&req,centralTaskId) == SUCCESS )
          {      
            centralProcedureInProgress = TRUE;
            centralDoWrite = !centralDoWrite;
            tmos_start_task( centralTaskId, START_READ_OR_WRITE_EVT, DEFAULT_READ_OR_WRITE_DELAY);
          }
          else
          {
            GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
          }
        }  
      }
      else
      {
        // Do a read
        attReadReq_t req;  

        req.handle = centralCharHdl;        
        if( GATT_ReadCharValue( centralConnHandle, &req, centralTaskId ) == SUCCESS )
        {
          centralProcedureInProgress = TRUE;
          centralDoWrite = !centralDoWrite;
        }
      }
    }
    return ( events ^ START_READ_OR_WRITE_EVT );
  }

  if ( events & START_WRITE_CCCD_EVT )
  {   
    if( centralProcedureInProgress == FALSE )
    {
                        // Do a write
                        attWriteReq_t req;
                       
                        req.cmd = FALSE;
                        req.sig = FALSE;
                        req.handle = centralCCCDHdl;
                        req.len = 2;
                        req.pValue = GATT_bm_alloc(centralConnHandle,ATT_WRITE_REQ,req.len,NULL,0);
                        if ( req.pValue != NULL )
                        {
                                req.pValue[0] = 1;
                                req.pValue[1] = 0;
                               
                                if( GATT_WriteCharValue(centralConnHandle,&req,centralTaskId) == SUCCESS )
                                {      
                                        centralProcedureInProgress = TRUE;
                                }
                                else
                                {
                                        GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
                                }
      }
    }
    return ( events ^ START_WRITE_CCCD_EVT );
  }

  if ( events & START_WRITE_CCCD2_EVT )
  {   
    if( centralProcedureInProgress == FALSE )
    {
                        // Do a write
                        attWriteReq_t req;
                       
                        req.cmd = FALSE;
                        req.sig = FALSE;
                        req.handle = centralCCCDHd2;//用第二个hdl。。
                        req.len = 2;
                        req.pValue = GATT_bm_alloc(centralConnHandle,ATT_WRITE_REQ,req.len,NULL,0);
                        if ( req.pValue != NULL )
                        {
                                req.pValue[0] = 1;
                                req.pValue[1] = 0;
                               
                                if( GATT_WriteCharValue(centralConnHandle,&req,centralTaskId) == SUCCESS )
                                {      
                                        centralProcedureInProgress = TRUE;
                                }
                                else
                                {
                                        GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
                                }
      }
    }
    return ( events ^ START_WRITE_CCCD2_EVT );
  }

  if ( events & START_READ_RSSI_EVT )
  {
    GAPRole_ReadRssiCmd(centralConnHandle);
    tmos_start_task( centralTaskId, START_READ_RSSI_EVT, DEFAULT_RSSI_PERIOD );      
    return (events ^ START_READ_RSSI_EVT);
  }

  // Discard unknown events
  return 0;
}


使用特权

评论回复
5
木木guainv|  楼主 | 2021-9-6 15:08 | 只看该作者
GATT的写入读取NOTIFY
这里可以将handle打出来
/*********************************************************************
10. @fn      centralProcessGATTMsg
11.  12. @brief   Process GATT messages
13.  14. @return  none
*/
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
    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 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 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 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 hdl %x noti: %x\n",pMsg->msg.handleValueNoti.handle,*pMsg->msg.handleValueNoti.pValue);
        }
  else if ( centralDiscState != BLE_DISC_STATE_IDLE )
  {
    centralGATTDiscoveryEvent( pMsg );
  }
  GATT_bm_free(&pMsg->msg, pMsg->method);
}


使用特权

评论回复
6
木木guainv|  楼主 | 2021-9-6 15:09 | 只看该作者
2、从机
为了做测试,将CHAR1增加一个NOTIFY属性,CHAR4就已经是notify属性的,按照CHAR4来修改来一下CHAR1
可以参考 CHAR4的配置,来对应改动即可

需要修改下面这些地方

MAC地址,注意这里的MAC和主机要相反!
打开 BLE_MAC 宏
```c
/*********************************************************************
* GLOBAL TYPEDEFS
*/
__align(4) u32 MEM_BUF[BLE_MEMHEAP_SIZE/4];

#if (defined (BLE_MAC)) && (BLE_MAC == TRUE)
u8C MacAddr[6] = {0x84,0xC2,0xE4,0x03,0x02,0x02};
#endif
```



需要NOTIFY的特征值(CHAR1,4)的特征值偏移,用于发送数据时用
在ATT表中 从 0 开始数即可

// Position of simpleProfilechar4 value in attribute array
#define SIMPLEPROFILE_CHAR1_VALUE_POS            2
#define SIMPLEPROFILE_CHAR4_VALUE_POS            12



ATT表增加特征配置项
/*********************************************************************
* Profile Attributes - Table
*/

static gattAttribute_t simpleProfileAttrTbl[] =
{
  // Simple Profile Service
  {
    { ATT_BT_UUID_SIZE, primaryServiceUUID }, /* type */
    GATT_PERMIT_READ,                         /* permissions */
    0,                                        /* handle */
    (uint8 *)&simpleProfileService            /* pValue */
  },

    // Characteristic 1 Declaration
    {
      { ATT_BT_UUID_SIZE, characterUUID },
      GATT_PERMIT_READ,
      0,
      &simpleProfileChar1Props
    },

      // Characteristic Value 1
      {
        { ATT_BT_UUID_SIZE, simpleProfilechar1UUID },
        GATT_PERMIT_READ | GATT_PERMIT_WRITE,
        0,
        simpleProfileChar1
      },

      // Characteristic 1 configuration  我增加的
      {
        { ATT_BT_UUID_SIZE, clientCharCfgUUID },
        GATT_PERMIT_READ | GATT_PERMIT_WRITE,
        0,
        (uint8 *)simpleProfileChar1Config
      },

      // Characteristic 1 User Description
      {
        { ATT_BT_UUID_SIZE, charUserDescUUID },
        GATT_PERMIT_READ,
        0,
        simpleProfileChar1UserDesp
      },      

    // Characteristic 2 Declaration
    {
      { ATT_BT_UUID_SIZE, characterUUID },
      GATT_PERMIT_READ,
      0,
      &simpleProfileChar2Props
    },

      // Characteristic Value 2
      {
        { ATT_BT_UUID_SIZE, simpleProfilechar2UUID },
        GATT_PERMIT_READ,
        0,
        simpleProfileChar2
      },

      // Characteristic 2 User Description
      {
        { ATT_BT_UUID_SIZE, charUserDescUUID },
        GATT_PERMIT_READ,
        0,
        simpleProfileChar2UserDesp
      },           

    // Characteristic 3 Declaration
    {
      { ATT_BT_UUID_SIZE, characterUUID },
      GATT_PERMIT_READ,
      0,
      &simpleProfileChar3Props
    },

      // Characteristic Value 3
      {
        { ATT_BT_UUID_SIZE, simpleProfilechar3UUID },
        GATT_PERMIT_WRITE,
        0,
        simpleProfileChar3
      },

      // Characteristic 3 User Description
      {
        { ATT_BT_UUID_SIZE, charUserDescUUID },
        GATT_PERMIT_READ,
        0,
        simpleProfileChar3UserDesp
      },

    // Characteristic 4 Declaration
    {
      { ATT_BT_UUID_SIZE, characterUUID },
      GATT_PERMIT_READ,
      0,
      &simpleProfileChar4Props
    },

      // Characteristic Value 4
      {
        { ATT_BT_UUID_SIZE, simpleProfilechar4UUID },
        0,
        0,
        simpleProfileChar4
      },

      // Characteristic 4 configuration
      {
        { ATT_BT_UUID_SIZE, clientCharCfgUUID },
        GATT_PERMIT_READ | GATT_PERMIT_WRITE,
        0,
        (uint8 *)simpleProfileChar4Config
      },

      // Characteristic 4 User Description
      {
        { ATT_BT_UUID_SIZE, charUserDescUUID },
        GATT_PERMIT_READ,
        0,
        simpleProfileChar4UserDesp
      },

    // Characteristic 5 Declaration
    {
      { ATT_BT_UUID_SIZE, characterUUID },
      GATT_PERMIT_READ,
      0,
      &simpleProfileChar5Props
    },

      // Characteristic Value 5
      {
        { ATT_BT_UUID_SIZE, simpleProfilechar5UUID },
        GATT_PERMIT_AUTHEN_READ,
        0,
        simpleProfileChar5
      },

      // Characteristic 5 User Description
      {
        { ATT_BT_UUID_SIZE, charUserDescUUID },
        GATT_PERMIT_READ,
        0,
        simpleProfileChar5UserDesp
      },
};


使用特权

评论回复
7
木木guainv|  楼主 | 2021-9-6 15:10 | 只看该作者
修改一下CHAR1的Props为notify
// Simple Profile Characteristic 1 Properties
static uint8 simpleProfileChar1Props = GATT_PROP_READ | GATT_PROP_WRITE|GATT_PROP_NOTIFY;



增加CHAR1的配置数据
static gattCharCfg_t simpleProfileChar1Config[4];
1
profile 中,初始化CHAR1的配置
/*********************************************************************
1. @fn      SimpleProfile_AddService
2.  3. @brief   Initializes the Simple Profile service by registering
4.          GATT attributes with the GATT server.
5.  6. @param   services - services to add. This is a bit map and can
7.                     contain more than one service.
8.  9. @return  Success or Failure
*/
bStatus_t SimpleProfile_AddService( uint32 services )
{
  uint8 status = SUCCESS;

  // Initialize Client Characteristic Configuration attributes
  GATTServApp_InitCharCfg( INVALID_CONNHANDLE, simpleProfileChar4Config );
  GATTServApp_InitCharCfg( INVALID_CONNHANDLE, simpleProfileChar1Config );

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

  if ( services & SIMPLEPROFILE_SERVICE )
  {
    // Register GATT attribute list and CBs with GATT Server App
    status = GATTServApp_RegisterService( simpleProfileAttrTbl,
                                          GATT_NUM_ATTRS( simpleProfileAttrTbl ),
                                                                                  GATT_MAX_ENCRYPT_KEY_SIZE,
                                          &simpleProfileCBs );
  }

  return ( status );
}



链接状态改变时,也加一下
/*********************************************************************
1. @fn          simpleProfile_HandleConnStatusCB
2.  3. @brief       Simple Profile link status change handler function.
4.  5. @param       connHandle - connection handle
6. @param       changeType - type of change
7.  8. @return      none
*/
static void simpleProfile_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, simpleProfileChar4Config );
      GATTServApp_InitCharCfg( connHandle, simpleProfileChar1Config );
    }
  }
}


使用特权

评论回复
8
木木guainv|  楼主 | 2021-9-6 15:11 | 只看该作者
增加notify的方法
我这里取巧了,只是用于测试, simpleProfile_Notify 这个函数是在用户定义的任务周期函数里面定义的,这里间隔发送 CHAR1 和 CHAR4
再强调: 调用这些蓝牙的操作,不能在相同时间内操作多个,否则前面的也不生效,例如下面同时notify CHAR1 和 CHAR4 ,则CHAR1是不会生效的!
/*********************************************************************
* @fn          simpleProfile_Notify
*
* @brief       Send a notification containing a heart rate
*              measurement.
*
* @param       connHandle - connection handle
* @param       pNoti - pointer to notification structure
*
* @return      Success or Failure
*/
bStatus_t simpleProfile_Notify( uint16 connHandle, attHandleValueNoti_t *pNoti )
{
  static char flag = 0;

  flag = !flag;
  // If notifications enabled
  if(flag == 0)
  {
      uint16 value =  GATTServApp_ReadCharCfg( connHandle, simpleProfileChar4Config );
      if ( value & GATT_CLIENT_CFG_NOTIFY )
      {
        printf("noti char 4..\n");
        // Set the handle
        pNoti->handle = simpleProfileAttrTbl[SIMPLEPROFILE_CHAR4_VALUE_POS].handle;

        // Send the notification
        return GATT_Notification( connHandle, pNoti, FALSE );
        //  GATT_Notification( connHandle, pNoti, FALSE );
      }
  }
  else
  {
      uint16 value2 = GATTServApp_ReadCharCfg( connHandle, simpleProfileChar1Config );
      printf("noti char 1..\n");
      // If notifications enabled
      if ( value2 & GATT_CLIENT_CFG_NOTIFY )
      {
        // Set the handle
          pNoti->handle = simpleProfileAttrTbl[SIMPLEPROFILE_CHAR1_VALUE_POS].handle;

        // Send the notification
        //return GATT_Notification( connHandle, pNoti, FALSE );
        GATT_Notification( connHandle, pNoti, FALSE );
      }
  }


  return bleIncorrectMode;
}


使用特权

评论回复
9
木木guainv|  楼主 | 2021-9-6 15:12 | 只看该作者
用户任务

/*********************************************************************
* @fn      performPeriodicTask
*
* @brief   Perform a periodic application task. This function gets
*          called every five seconds as a result of the SBP_PERIODIC_EVT
*          TMOS event. In this example, the value of the third
*          characteristic in the SimpleGATTProfile service is retrieved
*          from the profile, and then copied into the value of the
*          the fourth characteristic.
*
* @param   none
*
* @return  none
*/
static void performPeriodicTask( void )
{
  uint8 notiData[SIMPLEPROFILE_CHAR4_LEN] = { 0x88 };
  peripheralChar4Notify( notiData, SIMPLEPROFILE_CHAR4_LEN );
}

/*********************************************************************
* @fn      peripheralChar4Notify
*
* @brief   Prepare and send simpleProfileChar4 notification
*
* @param   pValue - data to notify
*          len - length of data
*
* @return  none
*/
static void peripheralChar4Notify( uint8 *pValue, uint16 len )
{
  attHandleValueNoti_t noti;

  noti.len = len;
  noti.pValue = GATT_bm_alloc( peripheralConnList.connHandle, ATT_HANDLE_VALUE_NOTI, noti.len, NULL, 0 );
  tmos_memcpy( noti.pValue, pValue, noti.len );
  if( simpleProfile_Notify( peripheralConnList.connHandle, &noti ) != SUCCESS )
  {
    GATT_bm_free( (gattMsg_t *)&noti, ATT_HANDLE_VALUE_NOTI );
  }
}

/*********************************************************************
* @fn      Peripheral_ProcessEvent
*
* @brief   Peripheral Application Task event processor.  This function
*          is called to process all events for the task.  Events
*          include timers, messages and any other user defined events.
*
* @param   task_id - The TMOS assigned task ID.
* @param   events - events to process.  This is a bit map and can
*                   contain more than one event.
*
* @return  events not processed
*/
uint16 Peripheral_ProcessEvent( uint8 task_id, uint16 events )
{

//  VOID task_id; // TMOS required parameter that isn't used in this function

  if ( events & SYS_EVENT_MSG ){
    uint8 *pMsg;

    if ( (pMsg = tmos_msg_receive( Peripheral_TaskID )) != NULL ){
      Peripheral_ProcessTMOSMsg( (tmos_event_hdr_t *)pMsg );
      // Release the TMOS message
      tmos_msg_deallocate( pMsg );
    }
    // return unprocessed events
    return (events ^ SYS_EVENT_MSG);
  }

  if ( events & SBP_START_DEVICE_EVT ){
        // Start the Device
    GAPRole_PeripheralStartDevice( Peripheral_TaskID, &Peripheral_BondMgrCBs, &Peripheral_PeripheralCBs );
    return ( events ^ SBP_START_DEVICE_EVT );
  }

  if ( events & SBP_PERIODIC_EVT )
  {
   // Restart timer
    if ( SBP_PERIODIC_EVT_PERIOD ){
      tmos_start_task( Peripheral_TaskID, SBP_PERIODIC_EVT, SBP_PERIODIC_EVT_PERIOD );
    }
    // Perform periodic application task 就是这里调用norify
    performPeriodicTask();

    return (events ^ SBP_PERIODIC_EVT);
  }

  if ( events & SBP_PARAM_UPDATE_EVT )
  {
    // Send connect param update request
    GAPRole_PeripheralConnParamUpdateReq( peripheralConnList.connHandle,
                                          DEFAULT_DESIRED_MIN_CONN_INTERVAL,
                                          DEFAULT_DESIRED_MAX_CONN_INTERVAL,
                                          DEFAULT_DESIRED_SLAVE_LATENCY,
                                          DEFAULT_DESIRED_CONN_TIMEOUT,
                                          Peripheral_TaskID);

    return (events ^ SBP_PARAM_UPDATE_EVT);
  }

  if ( events & SBP_READ_RSSI_EVT )
  {
    GAPRole_ReadRssiCmd(peripheralConnList.connHandle);
    tmos_start_task( Peripheral_TaskID, SBP_READ_RSSI_EVT, SBP_READ_RSSI_EVT_PERIOD );      
    return (events ^ SBP_READ_RSSI_EVT);
  }   

  // Discard unknown events
  return 0;
}


使用特权

评论回复
10
木木guainv|  楼主 | 2021-9-6 15:12 | 只看该作者
3、LOG
从机
noti char 1..
RSSI -52 dB Conn  1
noti char 4..
noti char 1..
noti char 4..
Disconnected.. Reason:8
Advertising..
Conn 1 - Int 3d
Connected..
noti char 1..
noti char 1..
RSSI -55 dB Conn  1
Update 1 - Int 3c
status = 0..
noti char 1..
status = 0..
noti char 4..
RSSI -51 dB Conn  1
noti char 1..
Update 1 - Int 8
noti char 4..
noti char 1..
RSSI -50 dB Conn  1
noti char 4..
noti char 1..
noti char 4..
RSSI -50 dB Conn  1
noti char 1..
noti char 4..
noti char 1..
RSSI -49 dB Conn  1
noti char 4..
noti char 1..



使用特权

评论回复
11
木木guainv|  楼主 | 2021-9-6 15:13 | 只看该作者
主机
CH57x_BLE_LIB_V1.60
Discovering...
Device 1 - Addr 9e b6 28 63 48 4d
Device 2 - Addr e5 b9 9c 48 b 72
Device 3 - Addr e3 7 ca b6 e3 2f
Device 4 - Addr 25 a3 22 e6 3a 9
Device 5 - Addr 4e 3 d2 96 4b 75
Device 6 - Addr ca 30 74 4e d7 76
Device 7 - Addr 90 e2 f3 38 c1 a4
Device 8 - Addr 61 59 99 c4 a 24
Device 9 - Addr ff 72 94 78 39 5d
Device 10 - Addr f5 aa 91 49 b5 5c
Device not found...
Discovering...
Device 1 - Addr e3 7 ca b6 e3 2f
Device 2 - Addr ca 30 74 4e d7 76
Device 3 - Addr 25 a3 22 e6 3a 9
Device 4 - Addr e5 b9 9c 48 b 72
Device 5 - Addr 82 47 dd 48 de 4b
Device 6 - Addr 9e b6 28 63 48 4d
Device 7 - Addr 61 59 99 c4 a 24
Device 8 - Addr 4e 3 d2 96 4b 75
Device not found...
Discovering...
Device 1 - Addr 25 a3 22 e6 3a 9
Device 2 - Addr e3 7 ca b6 e3 2f
Device 3 - Addr e5 b9 9c 48 b 72
Device 4 - Addr 4e 3 d2 96 4b 75
Device 5 - Addr ca 30 74 4e d7 76
Device 6 - Addr 82 47 dd 48 de 4b
Device 7 - Addr 56 8d 6d 14 cd 45
Device 8 - Addr ff 72 94 78 39 5d
Device 9 - Addr f5 aa 91 49 b5 5c
Device 10 - Addr a d6 6c 38 c1 a4
Device not found...
Discovering...
Device 1 - Addr e5 b9 9c 48 b 72
Device 2 - Addr 82 47 dd 48 de 4b
Device 3 - Addr 61 59 99 c4 a 24
Device 4 - Addr e3 7 ca b6 e3 2f
Device 5 - Addr 4e 3 d2 96 4b 75
Device 6 - Addr ca 30 74 4e d7 76
Device 7 - Addr 25 a3 22 e6 3a 9
Device 8 - Addr f9 69 64 38 c1 a4
Device 9 - Addr 56 8d 6d 14 cd 45
Device 10 - Addr f5 aa 91 49 b5 5c
Device not found...
Discovering...
Device 1 - Addr e3 7 ca b6 e3 2f
Device 2 - Addr f5 aa 91 49 b5 5c
Device 3 - Addr e5 b9 9c 48 b 72
Device 4 - Addr 25 a3 22 e6 3a 9
Device 5 - Addr ca 30 74 4e d7 76
Device 6 - Addr 2 2 3 e4 c2 84
Device 7 - Addr 9e b6 28 63 48 4d
Device 8 - Addr ff 72 94 78 39 5d
Device 9 - Addr 4e 3 d2 96 4b 75
Device 10 - Addr f9 69 64 38 c1 a4
Device found...
Connecting...
Connected...
Found Profile Service handle : 21 ~ ffff
Found Characteristic 1 handle : 23
RSSI : -40 dB
Found client characteristic configuration handle : 24
Found client characteristic configuration handle : 2e
Param Update...
Write success
RSSI : -38 dB
Receive hdl 23 noti: 88
Write success
Receive hdl 2d noti: 88
Receive hdl 23 noti: 88
RSSI : -37 dB
Param Update...
Receive hdl 2d noti: 88
Receive hdl 23 noti: 88
RSSI : -36 dB
Receive hdl 2d noti: 88
Receive hdl 23 noti: 88
RSSI : -41 dB
Receive hdl 2d noti: 88
Receive hdl 23 noti: 88


使用特权

评论回复
12
木木guainv|  楼主 | 2021-9-6 15:14 | 只看该作者
  • 截图 效果如下


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

134

主题

3880

帖子

5

粉丝