您的位置:首页 > 其它

BLE蓝牙的数据黏包处理

2016-11-01 11:03 239 查看
1.首先说明一下本文档的背景:

由于BLE蓝牙传输一个包最多只能18个字节,而实际通讯自己定的协议一般都会超过18个字节,而数据也一般会有非常多个包一起发送,这个时候很多包就会黏在一起,而其实最好最简单的处理方法就是,定义一个超大的buf,直接往buf里不断的往后黏,然后最后再将这个buf拿出来解析。但是呢,实际很多情况是需要实时处理蓝牙的数据,并将数据解析显示或者分析等,还有就是整个设备本身整个应用就是在传输中进行的,再者这个buf也是有限大小的,所以效率相当低下,且有一定局限性,遇到这种情况那就得边接收数据边解析处理数据,那么接下来就介绍对蓝牙黏包的处理。 

  

2.蓝牙数据包的处理:

这个数据包处理主要是针对一款开锁器而设计的,所以里面设计了一个在线模式和离线模式的开锁,其他则与平时其他蓝牙应用的差不多。

流程图:



 代码与解析:

uint8 incompleteFlag=0;//数据不完整标志

 uint8 frontDataCount=0;//数据前半部分数量

 uint8 backDataCount=18;//数据后半部分数量

 uint8 totalDataCount=24;//实际协议数据包长度,这个根据自己定的协议而定

 uint8_t tempString[24];//用的临时数组

 uint8_t flashBuf[4800];//写入flash的数组

 int flashBufLength=0;//flash数组的长度

 

 SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR6,  newValue, &returnBytes);//接收到app端数据

      if(returnBytes > 0)//确认有数据

      {

          if(incompleteFlag!=0)//数据不完整

          {

              memcpy(tempString+backDataCount,newValue,frontDataCount);//将之前不足的6个字节补上(第一次为例)

              backDataCount=18-frontDataCount;//剩下12个字节

              //数据处理       

           if(tempString[5]==0x01&&tempString[0]==0x02&&tempString[1]==0x81)

              {

                //离线模式  将数据存入flash,根据是否写入flash成功进行回应

                if(flashBufLength==0)

                {

                   memcpy(flashBuf,tempString,totalDataCount);

                   flashBufLength+=totalDataCount;

                }

                else

                {

                   memcpy(flashBuf+flashBufLength,tempString,totalDataCount);

                   UART_WriteTransport(flashBuf, flashBufLength+totalDataCount);

                   flashBufLength+=totalDataCount;

                   //写入flash操作                                  

                }

                 //回应   

                  myRespondData[0]=0X01;

                  myRespondData[1]=0X01;

                  qq_write(myRespondData, 2);

                // 发送一个通知消息 SBP_UART_CHANGE_EVT, 以便把数据发送到空口

                  SimpleBLEPeripheral_enqueueMsg(SBP_UART_CHANGE_EVT, NULL);  

              }

              else

              {

                 //在线模式  将数据赋值给密码锁协议包直接下发,根据开锁是否成功进行回应

                 

                //回应

                 myRespondData[0]=0X00;

                 myRespondData[1]=0X01;

              }

              

              if(returnBytes>=18)//还有数据

              {

                 memcpy(tempString,0,24);

                 memcpy(tempString,newValue+frontDataCount,backDataCount);//从新开始黏贴

                 frontDataCount=totalDataCount-backDataCount;

              }

              Else//没有数据了

              {

                 memcpy(tempString,0,24);

                 incompleteFlag=0;

                 frontDataCount=0;

                 backDataCount=18;

              }

          }

          else    //完整

          {

            if(newValue[0]==0x02&&newValue[1]==0x81)//如果头不符合则判定为错误数据

            {

              memcpy(tempString,newValue,backDataCount);//将18个字节直接黏到临时数组里

              frontDataCount=totalDataCount-backDataCount;//我的协议数组是24-18=6个字节还没有得到,要第二次接收才能得到(第一次为例)

            }

          }

           if(frontDataCount!=0)//零个字节没得到,则是完整数据

                incompleteFlag=1;

           else

                incompleteFlag=0;

      }      

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  CC2640 蓝牙