BLE工程——外设+观察者的实现

BLE支持外设和观察者同时工作,虽然TI提供的协议栈例程中并没有外设+广播者的工程,但是TI在如下网站上给出了外设+广播者的工程:

https://processors.wiki.ti.com/index.php/File:SimpleBleCombo.zip#file。

从上述网址下载得到SimpleBleCombo.zip压缩文件,解压后打开,里边有两个工程:外设+观察者(SimpleBLEPeripheralObserver)和中心设备+广播者(SimpleBLECenteralBroadcaster)。

要想实现外设+观察者的功能,可直接将SimpleBLEPeripheralObserver文件夹拷贝到协议栈:BLE-CC254x-1.3.2/Projects/ble/目录下,然后打开工程,编译、下载。然而这么做并没有什么意义,我们所需要的不是整个完整的工程,而是外设+广播的Profile实现文件,并使用这个Profile文件在TI的协议栈的SimpleBLEPeripheral工程做修改,来实现外设+观察者的功能。

1、SimpleBLEPeripheralObserver/Source目录下的peripheralObserverProfile.c和peripheralObserverProfile.h两个文件拷贝到协议栈安装位置BLE-CC254x-1.3.2/Projects/ble/Profiles/Roles目录下。

2、打开SimpleBLEPeripheral工程,选择Workspace为CC2541。

BLE工程——外设+观察者的实现 - ziye334 - ziye334的博客

3、在LIB工程组下,剔除CC2541_BLE_peri.lib库文件,然后添加CC2541_BLE_peri_observ.lib库文件。

BLE工程——外设+观察者的实现 - ziye334 - ziye334的博客

4、在PROFILES工程组下,剔除peripheral.c和peripheral.h文件,然后添加peripheralObserverProfile.c和peripheralObserverProfile.h两个文件。

BLE工程——外设+观察者的实现 - ziye334 - ziye334的博客

5、打开TOOLS工程组下的buildConfig.cfg文件,选择角色为外设+观察者:

//-DHOST_CONFIG=BROADCASTER_CFG

//-DHOST_CONFIG=OBSERVER_CFG

//-DHOST_CONFIG=PERIPHERAL_CFG

//-DHOST_CONFIG=CENTRAL_CFG

//-DHOST_CONFIG=BROADCASTER_CFG+OBSERVER_CFG

-DHOST_CONFIG=PERIPHERAL_CFG+OBSERVER_CFG

//-DHOST_CONFIG=CENTRAL_CFG+BROADCASTER_CFG

//-DHOST_CONFIG=PERIPHERAL_CFG+CENTRAL_CFG

6、打开APP工作组下的simpleBLEPeripheral.c文件。

7、修改头文件:

#include "peripheral.h"

#include "peripheralObserverPrifle.h"

8、添加几个宏定义,如下:



/* 最大扫描个数 */

#define DEFAULT_MAX_SCAN_RES            4

/* 扫描持续周期 */

#define DEFAULT_SCAN_DURATION           2000

/* 所有扫描模式:Limited,General */

#define DEFAULT_DISCOVERY_MODE          DEVDISC_MODE_ALL

#define DEFAULT_DISCOVERY_ACTIVE_SCAN  FALSE

#define DEFAULT_DISCOVERY_WHITE_LIST    FALSE
9、定义几个跟观察者相关的变量。

/* 扫描结果个数 */

static uint8 observerScanRes; 

/* 扫描索引 */

static uint8 observerScanIdx; 

/* 用于保存扫描设备的地址数组 */

static gapDevRec_t observerDevList[DEFAULT_MAX_SCAN_RES];

/* 用于保存扫描到的广播数据 */

static uint8 observerDevAdvData[DEFAULT_MAX_SCAN_RES][B_MAX_ADV_LEN];

/* 扫描状态 */

static uint8 observerScanning = FALSE;

10、删掉#if defined( CC2541_MINIDK )...#endif和它之间的代码,除了与simpleBLEPeripheral_HandleKeys()函数的代码。我使用的是SmartRF开发板,所以要保留按键处理函数。

11、在SimpleBLEPeripheral_Init()函数中注册按键处理函数。

RegisterForKeys( simpleBLEPeripheral_TaskID );

12、在SimpleBLEPeripheral_Init()函数中设置观察者相关配置。

{

  uint8 scanRes = DEFAULT_MAX_SCAN_RES;

  GAPRole_SetParameter( GAPOBSERVERROLE_MAX_SCAN_RES, 

                       sizeof( uint8 ), &scanRes );

}

GAP_SetParamValue(TGAP_GEN_DISC_SCAN, DEFAULT_SCAN_DURATION );

GAP_SetParamValue( TGAP_LIM_DISC_SCAN, DEFAULT_SCAN_DURATION );

13、去掉peripheralStateNotificationCB()函数GAPROLE_CONNECTED_ADV选项的内容去掉,因为对于外设+观察者,不允许存在连接后进行广播的情况。

