BLE开发(TI CC254x)之一主多从方案(蓝牙项目纪实)

近期一个BLE项目,整套方案做下来发现虽然需求特殊,但是根据这个项目可以衍生出BLE设备一主多从的一般性方法。

项目的需求基本如下:

1.实现基于CC2541芯片的蓝牙主机固件代码,要求主机1拖4从机;

2.上电自动、同时连接4个BLE设备;

3.身份识别需求:扫描绑定这4个唯一设备,不允许自动连接其他BLE设备

4.同时连接的情况下,读取4个BLE设备的通知型数据,并串口封包转发。

这个项目的麻烦在于需求3,4的实现,需求2要求上电自动连接多个BLE设备本来问题不大,但是需求3要求设备绑定,于是最初考虑的方法是:

1.采取广播包识别设备UUID的方式,类似iBeacon广播包中16个字节的UUID,可以作为唯一身份识别;

2.读取扫描应答包的设备名作为唯一识别标准;

3.根据设备的Mac地址作为设备的身份识别。

iBeacon是苹果推出的基于BLE4.0技术的应用层解决方案,主要利用BLE广播包进行信息的推送等服务,在长度受限的广播包中定义了16个字节的UUID,作为iBeacon设备的唯一识别码,这也是蓝牙2.4G作为有源RFID的一个方案之一。应该来说,在广播包里存放身份ID是最佳方案,无需建立连接即可唯一识别设备。

但是,这个项目的4个从机: 血压、血氧、血糖、血脂设备均为固定蓝牙设备,我无法修改其固件代码,只能动主机代码。

好吧,既然不能动从机,只能主机去想办法解决了。于是想到了方法2和3,方法2相比3实现起来要更麻烦,扫描应答包是从机对主机扫描的回应包,设备名存在于此包中,况且设备名不一定唯一(虽然该项目的四个设备名不同),考虑到一般性,决定采取Mac地址匹配的方法来进行设备筛选和上电自动绑定

需求4的麻烦在于如果采用Mac来识别设备并同时连接多个设备后,如何分别打开各设备的通知,从而读取各从机的通知型数据。答案是:依据连接时的handle,多从机时新建一个MulticonnHandle[]来存储从机的连接handle,因此最终确定的方案如下:

上电自动扫描+Mac地址匹配+自动连接+开启通知/断开连接

从一般性来说,该方案可以适用于:需要识别绑定专属BLE设备(无密码配对过程),并且一主多从通信的情况。


首先声明:CC2540/1芯片最多只能同时连接3个BLE设备,受芯片能力所限,官方解释如下




所以本方案也最多只能支持1拖3,要支持更多从机请选择CC2640/CC2650芯片。


具体实现如下:(基于simpleBLECentral.eww工程)


1.加入上电自动扫描

在simpleBLECentral_ProcessEvent()函数的设备启动事件下加入扫描的代码:

uint16 SimpleBLECentral_ProcessEvent( uint8 task_id, uint16 events )
{
  
   ...

  //设备启动事件
  if ( events & START_DEVICE_EVT )
  {
    // Start the Device
    VOID GAPCentralRole_StartDevice( (gapCentralRoleCB_t *) &simpleBLERoleCB );

    // Register with bond manager after starting device
    GAPBondMgr_Register( (gapBondCBs_t *) &simpleBLEBondCB );

    //设备已启动,进入上电自动扫描
    if ( !simpleBLEScanning & simpleBLEScanRes == 0 )
    {
      simpleBLEScanning = TRUE;
      simpleBLEScanRes = 0;
      GAPCentralRole_StartDiscovery( DEFAULT_DISCOVERY_MODE,
                                     DEFAULT_DISCOVERY_ACTIVE_SCAN,
                                     DEFAULT_DISCOVERY_WHITE_LIST );   
      //LCD_WRITE_STRING( "Scanning...", HAL_LCD_LINE_1 );
      NPI_PrintString("Scanning...\n");
      
    }
    else
    {
      //LCD_WRITE_STRING( "No Scan", HAL_LCD_LINE_1 );
      NPI_PrintString("Scanning Canceled\n");
    }
    
    return ( events ^ START_DEVICE_EVT );
  }

  if ( events & START_DISCOVERY_EVT )
  {
    simpleBLECentralStartDiscovery( );
    
    return ( events ^ START_DISCOVERY_EVT );
  }
  
  // Discard unknown events
  return 0;
}

2.实现Mac匹配算法绑定多从机

