蓝牙问题总结

一、

Base on the demo projects SimpleBLECentral and SimpleBLEPeripheral.

Backgroud: http://e2e.ti.com/support/low_power_rf/f/538/p/318484/1108115.aspx#1108115

(CC2540)Only 20 Bytes data can be transmitted in a time! This is just the way BLE is setup.

SimpleBLECentral receive 40 bytes data from the uart. In order to transmit these 40 bytes data from SimpleBLECentral to SimpleBLEPeripheral,  I have to break these 40 bytes into two packets(Accroding to Backgroud ) . The first packet contain the first 20 bytes data. The second packet contain the last 20 bytes data.

Then call the GATT_WriteCharValue twice.

The  SimpleBLECentral  program I had reedit is below:

void serialAppInitTransport( )
{
halUARTCfg_t uartConfig;

// configure UART
uartConfig.configured = TRUE;
uartConfig.baudRate = SBP_UART_BR;
uartConfig.flowControl = SBP_UART_FC;
uartConfig.flowControlThreshold = SBP_UART_FC_THRESHOLD;
uartConfig.rx.maxBufSize = SBP_UART_RX_BUF_SIZE;
uartConfig.tx.maxBufSize = SBP_UART_TX_BUF_SIZE;
uartConfig.idleTimeout = SBP_UART_IDLE_TIMEOUT;
uartConfig.intEnable = SBP_UART_INT_ENABLE;
uartConfig.callBackFunc = sbpSerialAppCallback;

// start UART
// Note: Assumes no issue opening UART port.
(void)HalUARTOpen( SBP_UART_PORT, &uartConfig );

return;
}
uint16 numBytes;

void sbpSerialAppCallback(uint8 port, uint8 event)
{
uint8 pktBuffer[SBP_UART_RX_BUF_SIZE];
// unused input parameter; PC-Lint error 715.
      (void)event;
      int i=0;
      for(i=12000;i>0;i--)

       {
          asm("nop");
        }

if ( (numBytes = Hal_UART_RxBufLen(port)) > 0 ) //  In the example numBytes = 40

 {
(void)HalUARTRead (port, pktBuffer, numBytes);
    if  (pktBuffer[0]=='A' && pktBuffer[1]=='T')

     {
        CommondHandle(pktBuffer, numBytes);
     }

     else

     {
         sbpGattWriteString(pktBuffer,numBytes/2);       first  -- tranmit the first 20 bytes data

          for(i=12000;i>0;i--)

         {
              asm("nop");
          }

        sbpGattWriteString(pktBuffer+20,numBytes/2);  second-- tranmit the last 20 bytes data
      }
  }

}

uint8 sbpGattWriteString(uint8 *pBuffer, uint16 length)
{
uint8 status;
uint8 len;
if(length > 20)
len = 20;
else
len = length;
attWriteReq_t req;
req.handle = simpleBLECharHdl;
req.len = len;
req.sig = 0;
req.cmd = 0;
osal_memcpy(req.value,pBuffer,len);
status = GATT_WriteCharValue( simpleBLEConnHandle, &req, simpleBLETaskId );

return status;
}

//

I found that the SimpleBLEPeripheral only receive the first 20 bytes data, and the last 20 bytes data lost.

Is there some thing wrong with the app or the Osal ?

It seem that something wrong with the delay time between the first sbpGattWriteString and the second sbpGattWriteString .

It seem that there is a watch dog in the Osal, then I cannot extend the “nor” waiting  time easily.

How can I solve this problem?

Thanks you !

 

solved:

Rather than waiting in busy loop, your task needs to return control to OSAL so the various BLE tasks can handle the write request and write response.  Your task will be notified when the write has completed - have a look at simpleBleCentral.c; in particular , see logic around simpleBLECentralProcessGATTMsg().

 

二、 notify

notification类似主动上报,数据的变化可以直接从server通知给client.你得先搞清楚这两种不同的通讯方式。

1.client ->server

client 发request到server,server 回应response.读写都行。

2.server->client.

server主动发notification给Client 反映自己的属性变化。这根读写没关系吧。

server- 有数据的. client- 访问数据的。不论是mater还是slaver都可以是server或client,甚至既可以是server同时又是client.

