【BLE】CC2541之回调函数

一、简介

本篇以SimpleBLECentral工程中simpleBLECentralEventCB函数,来简要说明回调函数的定义和调用过程。


二、版权声明

博主:甜甜的大香瓜

声明:喝水不忘挖井人,转载请注明出处。

原文地址:http://blog.csdn.net/feilusia

联系方式:[email protected]

技术交流QQ群:127442605


三、回调函数简介

TI的BLE协议栈使用到大量的回调函数,函数名末尾带“CB”的通常都是回调函数,它是指“call back”,在状态有改变时会调用此函数。


四、解析代码

1、定义一个“成员为函数指针”的结构体

1)定义一个函数指针

/**
 * Central Event Callback Function
 */
typedef void (*pfnGapCentralRoleEventCB_t)
(
  gapCentralRoleEvent_t *pEvent         //!< Pointer to event structure.
);
它的参数是一个gapCentralRoleEvent_t类型的消息指针*pEvent。

其中,gapCentralRoleEvent_t的类型如下

/**
 * Central Event Structure
 */
typedef union
{
  gapEventHdr_t             gap;                //!< GAP_MSG_EVENT and status.
  gapDeviceInitDoneEvent_t  initDone;           //!< GAP initialization done.
  gapDeviceInfoEvent_t      deviceInfo;         //!< Discovery device information event structure.
  gapDevDiscEvent_t         discCmpl;           //!< Discovery complete event structure.
  gapEstLinkReqEvent_t      linkCmpl;           //!< Link complete event structure.
  gapLinkUpdateEvent_t      linkUpdate;         //!< Link update event structure.
  gapTerminateLinkEvent_t   linkTerminate;      //!< Link terminated event structure.
} gapCentralRoleEvent_t;

2)定义一个结构体

/**
 * Central Callback Structure
 */
typedef struct
{
  pfnGapCentralRoleRssiCB_t   rssiCB;   //!< RSSI callback.
  pfnGapCentralRoleEventCB_t  eventCB;  //!< Event callback.
} gapCentralRoleCB_t;

gapCentralRoleCB_t结构体有两个成员,一个是pfnGapCentralRoleRssiCB_t类型的成员,一个是pfnGapCentralRoleEventCB_t类型的成员。


2、写一个回调函数,并完成注册

1)定义一个函数simpleBLECentralEventCB

/*********************************************************************
 * @fn      simpleBLECentralEventCB
 *
 * @brief   Central event callback function.
 *
 * @param   pEvent - pointer to event structure
 *
 * @return  none
 */