(1)在全局定义devMacList[MAX_DEVICE_NUM][B_ADDR_LEN]来预存指定设备的Mac,并实现Mac匹配算法。

预存Mac地址时需注意16进制序列逆序存储,主机扫描的设备列表的Mac存储在simpleDevList[].addr,如:(此处以两个从机为例)

static uint8 devMacList[MAX_DEVICE_NUM][B_ADDR_LEN]={//预存Mac地址
  {0xB8,0x43,0xA2,0x21,0xF8,0x5C},//十六进制序列逆序存储!与扫描存储的Mac地址对应,0x5CF821A243B8
  {0xAE,0x2D,0x42,0xBE,0x7C,0x08},
};
然后实现Mac匹配算法,基本思路:循环提取simpleDevList[].addr的值,在devMacList中查找Mac,若存在则记录下标。

//Mac地址匹配算法
//循环将simpleBLEDevList[i].addr的值提取,在devMacList中查找匹配的mac,若存在则记录对应的下标
 int findMacAddrMatching(int devMacRes[])
 {
        int k=0,num=0;
        int i=0,j=0;
        for(i=0;i<simpleBLEScanRes;i++)
        {
           for(j=0;j<MAX_DEVICE_NUM;j++)
           {
              if(isArrayEqual(simpleBLEDevList[i].addr,*(devMacList+j),B_ADDR_LEN,B_ADDR_LEN)==FALSE)
                  continue;//不相等匹配下一个
              devMacRes[j]=i;//按照预存Mac的顺序存储设备下标,故自动连接时获取的句柄MultiConnHandle[]也是固定顺序,便于分别设定通知开关的句柄
              k++;
              break;//若相等记录下标并跳出该层循环(mac唯一)
           }
        }
        //统计匹配到的mac设备个数
       for(k=0;k<MAX_DEVICE_NUM;k++)
       {
          if(devMacRes[k]!=-1)
            num++;
       }
       return num;
 }
isArrayEqual()功能非常简单,比较两个数组每个元素,完全相同返回真。但是在芯片上写代码,一切都要自己造轮子。。

//数组比较函数,两个数组完全相等返回TRUE,否则返回FALSE
static bool isArrayEqual(uint8 arr1[],uint8 arr2[],uint8 arr1_length,uint8 arr2_length)
{
  int i=0;
  if(arr1_length!=arr2_length)return FALSE;
  for(i=0;i<arr1_length;i++)
  {
      if(arr1[i]!=arr2[i])return FALSE;
  }
  return TRUE;
}
(2)实现Mac匹配算法后,在simpleBLECentralEventCB()的GAP_DEVICE_DISCOVERY_EVENT下打印扫描到的设备Mac信息,并执行Mac匹配函数。

       

        //打印所有设备Mac
        
        NPI_PrintString("device list:\n");    
        for(k=0;k<simpleBLEScanRes;k++)
        {
          NPI_PrintString((uint8*)bdAddr2Str( simpleBLEDevList[k].addr ));
          NPI_PrintString("\n");
        }      
        //执行Mac匹配算法
        devMacNum=findMacAddrMatching(devMacResult);

测试发现,打印的Mac地址是所有扫描到的设备,执行Mac匹配函数后4个专属设备在设备列表里的下标被成功保存到devMacResult[]中。


3.加入自动连接功能

在调用Mac匹配后,只需根据devMacResult[]中保存的下标以此发起连接请求。

但是每次连接发起后都会进入到GAP_LINK_ESTABLISHED_EVENT事件处理中,为保证逐个连接成功,还加入了自动连接标志进行调回处理。

示例代码如下:

        //自动连接     
            //连接第1个
            if(devMacNum > 0)
            {
                HalLedSet(HAL_LED_3, HAL_LED_MODE_ON );   //开LED3
           
                uint8 addrType;
                uint8 *peerAddr;
                
                simpleBLEScanIdx = devMacResult[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 );
   
                HalLedSet(HAL_LED_3, HAL_LED_MODE_OFF ); 
            }
            
              //连接第2个
      SECOND:
            if(devMacNum > 1)
            {
		...
            }
连接3,4其他从机以此类推。在GAP_LINK_ESTABLISHED_EVENT事件中处理连接结果,重点是保存连接的handle:
          MultiConnHandle[connHandle_num]=ppEvent->linkCmpl.connectionHandle;
          connHandle_num++;

存储了连接handle的MulticonnHandle[]将作为后面断开多从机连接和读取多从机数据的依据。