To enable notifications, you must write a value of 0x0001 to the client characteristic configuration descriptor (CCCD). If you know the handle of the client characteristic descriptor, you can enable notifications by using the following code:

  attWriteReq_t writeReq;
  uint16 connHandle = connectionHandle;  // this will always be 0 if device only ever has one connection at a time

  writeReq.handle = handleOfCCCD; // if you know the value, you can put it in as a fixed value;
                                  // otherwise you will need to first discover the value
  writeReq.len = 2;
  writeReq.value[0] = LO_UINT16(GATT_CLIENT_CFG_NOTIFY);
  writeReq.value[1] = HI_UINT16(GATT_CLIENT_CFG_NOTIFY);
  writeReq.sig = 0;
  writeReq.cmd = 1;
 
  GATT_WriteNoRsp( connHandle, &writeReq, taskId );

Before doing this, you may also need to discover the handle of the CCCD. Some example of this process can be found in the TimeApp project which is included in the SDK. Specifically, look in the file "timeapp_discovery.c".

 

三、数据收发

说简单点,先discovery(GAPCentralRole_StartDiscovery),回调中处理simpleBLECentralStartDiscovery(),通过UUID找到对应的handle,handle就是

attribute的地址,然后就可以使用GATT_WriteCharValue()或GATT_ReadCharValue()像指定的handle发送读写操作。最后在simpleBLECentralProcessGATTMsg()处理操作结果。还有另外一种通讯方式是notification,就是server主动向Client发送数据,不同于上面这种request/response模式,附图如下。

蓝牙问题总结_第1张图片

 

四、handle值的发现

static void simpleBLEGATTDiscoveryEvent( gattMsgEvent_t *pMsg )

{
  attReadByTypeReq_t req;
 
  if ( simpleBLEDiscState == BLE_DISC_STATE_SVC )
  {
    // Service found, store handles
    if ( pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP &&
         pMsg->msg.findByTypeValueRsp.numInfo > 0 )
    {
      simpleBLESvcStartHdl = pMsg->msg.findByTypeValueRsp.handlesInfo[0].handle;
      simpleBLESvcEndHdl = pMsg->msg.findByTypeValueRsp.handlesInfo[0].grpEndHandle;
    }
   
    // If procedure complete
    if ( ( pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP  &&
           pMsg->hdr.status == bleProcedureComplete ) ||
         ( pMsg->method == ATT_ERROR_RSP ) )
    {
      if ( simpleBLESvcStartHdl != 0 )
      {
        // Discover characteristic
        simpleBLEDiscState = BLE_DISC_STATE_CHAR;
       
        req.startHandle = simpleBLESvcStartHdl;
        req.endHandle = simpleBLESvcEndHdl;
        req.type.len = ATT_BT_UUID_SIZE;
        //req.type.uuid[0] = LO_UINT16(SIMPLEPROFILE_CHAR1_UUID);
        //req.type.uuid[1] = HI_UINT16(SIMPLEPROFILE_CHAR1_UUID);
        req.type.uuid[0] = LO_UINT16(SIMPLEPROFILE_CHAR4_UUID);
        req.type.uuid[1] = HI_UINT16(SIMPLEPROFILE_CHAR4_UUID);

        GATT_ReadUsingCharUUID( simpleBLEConnHandle, &req, simpleBLETaskId );
      }
    }
  }
  else if ( simpleBLEDiscState == BLE_DISC_STATE_CHAR )
  {
    // Characteristic found, store handle
    if ( pMsg->method == ATT_READ_BY_TYPE_RSP &&
         pMsg->msg.readByTypeRsp.numPairs > 0 )
    {
      /*simpleBLECharHdl = BUILD_UINT16( pMsg->msg.readByTypeRsp.dataList[0],
                                       pMsg->msg.readByTypeRsp.dataList[1] );*/
      simpleBLECharHd4 = BUILD_UINT16( pMsg->msg.readByTypeRsp.dataList[0],
                                       pMsg->msg.readByTypeRsp.dataList[1] );
     
      LCD_WRITE_STRING( "Simple Svc Found", HAL_LCD_LINE_1 );
      simpleBLEProcedureInProgress = FALSE;
    }
   
    simpleBLEDiscState = BLE_DISC_STATE_IDLE;

   
  }   
}

//注意:如果client刚刚发送了一次请求但是server还未返回,这时候client就不应该再次发送请求信息,如果发送,server会将此丢弃。

Once a client sends a request to a server, that client shall send no other request to the same server until a response PDU has been received.

 

五、绑定管理