static void simpleBLECentralEventCB( gapCentralRoleEvent_t *pEvent )
{
  switch ( pEvent->gap.opcode )
  {
    case GAP_DEVICE_INIT_DONE_EVENT:  
      {
        LCD_WRITE_STRING( "BLE Central", HAL_LCD_LINE_1 );
        LCD_WRITE_STRING( bdAddr2Str( pEvent->initDone.devAddr ),  HAL_LCD_LINE_2 );
      }
      break;

    case GAP_DEVICE_INFO_EVENT:
      {
        // if filtering device discovery results based on service UUID
        if ( DEFAULT_DEV_DISC_BY_SVC_UUID == TRUE )
        {
          if ( simpleBLEFindSvcUuid( SIMPLEPROFILE_SERV_UUID,
                                     pEvent->deviceInfo.pEvtData,
                                     pEvent->deviceInfo.dataLen ) )
          {
            simpleBLEAddDeviceInfo( pEvent->deviceInfo.addr, pEvent->deviceInfo.addrType );
          }
        }
      }
      break;
      
    case GAP_DEVICE_DISCOVERY_EVENT:
      {
        // discovery complete
        simpleBLEScanning = FALSE;

        // if not filtering device discovery results based on service UUID
        if ( DEFAULT_DEV_DISC_BY_SVC_UUID == FALSE )
        {
          // Copy results
          simpleBLEScanRes = pEvent->discCmpl.numDevs;
          osal_memcpy( simpleBLEDevList, pEvent->discCmpl.pDevList,
                       (sizeof( gapDevRec_t ) * pEvent->discCmpl.numDevs) );
        }
        
        LCD_WRITE_STRING_VALUE( "Devices Found", simpleBLEScanRes,
                                10, HAL_LCD_LINE_1 );
        if ( simpleBLEScanRes > 0 )
        {
          LCD_WRITE_STRING( "<- To Select", HAL_LCD_LINE_2 );
        }

        // initialize scan index to last device
        simpleBLEScanIdx = simpleBLEScanRes;

      }
      break;

    case GAP_LINK_ESTABLISHED_EVENT:
      {
        if ( pEvent->gap.hdr.status == SUCCESS )
        {          
          simpleBLEState = BLE_STATE_CONNECTED;
          simpleBLEConnHandle = pEvent->linkCmpl.connectionHandle;
          simpleBLEProcedureInProgress = TRUE;    

          // If service discovery not performed initiate service discovery
          if ( simpleBLECharHdl == 0 )
          {
            osal_start_timerEx( simpleBLETaskId, START_DISCOVERY_EVT, DEFAULT_SVC_DISCOVERY_DELAY );
          }
                    
          LCD_WRITE_STRING( "Connected", HAL_LCD_LINE_1 );
          LCD_WRITE_STRING( bdAddr2Str( pEvent->linkCmpl.devAddr ), HAL_LCD_LINE_2 );   
        }
        else
        {
          simpleBLEState = BLE_STATE_IDLE;
          simpleBLEConnHandle = GAP_CONNHANDLE_INIT;
          simpleBLERssi = FALSE;
          simpleBLEDiscState = BLE_DISC_STATE_IDLE;
          
          LCD_WRITE_STRING( "Connect Failed", HAL_LCD_LINE_1 );
          LCD_WRITE_STRING_VALUE( "Reason:", pEvent->gap.hdr.status, 10, HAL_LCD_LINE_2 );
        }
      }
      break;

    case GAP_LINK_TERMINATED_EVENT:
      {
        simpleBLEState = BLE_STATE_IDLE;
        simpleBLEConnHandle = GAP_CONNHANDLE_INIT;
        simpleBLERssi = FALSE;
        simpleBLEDiscState = BLE_DISC_STATE_IDLE;
        simpleBLECharHdl = 0;
        simpleBLEProcedureInProgress = FALSE;
          
        LCD_WRITE_STRING( "Disconnected", HAL_LCD_LINE_1 );
        LCD_WRITE_STRING_VALUE( "Reason:", pEvent->linkTerminate.reason,
                                10, HAL_LCD_LINE_2 );
      }
      break;

    case GAP_LINK_PARAM_UPDATE_EVENT:
      {
        LCD_WRITE_STRING( "Param Update", HAL_LCD_LINE_1 );
      }
      break;
      
    default:
      break;
  }
}


2)声明函数

static void simpleBLECentralEventCB( gapCentralRoleEvent_t *pEvent );

3)使simpleBLECentralEventCB成为回调函数

// GAP Role Callbacks
static const gapCentralRoleCB_t simpleBLERoleCB =
{
  simpleBLECentralRssiCB,       // RSSI callback
  simpleBLECentralEventCB       // Event callback
};

3、调用回调函数

1)定义一个新的函数指针变量pGapCentralRoleCB(central.c)

// App callbacks
static gapCentralRoleCB_t *pGapCentralRoleCB;

2)将pGapCentralRoleCB指向回调函数simpleBLECentralEventCB,也就是注册回调函数。

/**
 * @brief   Start the device in Central role.  This function is typically
 *          called once during system startup.
 *
 * Public function defined in central.h.
 */
bStatus_t GAPCentralRole_StartDevice( gapCentralRoleCB_t *pAppCallbacks )
{
  if ( pAppCallbacks )
  {
    pGapCentralRoleCB = pAppCallbacks;
  }

  return GAP_DeviceInit( gapCentralRoleTaskId, GAP_PROFILE_CENTRAL,
                         gapCentralRoleMaxScanRes, gapCentralRoleIRK,
                         gapCentralRoleSRK, &gapCentralRoleSignCounter );
}

3)调用回调函数

  // Pass event to app
  if ( pGapCentralRoleCB && pGapCentralRoleCB->eventCB )
  {
    pGapCentralRoleCB->eventCB( (gapCentralRoleEvent_t *) pMsg );
  }
}

注:实际上此时simpleBLECentralEventCB在第二步结束时,即可直接通过操作结构体来调用这个回调函数了。

但是之所以要将结构体中的simpleBLECentralEventCB函数首地址再传给simpleBLECentralEventCB(即第三点的1、2两个步骤),我认为是出于底层的profiles——central分层的考虑。


你可能感兴趣的:(【BLE】CC2541之回调函数)