本篇博文最后修改时间:2017年01月06日,11:06。
一、简介
本文以TI提供的SimpleBLECentral工程和SimpleBLEPeripheral工程为例,介绍SimpleBLECentral工程连接时读取RSSI、SimpleBLECentral工程不连接时读取RSSI、SimpleBLEPeripheral工程连接时读取RSSI的方法。
二、实验平台
协议栈版本:BLE-CC254x-1.4.0
编译软件:IAR 8.20.2
硬件平台:Smart RF(主芯片CC2541)
三、版权声明
博主:甜甜的大香瓜
声明:喝水不忘挖井人,转载请注明出处。
原文地址:http://blog.csdn.NET/feilusia
联系方式:897503845@qq.com
香瓜BLE之CC2541群:127442605
香瓜BLE之CC2640群:557278427
五、基础知识
1、什么是RSSI?
答:Received Signal Strength Indication,接收的信号强度指示。
2、RSSI有什么用?
答:可根据RSSI来测主从机之间的距离。
3、RSSI需不需要连接才能读取?
答:不需要。但需要不停地数据交互,才能更新结构体中得到的RSSI。
六、解析代码(SimpleBLECentral工程中以连接方式读RSSI)
注:该工程默认即是可读RSSI,下面只是解析代码。
1、添加RSSI回调函数
1)定义一个函数simpleBLECentralRssiCB(SimpleBLECentral.c中)
static void simpleBLECentralRssiCB( uint16 connHandle, int8 rssi )
{
LCD_WRITE_STRING_VALUE( "RSSI -dB:", (uint8) (-rssi), 10, HAL_LCD_LINE_1 );
//输出RSSI的值到串口
NPI_PrintValue("RSSI:-", (uint8) (-rssi), 10);
NPI_PrintString("dB\r\n");
}
2)声明函数simpleBLECentralRssiCB(SimpleBLECentral.c中)
static void simpleBLECentralRssiCB( uint16 connHandle, int8 rssi );
3)将回调函数与函数指针结构体挂钩(SimpleBLECentral.c中)
// GAP Role Callbacks
static const gapCentralRoleCB_t simpleBLERoleCB =
{
simpleBLECentralRssiCB, // RSSI callback
simpleBLECentralEventCB // Event callback
};
4)注册回调函数(SimpleBLECentral.c中)
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 );
return ( events ^ START_DEVICE_EVT );
}
2、读取RSSI过程
1)按下“down”键,若此时处于“连接”、且“不读取RSSI”状态时,则调用RSSI开始读的周期函数(SimpleBLECentral.c中)
if ( keys & HAL_KEY_DOWN )
{
// Start or cancel RSSI polling
if ( simpleBLEState == BLE_STATE_CONNECTED )
{
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 );
}
}
}
2)GAPCentralRole_StartRssi函数
bStatus_t GAPCentralRole_StartRssi( uint16 connHandle, uint16 period )
{
gapCentralRoleRssi_t *pRssi;
// Verify link is up
if (!linkDB_Up(connHandle)) //没连接则退出
{
return bleIncorrectMode;
}
// If already allocated
if ((pRssi = gapCentralRole_RssiFind( connHandle )) != NULL) //如果“RSSI的connHandle值”等于“主从机的connHandle”
{
// Stop timer
osal_CbTimerStop( pRssi->timerId );
}
// Allocate structure
else if ((pRssi = gapCentralRole_RssiAlloc( connHandle )) != NULL)//connHandle不相等,说明还没有给RSSI分配connHandle,则分配下
{
pRssi->period = period;
}
// Allocate failed
else
{
return bleNoResources;
}
// Start timer
osal_CbTimerStart( gapCentralRole_timerCB, (uint8 *) pRssi, //这是一个带回调函数的定时器函数,到时即会调用回调函数gapCentralRole_timerCB
period, &pRssi->timerId );
return SUCCESS;
}
3)回调定时器函数gapCentralRole_timerCB
static void gapCentralRole_timerCB( uint8 *pData )
{
gapCentralRoleRssiEvent_t *pMsg;
// Timer has expired so clear timer ID
((gapCentralRoleRssi_t *) pData)->timerId = INVALID_TIMER_ID; //清除定时器ID
// Send OSAL message
pMsg = (gapCentralRoleRssiEvent_t *) osal_msg_allocate( sizeof(gapCentralRoleRssiEvent_t) );
if ( pMsg )
{
pMsg->hdr.event = GAPCENTRALROLE_RSSI_MSG_EVT;
pMsg->pRssi = (gapCentralRoleRssi_t *) pData;
osal_msg_send ( gapCentralRoleTaskId, (uint8 *) pMsg ); //发送消息到gapCentralRoleTaskId任务的GAPCENTRALROLE_RSSI_MSG_EVT事件中
}
}
case GAPCENTRALROLE_RSSI_MSG_EVT:
{
gapCentralRoleRssi_t *pRssi = ((gapCentralRoleRssiEvent_t *) pMsg)->pRssi;
// If link is up and RSSI reads active
if (pRssi->connHandle != GAP_CONNHANDLE_ALL &&
linkDB_Up(pRssi->connHandle))
{
// Restart timer
osal_CbTimerStart( gapCentralRole_timerCB, (uint8 *) pRssi, //不停地定时地调用本事件,从而读取RSSI
pRssi->period, &pRssi->timerId );
// Read RSSI
VOID HCI_ReadRssiCmd( pRssi->connHandle ); //调用读取RSSI的函数,调用完后会进到回调函数simpleBLECentralRssiCB
}
}
break;
3、实验结果
疑问:测试中发现多次读到-129dB,暂不知原因,有人知道的话麻烦告诉我一声~谢谢!
答:
感谢群友“崔氏小农”的答疑解惑:
七、实验步骤(SimpleBLEPeripheral工程以连接方式读RSSI)
1、定义并注册一个回调函数
1)定义一个函数(SimpleBLEPeripheral.c中)
/*********************************************************************
* @fn simpleBLEPeripheralRssiCB
*
* @brief RSSI callback.
*
* @param newRSSI - RSSI
*
* @return none
*/
static void simpleBLEPeripheralRssiCB( int8 newRSSI )
{
HalLcdWriteStringValue( "RSSI -dB:", (uint8) (-newRSSI), 10, HAL_LCD_LINE_1 );
// 可以输出一个值,用10进制表示
NPI_PrintValue("RSSI:-", (uint8) (-newRSSI), 10);
NPI_PrintString("dB\r\n");
}
注:从机端的RssiCB会比主机端少一个connHandle参数。
static void simpleBLEPeripheralRssiCB( int8 newRSSI );
3)将回调函数与函数指针结构体挂钩(SimpleBLEPeripheral.c中)
// GAP Role Callbacks
static gapRolesCBs_t simpleBLEPeripheral_PeripheralCBs =
{
peripheralStateNotificationCB, // Profile State Change Callbacks
simpleBLEPeripheralRssiCB // When a valid RSSI is read from controller (not used by application)
};
4)注册回调函数(SimpleBLEPeripheral.c中)
if ( events & SBP_START_DEVICE_EVT )
{
// Start the Device
VOID GAPRole_StartDevice( &simpleBLEPeripheral_PeripheralCBs );
// Start Bond Manager
VOID GAPBondMgr_Register( &simpleBLEPeripheral_BondMgrCBs );
// Set timer for first periodic event
osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_PERIODIC_EVT, SBP_PERIODIC_EVT_PERIOD );
return ( events ^ SBP_START_DEVICE_EVT );
}
//设置RSSI的读取速率,默认是0
uint16 desired_rssi_rate = 1000;
GAPRole_SetParameter(GAPROLE_RSSI_READ_RATE,sizeof(uint16),&desired_rssi_rate);
再看看RSSI_READ_EVT事件在做什么:
3、实验结果
从机端读取的RSSI比较正常,不像主机端有异常的“-129dB”。
八、实验步骤(SimpleBLECentral工程中以不连接的扫描方式读RSSI)
1、修改代码(SimpleBLECentral.c中)
case GAP_DEVICE_INFO_EVENT:
{
// if filtering device discovery results based on service UUID
if ( DEFAULT_DEV_DISC_BY_SVC_UUID == TRUE )
{
if ( simpleBLEFindSvcUuid( SIMPLEPROFILE_SERV_UUID,
pEvent->deviceInfo.pEvtData,
pEvent->deviceInfo.dataLen ) )
{
simpleBLEAddDeviceInfo( pEvent->deviceInfo.addr, pEvent->deviceInfo.addrType );
NPI_PrintString("发现设备:");//打印地址
NPI_PrintString((uint8 *)bdAddr2Str(pEvent->deviceInfo.addr));
NPI_PrintString("\r\n");
NPI_PrintValue("rssi:-", (uint8)(-( pEvent->deviceInfo.rssi )), 10);//打印RSSI
NPI_PrintString("dB\r\n");
}
}
}
break;
可通过不停地按“up”键扫描,不需要连接即可获取RSSI。
因为主机在扫描时获得的结构体数据,就已经有RSSI数据了:
/**
* GAP_DEVICE_INFO_EVENT message format. This message is sent to the
* app during a Device Discovery Request, when a new advertisement or scan
* response is received.
*/
typedef struct
{
osal_event_hdr_t hdr; //!< GAP_MSG_EVENT and status
uint8 opcode; //!< GAP_DEVICE_INFO_EVENT
uint8 eventType; //!< Advertisement Type: @ref GAP_ADVERTISEMENT_TYPE_DEFINES
uint8 addrType; //!< address type: @ref GAP_ADDR_TYPE_DEFINES
uint8 addr[B_ADDR_LEN]; //!< Address of the advertisement or SCAN_RSP
int8 rssi; //!< Advertisement or SCAN_RSP RSSI
uint8 dataLen; //!< Length (in bytes) of the data field (evtData)
uint8 *pEvtData; //!< Data field of advertisement or SCAN_RSP
} gapDeviceInfoEvent_t;
2、实验结果
至此,SimpleBLECentral工程连接时读取RSSI、SimpleBLECentral工程不连接时读取RSSI、SimpleBLEPeripheral工程连接时读取RSSI的三种方法都成功了。
因此,实验成功。