1) simpleperipheral 和 central的例子,他们初始化都是设置的GAPBOND_PAIRING_MODE_WAIT_FOR_REQ等待配对.

那么我的问题是,到底是peripheral发起的配对请求还是central?在什么时候发起的配对请求?

这样两边其实都没有发起配对.

除非其中一个配置成GAPBOND_PAIRING_MODE_INITIATE, 如果是central的话会发起pairing request, 如果是peripheral的话会发起slave security request, 最终会导致central那端收到 GAP_SLAVE_REQUESTED_SECURITY_EVENT, 这个时候你看代码, 如果central也是出于GAPBOND_PAIRING_MODE_WAIT_FOR_REQ, 那么他还是会发起配对.

所以, 只要其中一个设置成GAPBOND_PAIRING_MODE_INITIATE, 两边就会配对, 如果都是GAPBOND_PAIRING_MODE_WAIT_FOR_REQ, 那么就没有配对过程.

你可以修改其中一个看看哈.

 

2) 只要其中一个设置成GAPBOND_PAIRING_MODE_INITIATE, 两边就会配对”。那么配对的时候,两边是不是互相需要发送密码才行?只有密码对了才算配对成功吗?

必须会有密码.

至于是否要手动输入, 根据设备的IO Capability 设置来的. 就是设备的输入输出能力.

 

3 )

关于绑定我看代码的时候遇到了一些疑问。如下:

例子代码中,每当链接成功事件产生后,会通知绑定管理

            // Notify the Bond Manager to the connection
          VOID GAPBondMgr_LinkEst( pPkt->devAddrType, pPkt->devAddr, pPkt->connectionHandle, GAP_PROFILE_PERIPHERAL );

这个函数的作用是绑定蓝牙吗?

bStatus_t GAPBondMgr_LinkEst( uint8 addrType, uint8 *pDevAddr, uint16 connHandle, uint8 role )
{
  uint8 idx;                          // NV Index
  uint8 publicAddr[B_ADDR_LEN]        // Place to put the public address
      = {0, 0, 0, 0, 0, 0};

  idx = GAPBondMgr_ResolveAddr( addrType, pDevAddr, publicAddr );
  if ( idx < GAP_BONDINGS_MAX )
  {

                ……

}

代码中只有判断 idx < GAP_BONDINGS_MAX ,意思是这个蓝牙地址在绑定列表中?

如果idx > =GAP_BONDINGS_MAX 呢?

 

GAP_BONDINGS_MAX 是flash 里面允许存储的最多的绑定设备信息的个数.

你不用担心怎么绑定的, 绑定的工作底层自动会把做好的.

你要做的只是在应用层的宏定义里面打开绑定, 设置一下IO capability 就行. 如果你的设备的IO capability 设置成有输入功能, 就会要求输入密码, 如果你是没有输入功能更, 系统会自动产生随机密码.

 

4 )

1、当绑定信息个数达到GAP_BONDINGS_MAX的时候,又来了一个要绑定的设备信息,例程是如何处理的?先删除一个最后再添加?还是按FIFO或者其他存储方式呢?谢谢!

2、我试了一下pairing功能,当使能pairing时,主设备和从设备第一次配对的时候使用回调函数会在LCD屏幕上显示pairing start、pairing success的过程;当断开链接,第二次再链接时,屏幕上才会显示Bonds success。不知道为什么第二次链接时才显示 Bonds success。为什么?

3、当pairing success之后,主设备程序不变,把从设备的程序从新下载之后,主设备和从设备都不再执行pairing回调函数了,即LCD不再显示pairing start、pairing success和Bonds success.但是反过来,将主设备的程序从新下载后,从设备程序不变,又能正常执行pairing回调函数,即能在LCD上显示pairing start、pairing success和Bonds success。为什么?

 

1. 你可以这样理解, 最多绑定个数理论上, 说的是理论上, 是没有限制的, 无非就是需要一些flash 空间存储些对方设备信息而已. 但是实际中, 你flash 空间毕竟是有限的, 所以只能限定个数. 比如10 个. 如果超出, 代码会去判断前面是否已经有设备 已经解除配对了, 如果有, 就用这个位置存放新的信息. 如果没有, 就不保存了.  实际开发中你可以做个提示, 告诉用户空间已满, 请删除空闲已配对设备, 腾出空间. 你如果仔细想一下的话, 想想手机, 很多手机都是有已配对设备个数限制的(现在的智能手机可能还好点, 空间大, 但肯定也不会放你无限使用), 一旦个数达到极限,肯定会提醒. 

