本文涉及到ble從機的:
- 廣播相關
- 連接相關
- 服務/特征相關
- 數據收發相關
- 其他
1.[廣播相關]
廣播內容:
//設置/修改掃描回復以及廣播數據,這種修改需要重啟廣播
GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof ( scanRspData ), scanRspData );
GAPRole_SetParameter( GAPROLE_ADVERT_DATA, sizeof( advertData ), advertData );
//或者 通過下面方式進行修改,實時生效
bStatus_t GAP_UpdateAdvertisingData( uint8_t taskID,uint8_t adType,uint8_t dataLen,uint8_t *pAdvertData );
廣播間隔和類型:
//獲取當前的廣播間隔
//這里的值都是1=1.25ms
uint16_t advInt;
advInt = GAP_GetParamValue( TGAP_DISC_ADV_INT_MIN );
PRINT("min adv %d\r\n",advInt);
advInt = GAP_GetParamValue( TGAP_DISC_ADV_INT_MAX );
PRINT("max adv %d\r\n",advInt);
//修改廣播間隔
/*注意,廣播的參數修改,需要重啟廣播,才能生效
*可以修改后,然后在廣播 GAPROLE_WAITING(廣播停止)狀態產生后,然后立刻開啟廣播. 不能關閉廣播后立刻開啟廣播.
*/
//160*1.25ms == 200ms
uint16_t advInt = 160;
GAP_SetParamValue( TGAP_DISC_ADV_INT_MIN, advInt );
GAP_SetParamValue( TGAP_DISC_ADV_INT_MAX, advInt );
//修改廣播類型
// GAP_ADVERTISEMENT_TYPE_DEFINES GAP Advertising Event Types
#define GAP_ADTYPE_ADV_IND 0x00 //!< Connectable undirected advertisement
#define GAP_ADTYPE_ADV_HDC_DIRECT_IND 0x01 //!< Connectable high duty cycle directed advertisement
#define GAP_ADTYPE_ADV_SCAN_IND 0x02 //!< Scannable undirected advertisement
#define GAP_ADTYPE_ADV_NONCONN_IND 0x03 //!< Non-Connectable undirected advertisement
#define GAP_ADTYPE_ADV_LDC_DIRECT_IND 0x04 //!< Connectable low duty cycle directed advertisement
//對於只廣播的類型,如一些 beacon,可以用 GAP_ADTYPE_ADV_NONCONN_IND 類型,這樣不可以連接,會比較省電,但是數據只能放到 GAPROLE_ADVERT_DATA 中不能放到 GAPROLE_SCAN_RSP_DATA 中
uint8 adv_type = GAP_ADTYPE_ADV_IND;
GAPRole_SetParameter( GAPROLE_ADV_EVENT_TYPE,sizeof( uint8_t ),&adv_type);
廣播開關:
//獲取當前廣播狀態
//0為非廣播,非0為廣播
uint8_t adv_status;
GAPRole_GetParameter(GAPROLE_ADVERT_ENABLED, &adv_status );
//開啟廣播
//對應狀態上報:GAPROLE_ADVERTISING
uint8_t advertising_enable = true;
GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8_t ), &advertising_enable );
//關閉廣播
// 對應的狀態上報:
// :GAPROLE_WAITING
// :pEvent->gap.opcode == GAP_END_DISCOVERABLE_DONE_EVENT
advertising_enable = false;
GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8_t ), &advertising_enable );
//重啟廣播
//要先關閉廣播,然后在停止廣播的狀態產生后才能再去使能廣播,不能剛執行完關閉廣播,就去開啟廣播
//否則會導致立刻開啟失敗,如當前在廣播狀態,執行關閉廣播,然后立刻執行開始廣播,這時候開始廣播是不會調用成功的
//因為這里只是設置協議棧狀態機標識位,實際上廣播並沒有立刻停止,要等協議棧輪詢處理后,才會真正關閉,如果現在去啟動廣播,協議棧會認為當前已經在廣播狀態
2.[連接相關]
2.1 狀態和參數
//連接參數
//設置最大最小連接間隔,最小為6,這里通常是在初始化的時候設置
//這里的最大最小范圍要盡量的大,比如6,1000因為主機端連的時候,可能會不斷的修改連接間隔,從而實現更快速的服務相關的查詢
//后面的連接間隔,通過GAPRole_PeripheralConnParamUpdateReq 函數去更新即可
GAPRole_SetParameter( GAPROLE_MIN_CONN_INTERVAL, sizeof( uint16 ), &desired_min_interval );
GAPRole_SetParameter( GAPROLE_MAX_CONN_INTERVAL, sizeof( uint16 ), &desired_max_interval );
//在從機啟動的api里面傳入了幾個回調函數:
GAPRole_PeripheralStartDevice( Peripheral_TaskID, &Peripheral_BondMgrCBs, &Peripheral_PeripheralCBs );
//其中Peripheral_PeripheralCBs的定義類似下面:
static gapRolesCBs_t Peripheral_PeripheralCBs = {
peripheralStateNotificationCB, // Profile State Change Callbacks,廣播狀態改變,連接斷開連上都會調用這個回調
peripheralRssiCB, // When a valid RSSI is read from controller (not used by application),當讀RSSI后,這里會產生 RSSI的回調,把rssi 值傳進來.
peripheralParamUpdateCB // 連接參數更新,比如連接 間隔發生改變之類,都會傳入到這個函數里
};
2.2 連接斷開更新參數等相關API
//斷開連接
///這里的connHandle 就是在連接的時候傳進來的時候的代表一個連接,多連接場景,這個值不同.
extern bStatus_t GAPRole_TerminateLink( uint16 connHandle );
//連接參數更新
//這個是從機端,去向主機端請求連接更新
//這里的gapConnHandle 就是在連接的時候傳進來的時候的代表一個連接,多連接場景,這個值不同.
//注意下面幾個參數值,這幾個值要按照ble的規范去寫,如果是對接ios,ios的這幾個值更為嚴格.
GAPRole_PeripheralConnParamUpdateReq( gapConnHandle,
DEFAULT_DESIRED_MIN_CONN_INTERVAL,
DEFAULT_DESIRED_MAX_CONN_INTERVAL,
DEFAULT_DESIRED_SLAVE_LATENCY,
DEFAULT_DESIRED_CONN_TIMEOUT,
heartRate_TaskID );
3.[服務/特征相關]
4.[數據傳輸相關]
5.[其他]
修改發射功率
初始化時候修改
在協議棧出事時候的config.h文件中修改以下定義:
#ifndef BLE_TX_POWER
#define BLE_TX_POWER LL_TX_POWEER_0_DBM
#endif
初始化以后修改
這里的傳參,和BLE_TX_POWER 中宏的取值范圍一致
extern bStatus_t LL_SetTxPowerLevel( u8 power );
BLE從機的名稱
BLE里面有兩個地方涉及到名字:
- 廣播/掃描回復包中
- GAP中
在wch的例程里,分別對應下面兩個地方
(規范並沒有規定,兩個地方的名字必須一致,但是這里建議大家用一致.)
如果程序中修改,上電時候改這兩個數組就好了
// GAP - SCAN RSP data (max size = 31 bytes)
static uint8 scanRspData[ ] =
{
// complete name
0x12, // length of this data
GAP_ADTYPE_LOCAL_NAME_COMPLETE,
'S',
'i',
'm',
'p',
'l',
'e',
' ',
'P',
'e',
'r',
'i',
'p',
'h',
'e',
'r',
'a',
'l',
// connection interval range
0x05, // length of this data
GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE,
LO_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL ), // 100ms
HI_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL ),
LO_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL ), // 1s
HI_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL ),
// Tx power level
0x02, // length of this data
GAP_ADTYPE_POWER_LEVEL,
0 // 0dBm
};
// GAP GATT Attributes
static uint8 attDeviceName[GAP_DEVICE_NAME_LEN] = "Simple Peripheral";
// Set the GAP Characteristics
GGS_SetParameter( GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName );
IOS中BLE設備的名稱問題:
對於ble設備有兩個名稱,一個是在廣播/掃描回復 的字段中放着,一個是叫ATT device name,需要連接后去通過GATT讀取。 並沒有明確的要求二者必須一致,但是對於諸如N家,S家的SDK來看,二者是一致的,在IOS 獲取BLE設備的名字時, 如果這個設備之前沒有連接過,那默認是廣播中的名字;當連接后,IOS會通過去讀從機的ATT DEVICE NAME,然后私自建立MAC->ATT DEVICE NAME 映射表,當下次再掃描時候,直接根據mac地址匹配自己緩存的BLE設備名字,所以IOS開發者時不時抱怨,為什么廣播的名字改了,掃描出來的名字卻沒變。IOS開發者需要每次都從廣播/掃描回復數據中 拿BLE設備廣播出來的名稱即可。
也可以在開發ble固件時候,強制讓廣播名字與ATT device name 一致,這樣IOS端的代碼就不用動.
微信小程序中交換mtu問題
微信的小程序的api中提供了 一個設置mtu的api: wx.setBLEMTU(Object object)
具體官方鏈接:https://developers.weixin.qq.com/miniprogram/dev/api/device/bluetooth-ble/wx.setBLEMTU.html
這個api 有多個返回:
屬性 | 類型 | 默認值 | 必填 | 說明 |
---|---|---|---|---|
deviceId | string | 是 | 用於區分設備的 id | |
mtu | number | 是 | 最大傳輸單元(22,512) 區間內,單位 bytes | |
success | function | 否 | 接口調用成功的回調函數 | |
fail | function | 否 | 接口調用失敗的回調函數 | |
complete | function | 否 | 接口調用結束的回調函數(調用成功、失敗都會執行) |
存在問題:當設備的mtu 不支持傳入的值時候,會直接返回fail,而不會把從機支持的最大值給報上來。