示例代码如下:

        //自动连接标志加1,开始连接下一个设备
          autoConnectFlag++;
          if(autoConnectFlag==1)
            goto SECOND;
          else if(autoConnectFlag==2)
            goto THIRD;
	  ...
          else if(autoConnectFlag==MAX_DEVICE_NUM)
            autoConnectFlag=0;//达到最大连接数后,结束上电连接任务

4.加入断开连接功能

一主多从条件下,要断开所有从机的连接,必须区分各个设备,读写数据也是一样,幸好连接事件中我们已保存各从机的连接handle。

示例代码如下:

            if(connHandle_num==1)
              GAPCentralRole_TerminateLink( MultiConnHandle[0]);
            else if(connHandle_num==2)
              GAPCentralRole_TerminateLink( MultiConnHandle[1]);
            ...
             NPI_PrintString("Disconnecting...\n");

5.读写特征值数据并处理

对于非通知型数据可以直接调用GATT_WriteCharValue和GATT_ReadCharValue读写数据,根据连接handle区分即可,如读取第一个设备的特征值:

  	  if ( simpleBLEDoWrite )
          {
            // Do a write
            NPI_PrintString("Writing...\n");
            attWriteReq_t req;
            
            req.handle = simpleBLECharHdl;
            req.len = 1;
            req.value[0] = simpleBLECharVal;
            req.sig = 0;
            req.cmd = 0;
            status = GATT_WriteCharValue(MultiConnHandle[0], &req, simpleBLETaskId );      
          }
          else
          {
            // Do a read
            NPI_PrintString("Reading...\n");
            attReadReq_t req;
            
            req.handle = simpleBLECharHdl;
            status = GATT_ReadCharValue(MultiConnHandle[0], &req, simpleBLETaskId );
          }
          
          if ( status == SUCCESS )
          {
            simpleBLEProcedureInProgress = TRUE;
            simpleBLEDoWrite = !simpleBLEDoWrite;
          }
        }  
 
对于通知型数据,实际是往CCC标志位写0x0001打开通知,多从机情况下只需依次打开通知监听即可,示例打开一个设备的通知,代码如下:
            attWriteReq_t req;
            
            req.handle = BLE_NotifyChar_Handle+1;
            req.len = 1;
            req.value[0] = 0x01;
            req.sig = 0;
            req.cmd = 0;
            status = GATT_WriteCharValue( MultiConnHandle[0], &req, simpleBLETaskId );  
通知开关的handle通常为 characteristic的handle+1。

读取到数据后,在simpleBLECentralProcessGATTMsg()中处理接收的数据,如数据的串口转发等。

至此,完成BLE一主多从的通信过程。







  • 8
    点赞
  • 67
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
### 回答1: BLE-CC254x是一种蓝牙低功耗(BLE)芯片,在物联网(IoT)和智能家居等领域应用广泛。BLE-CC254x安装包是为了让开发者可以更方便地使用这种芯片并进行软件开发而设计的。 BLE-CC254x安装包通常包含了一些必要的软件工具、驱动程序、开发文档以及一些示例代码等,这些都能够帮助开发者更快速地上手和进行开发。 在安装BLE-CC254x安装包之前,首先需要确定自己的电脑系统是否和该安装包兼容,并且需要按照安装包中的说明进行操作。安装完成后,开发者就可以开始使用BLE-CC254x芯片进行软件开发了。 需要注意的是,虽然BLE-CC254x安装包提供了很多便利,但如果开发者想要充分发挥出BLE-CC254x芯片的性能优势,还需要进行深入的学习和研究,以掌握相关的知识和技能。 ### 回答2: BLE-CC254x是一款蓝牙低能耗芯片,安装包则是指针对该芯片开发的软件安装包。 BLE-CC254x安装包主要是由一些驱动程序、固件升级文件、应用程序等组成,可以协助用户完成对该芯片的控制以及使用。安装包可以用于开发BLE相关的应用程序,支持不同的操作系统,如Windows、Linux等。 使用BLE-CC254x安装包,用户不仅可以轻松地配置芯片工作模式和参数,还能够进行调试和测试,以保证应用程序的正确运行。安装包提供了丰富的API和例程,使开发者能够快速上手开发,同时还支持多种开发环境,如Keil、IAR等。 总的来说,BLE-CC254x安装包是一款能够提高开发效率和开发质量的工具,它为开发者提供了方便、快捷的开发环境和丰富的开发资源。如果您正在开发BLE相关的应用程序,使用BLE-CC254x安装包一定会为您的工作带来很大的帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ctrlturtle

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值