2. 不知道你是在哪里加的打印代码? 

3. 是因为从设备是 GAPBOND_PAIRING_MODE_WAIT_FOR_REQ 模式吧.


关于默认密码, 请看定义:

// Default passcode
#define DEFAULT_PASSCODE 19655

类似, 密码可以自己设置.

把两边 IO capability 定义都改成如下, 就不需要输入密码, 系统会自动产生密码或者用默认密码, 具体请看一下代码

// Default GAP bonding I/O capabilities
#define DEFAULT_IO_CAPABILITIES GAPBOND_IO_CAP_DISPLAY_ONLY

 

5)修改蓝牙地址

查看文档5.3.2

Every CC2540/41 device comes pre-programmed with a unique 48-bit IEEE address. This is referred to as
the device’s “primary address”, and cannot be changed. It is also possible to set a “secondary address” on
a device, which will override the primary address upon power-up. Flash Programmer can be used to read
the primary address, as well as to read or write the secondary address.
To read the primary address of a device connected to the CC Debugger, select “Primary” under the
“Location” option, and click the “Read IEEE” button. The primary device address should appear in the box
on the right as shown in Figure 48.

To read the secondary address, select “Secondary” under the “Location” option, and click the “Read IEEE”
button. The secondary device address should appear in the box on the right.
To set a new secondary address, select “Secondary” under the “Location” option, and enter the desired
address in the box on the right. Click the “Write IEEE” button to perform the write. If the secondary
device is set to “FF FF FF FF FF FF”, the device will use the primary address. If the secondary device is set
to anything else, the secondary address will be used.

 
六、蓝牙断开连接问题

首先要确定是否主从机均已经初始化完毕,如果对方没有初始化,那当然无法连接。

确定好后还有问题,那么一般是因为主机没有更新链路。这个过程为,从机的DEFAULT_ENABLE_UPDATE_REQUEST 设置为TRUE,从机就会发送一个param update的请求,然后主机就会出现一个在simpleBLECentralEventCB中产生一个GAP_LINK_PARAM_UPDATE_EVENT事件,然后主机就会去做这个链路更新。

所以我们要做的就是确定这个DEFAULT_ENABLE_UPDATE_REQUEST 设置成TRUE了。

补充说明:

对于BLE Link Layer层上断开连接的说明。

连接断开可能是由于主机或者从机身上的任何原因。一方断开连接,另外一方必须在退出连接状态之前响应其断开连接的请求。

连接断开也可能是因为超时:

-- 最大超时参数定义了主从机在接收到Link Layer层的包之前的最大时间。

-- 最大超时时间必须大于有效的连接间隔,必须小于32s。

-- 主从机均存有一个超时值,每当收到一个包被收到时,该超时值置为零。

-- 如果超时时间超过了最大超时时间,那么设备就应该当成连接已经断开,并且退出连接。 


七、无法搜索到设备的原因

1、这边有一个宏非常关键,DEFAULT_DEV_DISC_BY_SVC_UUID这个宏,默认为TRUE,但是在代码里面:

static void simpleBLECentralEventCB( gapCentralRoleEvent_t *pEvent )

{

...

 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) );
        }

...

}

看完代码就知道,扫描的值没有被赋值,因此一直为0。


2、这几天出现的一个BUG让我调试好久,一直不知道错误在哪里,昨天终于发现了,等下把代码贴出来,然后晚上再把写好的代码贴好。

出现的问题是: Central主机,扫描,然后连接,断开连接,没有问题,再次扫描,调用GAP_DeviceDiscoveryRequest()开始搜索,并且返回为SUCCESS,但是奇怪的是没有任何回应,一般协议栈应该会产生一个GAP_DEVICE_DISCOVERY_EVENT事件,但是结果是明晚在那边打了断点没有进。

查找了N久之后,问题出现在一个变量身上,这个变量是simpleBLEDiscState。

下面贴出产生问题的地方:

static void simpleBLEGATTDiscoveryEvent( gattMsgEvent_t *pMsg )
{
	attReadByTypeReq_t req;
  	static uint8 Flag = 1;
	uint16 Uuid;
    
    	switch (Flag)
    	{
    	case 1:
        	Uuid = UUID_XX1;
        	break;
    	case 2:
    	    Uuid = UUID_XX2;
    	    break;
    	case 3:
    	    Uuid = UUID_XX3;	
       	    break;
    	default:
		break;
    	}
    
	if ( simpleBLEDiscState == BLE_DISC_STATE_SVC )
 	{
		// Service found, store handles
		if ( pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP &&
			 pMsg->msg.findByTypeValueRsp.numInfo > 0 )
		{
		 	simpleBLESvcStartHdl = pMsg->msg.findByTypeValueRsp.handlesInfo[0].handle;
		 	simpleBLESvcEndHdl = pMsg->msg.findByTypeValueRsp.handlesInfo[0].grpEndHandle;
		}
		
		// If procedure complete
		if ( ( pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP  && 
			   pMsg->hdr.status == bleProcedureComplete ) ||
			 ( pMsg->method == ATT_ERROR_RSP ) )
		{
			if ( simpleBLESvcStartHdl != 0 )
		   	{
				// Discover characteristic
				simpleBLEDiscState = BLE_DISC_STATE_CHAR;
				
				req.startHandle = simpleBLESvcStartHdl;
				req.endHandle = simpleBLESvcEndHdl;
				req.type.len = ATT_BT_UUID_SIZE;
				req.type.uuid[0] = LO_UINT16(Uuid);
				req.type.uuid[1] = HI_UINT16(Uuid);
				
				GATT_ReadUsingCharUUID( ULOCKBLEConnHandle, &req, simpleBLETaskId );
		  	}
		}
		if(Flag == 2 || Flag == 3  )
		{
			simpleBLEDiscState = BLE_DISC_STATE_CHAR;
				
			req.startHandle = simpleBLESvcStartHdl;
			req.endHandle = simpleBLESvcEndHdl;
			req.type.len = ATT_BT_UUID_SIZE;
			req.type.uuid[0] = LO_UINT16(Uuid);
			req.type.uuid[1] = HI_UINT16(Uuid);
			
			GATT_ReadUsingCharUUID( ULOCKBLEConnHandle, &req, simpleBLETaskId );
		}
 	}
 	else if ( simpleBLEDiscState == BLE_DISC_STATE_CHAR )
 	{
        	// Characteristic found, store handle
  		if(pMsg->method == ATT_READ_BY_TYPE_RSP && 
			pMsg->msg.readByTypeRsp.numPairs > 0 )
		{
			if(UUID_XX1== Uuid)
			{
				handlexx_1= BUILD_UINT16( pMsg->msg.readByTypeRsp.dataList[0],
											pMsg->msg.readByTypeRsp.dataList[1] );
				SerialPrintValue("handle found ! value : ",handlexx_1,10);
                		SerialPrintString("\r\n");
                		Flag = 2;
			}
			else if(UUID_XX2 == Uuid)
			{
				handlexx_2= BUILD_UINT16( pMsg->msg.readByTypeRsp.dataList[0],
											pMsg->msg.readByTypeRsp.dataList[1] );
                		SerialPrintValue("handle found! value : ",handlexx_2,10);
                		SerialPrintString("\r\n");
                		Flag = 3;
			}
            
			else if(UUID_XX3 == Uuid)
 			{ 
				handlexx_3 = BUILD_UINT16( pMsg->msg.readByTypeRsp.dataList[0],
				pMsg->msg.readByTypeRsp.dataList[1] );
				SerialPrintValue("handle found! value : ",handlexx_3,10);
				SerialPrintString("\r\n");
			} 
			simpleBLEDiscState=BLE_DISC_STATE_SVC;
		}
	}
}

好了,终于把这个BUG完完全全的给弄好了!

下面看代码:


/*
 *这里参考的是TI的同时参考两个特征值的代码
 *可以看我另一篇文档查看
 *http://blog.csdn.net/qaqwe/article/details/25237067
*/
#if defined(MULT_CHAR_DISC)
static void simpleBLEGATTDiscoveryEvent( gattMsgEvent_t *pMsg )
{ 
  
    attReadByTypeReq_t req;
    if ( simpleBLEDiscState == BLE_DISC_STATE_SVC )   
    {    
        // Service found, store handles    
        if ( pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP &&       
                    pMsg->msg.findByTypeValueRsp.numInfo > 0 )   
        {      
            simpleBLESvcStartHdl = pMsg->msg.findByTypeValueRsp.handlesInfo[0].handle;  
            simpleBLESvcEndHdl = pMsg->msg.findByTypeValueRsp.handlesInfo[0].grpEndHandle;    
        }    
  
        // If procedure complete    
        if ( ( pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP  &&           
                pMsg->hdr.status == bleProcedureComplete ) ||         
                ( pMsg->method == ATT_ERROR_RSP ) )   
        {      
            if ( simpleBLESvcStartHdl != 0 )      
            {        
                // Discover characteristic       
                simpleBLEDiscState = BLE_DISC_STATE_CHAR1;      
                req.startHandle = simpleBLESvcStartHdl;    
                req.endHandle = simpleBLESvcEndHdl;    
                req.type.len = ATT_BT_UUID_SIZE;
                req.type.uuid[0] = LO_UINT16(xxUUID_1);    
                req.type.uuid[1] = HI_UINT16(xxUUID_1);      
                GATT_ReadUsingCharUUID( simpleBLEConnHandle, &req, simpleBLETaskId );     
            }    
        }  
    }  
  
    else if ( simpleBLEDiscState == BLE_DISC_STATE_CHAR1 )  
    {    
        // Characteristic found, store handle    
        if ( pMsg->method == ATT_READ_BY_TYPE_RSP &&      
            pMsg->msg.readByTypeRsp.numPairs > 0 )
        {      
            xxhandle_1 = BUILD_UINT16( pMsg->msg.readByTypeRsp.dataList[0],                         
                                        pMsg->msg.readByTypeRsp.dataList[1] );      
            //ReadAttrNum = ULOCK_STAT;
            SerialPrintValue("ulock state handle : ",xxhandle_1,10);
            SerialPrintString("\r\n");
            simpleBLEProcedureInProgress = TRUE;
        }
        else // pMsg->msg.readByTypeRsp.numPairs is 0.
        {
            simpleBLEDiscState = BLE_DISC_STATE_CHAR2; 
            req.startHandle = simpleBLESvcStartHdl;
            req.endHandle = simpleBLESvcEndHdl;
            req.type.len = ATT_BT_UUID_SIZE;
            req.type.uuid[0] = LO_UINT16(xxUUID_2);
            req.type.uuid[1] = HI_UINT16(xxUUID_2);
            
            GATT_DiscCharsByUUID( simpleBLEConnHandle, &req, simpleBLETaskId );
        }
    }  
  
    else if (simpleBLEDiscState == BLE_DISC_STATE_CHAR2)  
    {     
        // Characteristic found, store handle    
        if ( pMsg->method == ATT_READ_BY_TYPE_RSP &&     
            pMsg->msg.readByTypeRsp.numPairs > 0 )    
        {      
            //这边查找到的handle需要加1
			//注意GATT_DiscCharsByUUID 查找到的handle非特征值的handle,需要加1
			//GATT_ReadUsingCharUUID 查找到的handle为特征值的handle
            xxhandle_2 = BUILD_UINT16( pMsg->msg.readByTypeRsp.dataList[0],                                      
                                        pMsg->msg.readByTypeRsp.dataList[1] ) + 1;     
      
            SerialPrintValue("ulock control handle : ",xxhandle_2,10);
            SerialPrintString("\r\n");
            simpleBLEProcedureInProgress = FALSE;  
        }

		//重要,否则将在下次扫描时无法回应扫描结果
		simpleBLEDiscState = BLE_DISC_STATE_IDLE;

	
}
#endif


八、OAD问题

http://www.deyisupport.com/question_answer/wireless_connectivity/bluetooth/f/103/t/60727.aspx

http://www.deyisupport.com/question_answer/wireless_connectivity/bluetooth/f/103/t/51134.aspx

http://bbs.ednchina.com/BLOG_ARTICLE_3019402.HTM


九、RSSI换算距离

要知道蓝牙通信节点(如手机和蓝牙设备)之间的距离,最容易实现的方法是通过读取接收RSSIReceived Signal Strength Indication)值来计算。无线通讯中功率与距离的关系如下:

 其中A可以看作是信号传输1米远时接收信号的功率,n是传播因子(它受障碍,温度和湿度等影响),r是节点之间的距离。当确定了常数An的值后,距离r就可以根据PR(dBm)计算出来。

一般比较难算的话可以通过实际测量来确定!



你可能感兴趣的:(低功耗蓝牙开发)