/*case GAPROLE_CONNECTED_ADV:

{

  #if (defined HAL_LCD) && (HAL_LCD == TRUE)

    HalLcdWriteString( "Connected Advertising",  HAL_LCD_LINE_3 );

  #endif // (defined HAL_LCD) && (HAL_LCD == TRUE)

}

break;*/

14、向GAP Role回调函数添加观察者回调函数ObserverEventCB()。

static gapRolesCBs_t simpleBLEPeripheral_PeripheralCBs =

{

  peripheralStateNotificationCB,

  NULL,

  ObserverEventCB

};

15、编写ObserverEventCB()函数。

static void ObserverEventCB( observerRoleEvent_t *pEvent )

{

  switch ( pEvent->gap.opcode )

  {

    case GAP_DEVICE_INIT_DONE_EVENT:  

      break;

 

    case GAP_DEVICE_INFO_EVENT:

      {

        ObserverAddDeviceInfo( pEvent );

      }

      break;

      

    case GAP_DEVICE_DISCOVERY_EVENT:

      {

        observerScanning = FALSE;

 

        observerScanRes = pEvent->discCmpl.numDevs;

        osal_memcpy( observerDevList, pEvent->discCmpl.pDevList,

                   (sizeof( gapDevRec_t ) * pEvent->discCmpl.numDevs) );

        

        HalLcdWriteStringValue( "Devices Found", observerScanRes,

                           10, HAL_LCD_LINE_5 );

        if ( observerScanRes > 0 )

        {

          HalLcdWriteString( "<- To Select", HAL_LCD_LINE_6 );

        }

 

        observerScanIdx = observerScanRes;

        

        HalLedSet( HAL_LED_2, HAL_LED_MODE_OFF );

      }

      break;

      

    default:

      break;

  }

}

16、编写ObserverAddDeviceInfo()函数来接收扫描到设备的地址和广播数据。

static void ObserverAddDeviceInfo( observerRoleEvent_t *pEvent )

{

  uint8 i;

  

  if ( observerScanRes < DEFAULT_MAX_SCAN_RES )

  {

    for ( i = 0; i < observerScanRes; i++ )

    {

      if ( osal_memcmp( pEvent->deviceInfo.addr, 

                      observerDevList[i].addr , B_ADDR_LEN ) )

      {

        return;

      }

    }

    

  osal_memcpy( observerDevList[observerScanRes].addr, 

            pEvent->deviceInfo.addr, B_ADDR_LEN );

     observerDevList[observerScanRes].addrType = pEvent->deviceInfo.addrType;

  osal_memcpy( observerDevAdvData[observerScanRes], 

            &(pEvent->deviceInfo.pEvtData[4]), 

            pEvent->deviceInfo.pEvtData[3] );

    observerScanRes++;

  }

}

17、修改simpleBLEPeripheral_HandleKeys()函数代码为:

static void simpleBLEPeripheral_HandleKeys( uint8 shift, uint8 keys )

{

  VOID shift;

  

  if ( keys == HAL_KEY_UP )

  {

    uint8 adv_state;

    

    GAPRole_GetParameter( GAPROLE_ADVERT_ENABLED, &adv_state );

    if ( adv_state )

      adv_state = FALSE;

    else

      adv_state = TRUE;

   GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &adv_state );

  }

  if ( keys == HAL_KEY_CENTER )

  {

    if ( !observerScanning )

    {

      observerScanning = TRUE;

      observerScanRes = 0;

      osal_memset(observerDevAdvData, 0,  sizeof(observerDevAdvData));

      

      HalLcdWriteString( "Discovering...", HAL_LCD_LINE_5 );

      HalLcdWriteString( "", HAL_LCD_LINE_6 );

      HalLcdWriteString( "", HAL_LCD_LINE_7 );

      

      GAPObserverRole_StartDiscovery( DEFAULT_DISCOVERY_MODE, 

                              DEFAULT_DISCOVERY_ACTIVE_SCAN,

                              DEFAULT_DISCOVERY_WHITE_LIST );  

    }

  }  

  if ( keys == HAL_KEY_LEFT )

  {

    if ( !observerScanning && observerScanRes > 0 )

    {

      observerScanIdx++;

      if ( observerScanIdx >= observerScanRes )

      {

        observerScanIdx = 0;

      }

      HalLcdWriteStringValue( "Device", observerScanIdx + 1,

                         10, HAL_LCD_LINE_5 );

      HalLcdWriteString( bdAddr2Str( observerDevList[observerScanIdx].addr ),

                     HAL_LCD_LINE_6 );

      HalLcdWriteString( " ", HAL_LCD_LINE_7);

      HalLcdWriteString( (char *)observerDevAdvData[observerScanIdx], 

                     HAL_LCD_LINE_7 );

    }

  }

}


如上工程就修改完毕了,编译通过并下载进SmartRF开发板中,功能如下:

<1>按下SmartRF的JoyStick上键,打开/关闭广播。

<2>按下SmartRF的JoyStick中间键,开始扫描。扫描成功后,通过按下JoyStick的左键就可以选择扫描到设备地址和广播数据。

评论

© ziye334 | Powered by LOFTER