一、簡介
本文以TI提供的SimpleBLECentral工程和SimpleBLEPeripheral工程爲例,介紹讀取RSSI的方法。
二、實驗平臺
協議棧版本:BLE-CC254x-1.4.0
編譯軟件:IAR 8.20.2
硬件平臺:Smart RF(主芯片CC2541)
三、版權聲明
聲明:喝水不忘挖井人,轉載請註明出處。
原文地址:http://write.blog.csdn.net/postedit
聯繫方式:[email protected]
開源四軸羣:84342712
四、關於RSSI
1、什麼是RSSI?
Received Signal Strength Indication,接收的信號強度指示。
2、RSSI有什麼用?
可根據RSSI來測主從機之間的距離。
3、RSSI需不需要連接才能讀取?
不需要。但需要不停地數據交互,才能更新結構體中得到的RSSI。
五、解析SimpleBLECentral工程中讀RSSI
注:該工程默認即是可讀RSSI,下面只是解析代碼
1、添加RSSI回調函數
1)定義一個函數simpleBLECentralRssiCB(此處添加串口輸出)
- 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)聲明函數
- static void simpleBLECentralRssiCB( uint16 connHandle, int8 rssi );
3)將回調函數與函數指針結構體掛鉤
- // GAP Role Callbacks
- static const gapCentralRoleCB_t simpleBLERoleCB =
- {
- simpleBLECentralRssiCB, // RSSI callback
- simpleBLECentralEventCB // Event callback
- };
4)註冊回調函數
- 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開始讀的周期函數
- 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;
實驗結果:
測試中發現多次讀到-129dB,暫不知原因,有人知道的話麻煩告訴我一聲~謝謝!
感謝羣友“崔氏小農”的答疑解惑:
六、SimpleBLEPeripheral工程中讀RSSI
1、定義並註冊一個回調函數(SimpleBLEPeripheral.c中)
1)定義一個函數
- /*********************************************************************
- * @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)將回調函數與函數指針結構體掛鉤
- // 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)註冊回調函數
- 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事件在做什麼:
實驗結果:
從機端讀取的RSSI比較正常,不像主機端有異常的“-129dB”。
七、主機端掃描時獲取RSSI的方法
- 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;
實驗結果如下: