1. 程式人生 > >【BLE】CC2541之回撥函式

【BLE】CC2541之回撥函式

本篇博文最後修改時間:2017年01月06日,11:06。

一、簡介

本文以SimpleBLECentral工程中simpleBLECentralEventCB函式,來簡要說明回撥函式的定義和呼叫過程。

二、實驗平臺

協議棧版本:BLE-CC254x-1.4.0

編譯軟體:IAR 8.20.2

硬體平臺:Smart RF開發板(主晶片CC2541)

博主:甜甜的大香瓜

宣告:喝水不忘挖井人,轉載請註明出處。

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

聯絡方式:[email protected]

香瓜BLE之CC2541群:127442605

香瓜BLE之CC2640群:557278427

香瓜BLE之Android群:541462902

香瓜微控制器之STM8/STM32群:164311667
甜甜的大香瓜的小店(淘寶店):https://shop217632629.taobao.com/?spm=2013.1.1000126.d21.hd2o8i 四、實驗前提 1、在進行本文步驟前,請先閱讀以下博文: 暫無 2、在進行本文步驟前,請先實現以下博文:
暫無

五、基礎知識

1、回撥函式是什麼?

答: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分層的考慮。

相關推薦

BLECC2541函式

本篇博文最後修改時間:2017年01月06日,11:06。 一、簡介 本文以SimpleBLECentral工程中simpleBLECentralEventCB函式,來簡要說明回撥函式的定義和呼叫過程。 二、實驗平臺 協議棧版本:BLE-CC254x-1.4.0 編

BLECC2541主機端讀取特征值

roi repl void 定時 store val star content else if 本篇博文最後改動時間:2017年01月06日,11:06。

BLECC2541連線引數

轉載自: https://blog.csdn.net/feilusia/article/details/46909723 一、簡介 本文介紹CC2541的連線引數。 二、實驗平臺 協議棧版本:BLE-CC254x-1.4.0 編譯軟體:IAR 8.20.2 硬體平臺:S

BLECC2541電池電量服務

本篇博文最後修改時間:2017年01月06日,11:06。 一、簡介 本文以SimpleBLEPeripheral工程為例,介紹如何新增一個電池電量服務。 二、實驗平臺 協議棧版本:BLE-CC254x-1.4.0 編譯軟體: IAR 8.20.2 硬體平臺: Smar

BLECC2541通訊協議

本篇博文最後修改時間:2016年12月12日,10:51。 一、簡介 本文以SimpleBLEPeripheral工程為例,介紹如何在一個可讀、可寫、可通知、20位元組長的特徵值char6基礎上,新增一個香瓜自定義的通訊協議,並用app傳送指令實現P11口上的LE

BLECC2541新增特徵值

本篇博文最後修改時間:2017年03月21日,15:32。 一、簡介 本文以SimpleBLEPeripheral工程為例,介紹如何新增一個可讀、可寫、可通知、20位元組長的特徵值char6,並用app實現資料的收發。 二、實驗平臺 協議棧版本:BLE-CC254

BLECC254132.768kHZ外部晶振

本篇博文最後修改時間:2017年01月06日,11:06。 一、簡介 本文介紹外部的32.768K晶振對於CC2541的作用。 二、實驗平臺 協議棧版本:BLE-CC254x-1.4.0 編譯軟體:IAR 8.20.2 硬體平臺:Smart RF(主晶片CC2

BLECC2541解析協議棧的晶振初始化過程

本篇博文最後修改時間:2017年01月06日,11:06。 一、簡介 本文以SimpleBLEPeripheral為例,解析協議棧的晶振初始化過程。 二、實驗平臺 協議棧版本:BLE-CC254x-1.4.0 編譯軟體:IAR 8.20.2 硬體平臺:Smart

BLECC2541發現服務與特徵值

本篇博文最後修改時間:2017年01月06日,11:06。 一、簡介 本文以SimpleBLECentral工程為例,解析CC2541作為主機時是如何發現從機的服務和特徵值的。二、實驗平臺 協議棧版本:BLE-CC254x-1.4.0 編譯軟體:IAR 8.20.2

BLECC2541indicate

本篇博文最後修改時間:2017年08月31日,17:00。 一、簡介 本文以SimpleBLEPeripheral為例,講述如何通過按五項按鍵的“center”鍵傳送indicate資料給btool,用PC的串列埠工具打印出“indicate”的“發資料”和“應答”的過程

BLECC2541開啟廣播過程

本篇博文最後修改時間:2016年11月11日,09:31。 一、簡介 本文介紹在應用層如何開啟廣播,且解析協議棧在此操作後做了什麼。 二、實驗平臺 協議棧版本:BLE-CC254x-1.4.0 編譯軟體:IAR 8.20.2 硬體平臺:Amart RF開發板(主晶

BLECC2541主機端獲取notify資料

本篇博文最後修改時間:2017年01月06日,11:06。 一、簡介 本文以SimpleBLECentral工程和SimpleBLEPeripheral工程為例,介紹CC2541作為主機時是如何獲取從機char4通道的notify資料。 二、實驗平臺 協議棧版

BLECC2541通過RSSI測距

本篇博文最後修改時間:2016年11月11日,09:21。 一、簡介 本文介紹如何在SimpleBLEPeripheral工程中,通過RSSI粗略測距。 二、實驗平臺 協議棧版本:BLE-CC254x-1.4.0 編譯軟體:IAR 8.20.2 硬體平臺:

CC2541函式程式碼解析

轉自:香瓜部落格回撥函式,解析程式碼: 一 、定義一個 “ 成員為函式指標 ” 的結構體 1 )定義一個函式指標 /** * Central Event Callback Function */ typedef void (*pfnGapCentralRoleEventCB

26、支付模組開發——支付寶函式實現和查詢使用者訂單狀態介面編寫

####1、支付寶回撥函式實現 我們在除錯支付寶沙箱環境的時候,支護寶會有一個回撥函式,也就是在支付成功之後,可以呼叫我們支付之後需要執行的相關方法,從而達到資料庫的資料和我們的操作相統一。 首先我們先在本地將回調函式編寫好~ 在OrderController類中新建我們的支付寶回撥函式

Unity技巧統一管理函式——觀察者模式

using UnityEngine; using System.Collections; using System.Collections.Generic; public class TimerController : MonoBehaviour { public delegate void OnC

Zookeeper C API函式

監視回撥函式 原型: Typedef void (*watcher_fn)(zhandle_t *zh, int type, int state, const char *path, void *watcherCtx); 監視函式原型的各個引數說明如下:

Zookeeper C API函式

監視回撥函式 原型: Typedef void (*watcher_fn)(zhandle_t *zh, int type, int state, const char *path, void *watcherCtx); 監視函式原型的各個引數說明如下:

Node.js實戰(八)函式

Node.js 非同步程式設計的直接體現就是回撥。 非同步程式設計依託於回撥來實現,但不能說使用了回撥後程序就非同步化了。 回撥函式在完成任務後就會被呼叫,Node 使用了大量的回撥函式,Node 所有 API 都支援回撥函式。 例如,我們可以一邊讀取檔案,一邊執行其他命令,在檔案讀取完成後,我們將檔案

C++學習 C/C++函式

 在理解“回撥函式”之前,首先討論下函式指標的概念。 函式指標 (1)概念:指標是一個變數,是用來指向記憶體地址的。一個程式執行時,所有和執行相關的物件都是需要載入到記憶體中,這就決定了程式執行時的任何物件都可以用指標來指向它。函式是存放在記憶體程式碼區域內的,它們同樣有地