首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

由浅入深,蓝牙4.0/BLE协议栈开发攻略大全(2)

由浅入深,蓝牙4.0/BLE协议栈开发攻略大全(2)

手动连接
  从机的对外广播是在初始化的时候完成的,那主机的扫描是在哪里开始的呢?阅读源码可以发现主机的操作都在按键处理中完成的。主机通过五向按键中的五个按键实现不同的功能。
  static void simpleBLECentral_HandleKeys( uint8 shift, uint8 keys )
  {
  (void)shift; // Intentionally unreferenced parameter
  if ( keys & HAL_KEY_UP ) // 向上
  {
  // Start or stop discovery
  if ( simpleBLEState != BLE_STATE_CONNECTED ) // 如果没有连接,开始扫描
  {
  if ( !simpleBLEScanning )
  {
  simpleBLEScanning = TRUE;
  simpleBLEScanRes = 0;
  LCD_WRITE_STRING( “Discovering.。。”, HAL_LCD_LINE_1 );
  LCD_WRITE_STRING( “”, HAL_LCD_LINE_2 );
  GAPCentralRole_StartDiscovery( DEFAULT_DISCOVERY_MODE,
  DEFAULT_DISCOVERY_ACTIVE_SCAN,
  DEFAULT_DISCOVERY_WHITE_LIST );
  }
  else
  {
  GAPCentralRole_CancelDiscovery();
  }
  }
  else if ( simpleBLEState == BLE_STATE_CONNECTED && // 如果连接并且发现Handle进行读写操作
  simpleBLECharHdl != 0 &&
  simpleBLEProcedureInProgress == FALSE )
  {
  uint8 status;
  // Do a read or write as long as no other read or write is in progress
  if ( simpleBLEDoWrite )
  {
  // Do a write
  attWriteReq_t req;
  req.handle = simpleBLECharHdl;
  req.len = 1;
  req.value[0] = simpleBLECharVal;
  req.sig = 0;
  req.cmd = 0;
  status = GATT_WriteCharValue( simpleBLEConnHandle, &req, simpleBLETaskId );
  }
  else
  {
  // Do a read
  attReadReq_t req;
  req.handle = simpleBLECharHdl;
  status = GATT_ReadCharValue( simpleBLEConnHandle, &req, simpleBLETaskId );
  }
  if ( status == SUCCESS )
  {
  simpleBLEProcedureInProgress = TRUE;
  simpleBLEDoWrite = !simpleBLEDoWrite;
  }
  }
  }
  if ( keys & HAL_KEY_LEFT ) // 左
  {
  // Display discovery results
  if ( !simpleBLEScanning && simpleBLEScanRes > 0 ) // 显示扫描到的设备
  {
  // Increment index of current result (with wraparound)
  simpleBLEScanIdx++;
  if ( simpleBLEScanIdx >= simpleBLEScanRes )
  {
  simpleBLEScanIdx = 0;
  }
  LCD_WRITE_STRING_VALUE( “Device”, simpleBLEScanIdx + 1,
  10, HAL_LCD_LINE_1 );
  LCD_WRITE_STRING( bdAddr2Str( simpleBLEDevList[simpleBLEScanIdx].addr ),
  HAL_LCD_LINE_2 );
  }
  }
  if ( keys & HAL_KEY_RIGHT ) // 右
  {
  // Connection update
  if ( simpleBLEState == BLE_STATE_CONNECTED ) // 如果连接,则更新连接
  {
  GAPCentralRole_UpdateLink( simpleBLEConnHandle,
  DEFAULT_UPDATE_MIN_CONN_INTERVAL,
  DEFAULT_UPDATE_MAX_CONN_INTERVAL,
  DEFAULT_UPDATE_SLAVE_LATENCY,
  DEFAULT_UPDATE_CONN_TIMEOUT );
  }
  }
  if ( keys & HAL_KEY_CENTER ) // 中间键
  {
  uint8 addrType;
  uint8 *peerAddr;
  // Connect or disconnect
  if ( simpleBLEState == BLE_STATE_IDLE ) // 空闲则连接
  {
  // if there is a scan result
  if ( simpleBLEScanRes > 0 )
  {
  // connect to current device in scan result
  peerAddr = simpleBLEDevList[simpleBLEScanIdx].addr;
  addrType = simpleBLEDevList[simpleBLEScanIdx].addrType;
  simpleBLEState = BLE_STATE_CONNECTING;
  GAPCentralRole_EstablishLink( DEFAULT_LINK_HIGH_DUTY_CYCLE,
  DEFAULT_LINK_WHITE_LIST,
  addrType, peerAddr );
  LCD_WRITE_STRING( “Connecting”, HAL_LCD_LINE_1 );
  LCD_WRITE_STRING( bdAddr2Str( peerAddr ), HAL_LCD_LINE_2 );
  }
  }
  else if ( simpleBLEState == BLE_STATE_CONNECTING || // 连接则断开连接
  simpleBLEState == BLE_STATE_CONNECTED )
  {
  // disconnect
  simpleBLEState = BLE_STATE_DISCONNECTING;
  gStatus = GAPCentralRole_TerminateLink( simpleBLEConnHandle );
  LCD_WRITE_STRING( “Disconnecting”, HAL_LCD_LINE_1 );
  }
  }
  if ( keys & HAL_KEY_DOWN ) // 下
  {
  // Start or cancel RSSI polling
  if ( simpleBLEState == BLE_STATE_CONNECTED ) // 连接则读取RSSi的值
  {
  if ( !simpleBLERssi )
  {
  simpleBLERssi = TRUE;
  GAPCentralRole_StartRssi( simpleBLEConnHandle, DEFAULT_RSSI_PERIOD );
  }
  else
  {
  simpleBLERssi = FALSE;
  GAPCentralRole_CancelRssi( simpleBLEConnHandle );
  LCD_WRITE_STRING( “RSSI Cancelled”, HAL_LCD_LINE_1 );
  }
  }
  }
  }
  因为从机一直处于广播状态,所以秩序将上一节中的从机程序烧录进开发板即可,然后将主机程序烧录到另外一快开发板,通过五向按键来实现和从机的连接和读写功能。
  (1) 上电提示
  从机上电提示:

  


  主机上电提示:

  


  (2)根据主机的按键功能,我们按“UP”键,开始搜索周边设备。搜索完成后,可以看到,扫描到了一个设备。
  (3)接着我们查看扫描到的设备地址,按左键。可以看到扫描到的设备地址为0x7C669D9F638A。这个地址正是我们的从机地址。
  (4)按中间键连接从机,可以看到主机提示连接成功,从机也提示连接成功。
  (5)接着我们开始读取从机的RSSI值,按下键。

  


  (6)再次按下键,取消RSSI值的读取。
  (7)对从机的CHAR1进行读写,再次按上键读取到CHAR1的值为1。
  (8)接着按上键,对CHAR1写入0,同时看到从机提示CHAR1的值被修改为0。
  主机写入成功:

  


  从机提示CHAR1被改变:

  


  上电自动连接
  上一节中我们通过五向按键实现了主机连接从机的功能,这一节中们来实现主机上电后自动搜索连接从机。
  要实现连接,从机必须处于广播状态,剩下的工作全部由主机完成,扫描、发起连接。
  主机的状态也有回调函数,主机启动后,第一个状态是初始化,所以我们在初始化完成时开始扫描,
  这样开机后主机就会开始扫描周边设备,接下来我们在扫描完成后对扫描到的设备发起连接。
  将工程编译下载后通过串口助手观察主机和从机的输出可以发现主机上电后自动的完成了一系列的操作。

  第二十四节 OAD空中升级
  通过仿真器更新程序或者通过USB更新固件那都是一般人都可以实现的操作,但是要想实现OAD空中升级,这还是需要一定的技术能力。这一节我就带着大家完善这一能力。
  OADn air download,指空中下载模式。当我们的产品发布以后,有时需要对固件进行升级,OAD是升级方式中的一种。
  配置BIM(Boot Image Manger)
  打开IAR,打开BLE-CC254x-1.4.0下的工程C:\TexasInstruments\BLE-CC254x-1.4.0\Projects\ble\util\BIM\cc254x\BIM.eww,然后编译,下载到开发板中。
  配置Image A
  打开OADExample工程,配置工程,添加如下几个宏
  FEATURE_OAD_BIM
  HAL_IMAGE_A
  FEATURE_OAD
  OAD_KEEP_NV_PAGES
  (1) 打开simplePeripheral.c找到宏定义DEFAULT_ENABLE_UPDATE_REQUEST,将其改为FLASE。否则会影响BLEDevice Monitor对其进行空中升级,到时可以再改回来。
  (2) IAR左侧导航中找到Profile文件夹,点击右键添加oad_target.c和oad_target.h两个文件,二文件位于 C:\TexasInstruments\BLE- CC254x-1.4.0\Projects\ble\Profiles\OAD中。
  (3) 在IAR导航中找到 HAL→Target→MT254xboard→Driver,右键添加文件hal_crc.c,该文件位于C:\TexasInstruments \BLE-CC254x-1.4.0\Components\hal\target\MT254xboard中。
  (4) 在刚才的simplePeripheral.c文件中,找到simplePeripheral_Init()函数,在里面添加OADTarget_AddService()函数。
  (5) 在simplePeripheral.c的前面,添加引用OAD的头文件,OAD.h和OAD_target.h。
  (6) 点击Project→Option…,或直接按Alt+F7,选择BuildActions,在Post-buildcommand line中添加:
  “$PROJ_DIR$\。。\。。\common\cc2540\cc254x_ubl_pp.bat”“$PROJ_DIR$” “ rodUBL”“$PROJ_DIR$\CC2540-OAD-ImgA\Exe\OADExample”
  注意,各双引号之间只有一个空格。注意图中红框标的部分,Image_A是和之前第1步对应的。
  (7) 点击Project→Option…,或直接按Alt+F7,选择Linker,选择Config,Linker Configurationfile中勾选Override default,添加C:\TexasInstruments\BLE-CC254x-1.4.0\Projects\ble\common \cc2540\cc254x_f256_imgA.xcl。
  (8) 点击Project→Option…,或直接按Alt+F7,选择Linker,选择Extra Output。
  (9) Extra Option添加Hex文件的输出。
  (10) 点击OK,编译下载,如果出现如下错误,是因为我们使用的是IAR8051 8.30版本,如果你使用的是IAR8.20版本就没有这问题。
  (11) 这个问题是因为使用了虚拟寄存器导致的,我们找到如下文件。

  


  (12) 对文件的115行进行如下修改,将虚拟寄存器注释掉。

  


  (13) 编译后,可以看到我们生成的文件
  (14) 我们将hex文件叠加到BIM后面
  这样ImageA就成功烧录进开发板了。
  配置Image B
  (1) 方法如Image A,其它要注意的几个地方:点击Project→Option…,或直接按Alt+F7,选择C/C++Compiler,选择Preprocessor,将Defined symbols中的HAL_IMAGE_A改成B。
  (2) 点击Project→Option…,或直接按Alt+F7,选择Linker,选择Config,将Linker Configuration file中的文件改为B。
  (3) 保存后编译,同样的可以看到生成的文件。

  


  (4) 为了区分A和B镜像,我们将最终结果改名。


  空中升级
  有了bin文件就可以进行空中升级了,打开BLE Device Monitor(没有安装的需要安装),打开后软件会自动扫描设备,如图,我们扫描到了开发板。

  


  (2) 连接后,打开OAD
  (3) 点击file,选择Progame(OAD),选择生成的bin文件,可以看到我们当前运行的是A固件
  (4) 点击start,当进行到100%,就完成了固件空中升级。
  (5) 升级后再次打开OAD选项,可以看到选择运行的固件已经是B版本的了。
  注意:
  要把 BLE协议栈BLE-CC254x-1.4.0 安装在C盘,在其他盘符下没有生成bin文件。

  第二十五节 SBL串口升级
  SBL升级和OAD升级的配置步骤都是一样的,主要是配置的参数不一样,下面我们来配置一个SBL升级的固件。
  配置SBL
  打开IAR,打开BLE-CC254x-1.4.0下的工程C:\TexasInstruments\BLE-CC254x-1.4.0\Projects\ble\util\SBL\iar\cc254x\sbl.eww,然后编译,下载到开发板中。


  配置Bin文件
  (1) 添加宏
  MAKE_CRC_SHDW
  FEATURE_SBL
  OAD_KEEP_NV_PAGES


  (2) 添加build选项
  “$PROJ_DIR$\。。\。。\common\cc2540\cc254x_ubl_pp.bat”“$PROJ_DIR$” “ProdUBL” “$PROJ_DIR$\MT254xboard\Exe\SBLExample”


  (3) Config选项


  (4) Extra Output选项

  


  (5) 保存编译

 


  (6) 打开串口升级软件SerialBootTool.exe,选择SBLExample.bin文件。

 


  (7) Load Image


  这样我们的SBL固件就制作完毕了。
返回列表