BLE开发_03_BLE常用参数及其修改_WCH
目录
本文以CH585EVT中从机/主机例程为例
UID和MAC地址
UID
UID:每个芯片出厂时都具有唯一的ID号,即芯片身份识别号。该ID数据及其校验和共8字节,存储于芯片内部只读区域中
下载时ISP工具会显示UID:UID = 6字节芯片MAC地址+ 2字节校验和
MAC地址
#if(defined(BLE_MAC)) && (BLE_MAC == TRUE)
for(i = 0; i < 6; i++)
{
cfg.MacAddr[i] = MacAddr[5 - i];//使用自定义MAC地址
}
#else
{
uint8_t MacAddr[6];
GetMACAddress(MacAddr);
for(i = 0; i < 6; i++)
{
cfg.MacAddr[i] = MacAddr[i]; // 使用芯片mac地址
}
}
#endif
- BLE_MAC的宏定义在HAL/include/CONFIG.h中,由于HAL库是整个BLE共用的,如果要单个工程修改宏定义,需要按如下方式修改
![image]()
动态修改MAC地址
- 流程是关闭广播--修改MAC地址--打开广播
//自定义tmos任务,完成关闭广播和修改MAC地址
if(events & SBP_TEST_EVT)
{
uint8_t initial_advertising_enable = FALSE;
uint8_t myAddr[6] = {0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0x00};
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initial_advertising_enable);
GAP_ConfigDeviceAddr(ADDRTYPE_STATIC, myAddr);
return (events ^ SBP_TEST_EVT);
}
//在peripheralStateNotificationCB回调函数中打开广播,不能在修改数据后立刻开启广播
case GAPROLE_WAITING:
if(pEvent->gap.opcode == GAP_END_DISCOVERABLE_DONE_EVENT)
{
PRINT("Waiting for advertising..\n");
uint8_t initial_advertising_enable = TRUE;
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initial_advertising_enable);
}
读取MAC地址
/**
* @brief get 6 bytes MAC address
*
* @param Buffer - Pointer to the buffer where data should be stored, Must in RAM and be aligned to 4 bytes.
*
* @return 0-SUCCESS (!0)-FAILURE
*/
#define GetMACAddress(Buffer) FLASH_EEPROM_CMD( CMD_GET_ROM_INFO, ROM_CFG_MAC_ADDR, Buffer, 0 )
其他地址
//修改方式和动态修改MAC地址流程一致
// GAP_ADDR_TYPE_DEFINES GAP Address Types
#define ADDRTYPE_PUBLIC 0x00 //公共地址
#define ADDRTYPE_STATIC 0x01 //静态地址
#define ADDRTYPE_PRIVATE_NONRESOLVE 0x02 //不可解析私有地址
#define ADDRTYPE_PRIVATE_RESOLVE 0x03 //可解析私有地址
- 不可解析私有地址不能用于设备回连
广播参数
- 广播参数的修改和上面的MAC地址修改方式一样,需要先关闭广播,修改参数,恢复广播,注意恢复广播的位置
广播数据和扫描应答数据
GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof(scanRspData), scanRspData);//扫描应答数据
GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData);//广播数据
// GAP - Advertisement data (max size = 31 bytes, though this is
// best kept short to conserve power while advertising)
static uint8_t advertData[] = {
// Flags; this sets the device to use limited discoverable
// mode (advertises for 30 seconds at a time) instead of general
// discoverable mode (advertises indefinitely)
0x02, // length of this data 长度
GAP_ADTYPE_FLAGS,//类型
DEFAULT_DISCOVERABLE_MODE | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,//值
// service UUID, to notify central devices what services are included
// in this peripheral
0x03, // length of this data,长度
GAP_ADTYPE_16BIT_MORE, // some of the UUID's, but not all,类型
LO_UINT16(SIMPLEPROFILE_SERV_UUID),//值
HI_UINT16(SIMPLEPROFILE_SERV_UUID)
};
//扫描应答数据
// GAP - SCAN RSP data (max size = 31 bytes)
static uint8_t 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
};
- 除了扫描应答数据中有广播名称外还有attDeviceName也定义了广播名称,建议这两处的名称保持一致,IOS中不一致会出现问题,GAP_DEVICE_NAME_LEN宏定义在XXXXlib.h文件中,如果需要修改需要修改文件读写权限
修改广播数据和扫描应答数据
/**
* @brief Setup or change advertising and scan response data.
*
* @note if the return status from this function is SUCCESS,the task isn't complete
* until the GAP_ADV_DATA_UPDATE_DONE_EVENT is sent to the calling application task.
*
* @param taskID - task ID of the app requesting the change
* @param adType - TRUE - advertisement data, FALSE - scan response data
* @param dataLen - Octet length of advertData
* @param pAdvertData - advertising or scan response data
*
* @return SUCCESS: data accepted
* bleIncorrectMode: invalid profile role
*/
extern bStatus_t GAP_UpdateAdvertisingData( uint8_t taskID, uint8_t adType, uint16_t dataLen, uint8_t *pAdvertData );
example:
if(events & SBP_TEST_EVT)
{
GAP_UpdateAdvertisingData(Peripheral_TaskID,FALSE,sizeof(scanRspData1), scanRspData1);
return (events ^ SBP_TEST_EVT);
}
广播间隔
uint16_t advInt = DEFAULT_ADVERTISING_INTERVAL;// 单位为 0.625ms,默认80*0.625ms
// Set advertising interval
GAP_SetParamValue(TGAP_DISC_ADV_INT_MIN, advInt);
GAP_SetParamValue(TGAP_DISC_ADV_INT_MAX, advInt);
- 广播间隔是指两个连续广播事件之间的时间间隔。一个广播事件包含在 3 个广播信道(37、38、39)上依次发送广播包,广播间隔就是从一个广播事件开始到下一个广播事件开始的时间,减小广播间隔可以加快连接速度,但是会增加功耗
- BLE 规范允许设置一个范围(最小值和最大值),控制器会在该范围内伪随机选择一个值作为本次广播事件的间隔。这样多个设备即使间隔范围相同,实际间隔也会错开,减少冲突。
连接参数
连接间隔
//从机
uint16_t desired_min_interval = DEFAULT_DESIRED_MIN_CONN_INTERVAL;
uint16_t desired_max_interval = DEFAULT_DESIRED_MAX_CONN_INTERVAL;
GAPRole_SetParameter(GAPROLE_MIN_CONN_INTERVAL, sizeof(uint16_t), &desired_min_interval);
GAPRole_SetParameter(GAPROLE_MAX_CONN_INTERVAL, sizeof(uint16_t), &desired_max_interval);
//主机
GAP_SetParamValue(TGAP_CONN_EST_INT_MIN, DEFAULT_MIN_CONNECTION_INTERVAL);
GAP_SetParamValue(TGAP_CONN_EST_INT_MAX, DEFAULT_MAX_CONNECTION_INTERVAL);
- 蓝牙主机从机连接后并不是持续发送数据的,而是在固定周期的类似于窗口内发送数据,称为连接事件,两个连接事件的时间间隔为连接间隔,连接间隔由主机决定,从机可以请求更新参数,连接间隔越小响应越快,但是功耗也越高
从设备延迟(slave latency)
- 从设备延迟是指从机可以连续跳过多少个连接事件而不必响应主机的数据包,但不导致连接断开。如latency设置为5,在后面5次连接事件中从机都可以不响应并且不会导致断开,但第六次连接事件必须相应,在中间跳过的数据会在从机唤醒后由协议栈链路层自动重传
- 从设备延迟用于降低设备功耗
// Slave latency to use parameter update
#define DEFAULT_DESIRED_SLAVE_LATENCY 0
连接超时
- 连接超时用于判断设备连接是否有效,如果超出该时间,设备会认为该连接无效;一旦判定超时,协议栈会向应用层报告连接断开事件,设备可以执行清理、重新广播、释放资源等操作
// Supervision timeout value (units of 10ms, 100=1s)
#define DEFAULT_DESIRED_CONN_TIMEOUT 100
MTU
-
MTU-最大传输单元,通常指的是ATT层的MTU,MTU最大值为512
-
MTU的协商
- MTU的协商是在建立连接之后主机/从机发起协商
- 最终的 ATT_MTU = min(请求方 MTU,响应方 MTU),双方在后续通信中使用这个较小值
- 假设ATT_MTU最终协商值为512,由于ATT层的包头占用3字节,实际用户数据为509字节
- 受限于蓝牙规范中链路层数据长度扩展(DLE)的最大有效载荷为251字节,当ATT_MTU大于247字节时在L2CAP层自动分包,比如当ATT_MTU协商值为512时,底层分包为244+244+21字节发送
-
修改MTU: MTU = BLE_BUFF_MAX_LEN - 4
#ifndef BLE_BUFF_MAX_LEN
#define BLE_BUFF_MAX_LEN 516
#endif
- 从机主动发起协商更新MTU
//1. Peripheral_Init()中添加client权限
GATT_InitClient();
//2.更新MTU
if(peripheralConnList.connHandle != GAP_CONNHANDLE_INIT)//连接后才更新MTU
{
attExchangeMTUReq_t req = {
.clientRxMTU = BLE_BUFF_MAX_LEN - 4,
};
GATT_ExchangeMTU(peripheralConnList.connHandle, &req, Peripheral_TaskID);
}
else{
PRINT("no connected...\r\n");
}
- MTU读取
/**
* @brief This function is used to get the MTU size of a connection.
*
* @param connHandle - connection handle.
*
* @return connection MTU size.<BR>
*/
extern uint16_t ATT_GetMTU( uint16_t connHandle );
PHY
- PHY是协议栈最底层的无线传输规范,定义了数据如何在空间中通过无线电波进行编码、调制和发送。PHY 直接决定了通信的速率、距离和抗干扰能力
- 1M/2M PHY指的是数据在空中传输速率,并不是数据的实际发送速率,实际发送速率还受到MTU/连接间隔等参数的影响
/**
* @brief Update the connection phy.
*
* @param connHandle - connection handle
* @param all_phys - a bit field that allows the Host to specify, for each direction
* set BIT0:The Host has no preference among the transmitter PHYs supported by the Controller
* set BIT1:The Host has no preference among the receiver PHYs supported by the Controller
* @param tx_phys - a bit field that indicates the transmitter PHYs.(GAP_PHY_BIT_TYPE)
* @param rx_phys - a bit field that indicates the receiver PHYs.(GAP_PHY_BIT_TYPE)
* @param phy_options - resv
*
* @return SUCCESS: PHY update started started .<BR>
* bleIncorrectMode: No connection to update.<BR>
*/
extern bStatus_t GAPRole_UpdatePHY( uint16_t connHandle, uint8_t all_phys, uint8_t tx_phys,\
uint8_t rx_phys, uint16_t phy_options );
从机主动更新连接参数
/**
* @brief Update the parameters of an existing connection
*
* @param connHandle - the connection Handle
* @param connIntervalMin - minimum connection interval in 1.25ms units
* @param connIntervalMax - maximum connection interval in 1.25ms units
* @param latency - the new slave latency
* @param connTimeout - the new timeout value
* @param taskId - taskID will recv L2CAP_SIGNAL_EVENT message
*
* @return SUCCESS, bleNotConnected or bleInvalidRange
*/
extern bStatus_t GAPRole_PeripheralConnParamUpdateReq( uint16_t connHandle, uint16_t connIntervalMin,
uint16_t connIntervalMax, uint16_t latency, uint16_t connTimeout, uint8_t taskId );
注意:库中还有个GAPRole_UpdateLink可以更新连接参数,但是是主机使用,该函数可以直接更新连接参数不经过协商,而GAPRole_PeripheralConnParamUpdateReq是更新连接参数请求,主机有权拒绝


浙公网安备 33010602011771号