低功耗蓝牙BLE之修改广播间隔等参数

本文详细介绍了低功耗蓝牙中的两种发现模式:有限可发现模式和普通可发现模式。包括如何设置这两种模式,以及如何配置广告时间和间隔等参数。

发现模式  (Discoverable Mode)


低功耗蓝牙的发现模式主要分为有限可发现模式和普通可发现模式,TI的CC2540和CC2541的工程中发现模式具体定义在components/ble/include目录下的Gap.h文件中,如下所示:

/** @defgroup GAP_ADTYPE_FLAGS_MODES GAP ADTYPE Flags Discovery Modes
* @{
*/
#define GAP_ADTYPE_FLAGS_LIMITED                0x01 //!< Discovery Mode: LE Limited Discoverable Mode
#define GAP_ADTYPE_FLAGS_GENERAL                0x02 //!< Discovery Mode: LE General Discoverable Mode
#define GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED    0x04 //!< Discovery Mode: BR/EDR Not Supported
/** @} End GAP_ADTYPE_FLAGS_MODES */

注意发现模式的定义必须在广播数据的开头处,不能在扫描回应数据中定义,实例代码如下:

// GAP - Advertisement data (max size = 31 bytes, though this is
// best kept short to conserve power while advertisting)
static uint8 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_ADTYPE_FLAGS_LIMITED)


如果将上述实例代码段中的DEFAULT_DISCOVERABLE_MODE设置为GAP_ADTYPE_FLAGS_LIMITED,设置的代码如下:

#define DEFAULT_DISCOVERABLE_MODE             GAP_ADTYPE_FLAGS_LIMITED

则设备就处于有限可发现模式,当设备处于有限可发现模式时,很多人以及网上的一些资料提到广播会在使能打开之后的 30.72s 之后停止广播。但是实际测试并不是这样,而是180s,通过查阅发现在Gap.h文件中有如下说明:

#define TGAP_LIM_ADV_TIMEOUT           1  //!< Maximum time to remain advertising, when in Limited Discoverable mode. In seconds (default 180 seconds)

注释中说明在有限可发现模式下,默认是180s之后停止广播,如果想设置这个值,可以用下面的方式:

GAP_SetParamValue( TGAP_LIM_ADV_TIMEOUT, ADV_TIMEOUT );


注意:通过上述方法设置 TGAP_LIM_ADV_TIMEOUT时,设置的时间单位是s(秒)。


还有些人会碰到另一种情况,就是在设置的时间或者是默认的时间之后,广播停止了,但是过了一段时间,默认应该是 30s 之后,广播又重新开启了,出现这种情况的时候确认下GAPROLE_ADVERT_OFF_TIME的设置,如果不设置该值,就会出现停止广播 30s(默认值)之后重新广播的情况,该值的默认值在projects/ble/profiles/roles目录下的peripheral.c文件中设置,如下:

#define DEFAULT_ADVERT_OFF_TIME       30000   // 30 seconds

所以如果要实现有限可发现模式,就要在应用的初始化地方设置该值为 0,设置方式如下:

uint16 gapRole_AdvertOffTime = 0;
GAPRole_SetParameter( GAPROLE_ADVERT_OFF_TIME, sizeof( uint16 ), &gapRole_AdvertOffTime );


介于上面的说明,我们来实现两个具体的情景便于理解:


1.广播使能开启之后,限制广播在 30s 之后停止,并且在应用部分没有使能打开的情况下不再广播,相关代码实现如下:

#define DEFAULT_DISCOVERABLE_MODE             GAP_ADTYPE_FLAGS_LIMITED

uint16 gapRole_AdvertOffTime = 0;
GAPRole_SetParameter( GAPROLE_ADVERT_OFF_TIME, sizeof( uint16 ), &gapRole_AdvertOffTime );//GAPROLE_ADVERT_OFF_TIME设置的时间单位是ms,默认是30s

uint16 ADV_TIMEOUT = 30;
GAP_SetParamValue( TGAP_LIM_ADV_TIMEOUT, ADV_TIMEOUT );//设置的单位是s,不设置的话,默认是180s


2.广播使能开启之后,限制广播在 20s 之后停止,然后过 15s 之后自动重新广播,如此反复。

#define DEFAULT_DISCOVERABLE_MODE             GAP_ADTYPE_FLAGS_LIMITED

uint16 gapRole_AdvertOffTime = 15000;
GAPRole_SetParameter( GAPROLE_ADVERT_OFF_TIME, sizeof( uint16 ), &gapRole_AdvertOffTime );//GAPROLE_ADVERT_OFF_TIME设置的时间单位是ms,默认是30s

uint16 ADV_TIMEOUT = 20;
GAP_SetParamValue( TGAP_LIM_ADV_TIMEOUT, ADV_TIMEOUT );//设置的单位是s,不设置的话,默认是180s



另外,该模式下设置广播间隔方法如下:

GAP_SetParamValue( TGAP_LIM_DISC_ADV_INT_MIN, advInt );//单位是0.625ms
GAP_SetParamValue( TGAP_LIM_DISC_ADV_INT_MAX, advInt );//单位是0.625ms



普通可发现模式  (GAP_ADTYPE_FLAGS_GENERAL)


若将实例代码段中的DEFAULT_DISCOVERABLE_MODE设置为GAP_ADTYPE_FLAGS_GENERAL,设置的代码如下:

#define DEFAULT_DISCOVERABLE_MODE             GAP_ADTYPE_FLAGS_GENERAL

普通可发现模式是用的最多的模式,在该模式下,我们可以设置广播持续时间,设置方法如下:

GAP_SetParamValue( TGAP_GEN_DISC_ADV_MIN, DEFAULT_ADV_DURATION );

我们看一下TGAP_GEN_DISC_ADV_MIN的介绍,仍然在Gap.h中,如下:

#define TGAP_GEN_DISC_ADV_MIN          0  //!< Minimum time to remain advertising, when in Discoverable mode (mSec).  Setting this parameter to 0 turns off the timeout (default).

从注释可以看到如果设置DEFAULT_ADV_DURATION为0,那就关闭了超时,也就是会一直持续的广播(当然前提是应用部分没有去主动使能关闭广播)。这个时候GAPROLE_ADVERT_OFF_TIME就无效了,因为持续广播时不会触发GAP_END_DISCOVERABLE_DONE_EVENT这个事件(该事件只有在广播关闭的时候才会发送给应用层,并在peripheral.c中进行接收处理,这是唯一处理GAPROLE_ADVERT_OFF_TIME的地方)。


接下来直接介绍几种使用场景:


1.最常用的场景,一直持续广播

#define DEFAULT_DISCOVERABLE_MODE             GAP_ADTYPE_FLAGS_GENERAL
// Duration of slow advertising duration in ms (set to 0 for continuous advertising)
#define DEFAULT_SLOW_ADV_DURATION             0
GAP_SetParamValue( TGAP_GEN_DISC_ADV_MIN, DEFAULT_SLOW_ADV_DURATION );

2.普通可发现模式下的限时广播,使能打开广播后限制20s后停止广播,而且不再自动重新广播。

#define DEFAULT_DISCOVERABLE_MODE             GAP_ADTYPE_FLAGS_GENERAL
// Duration of advertising duration in ms (set to 0 for continuous advertising)
#define DEFAULT_ADV_DURATION             20000
GAP_SetParamValue( TGAP_GEN_DISC_ADV_MIN, DEFAULT_ADV_DURATION );
uint16 gapRole_AdvertOffTime = 0;
GAPRole_SetParameter( GAPROLE_ADVERT_OFF_TIME, sizeof( uint16 ), &gapRole_AdvertOffTime );

3.循环间断限时广播,使能打开广播之后,广播20s,然后停止广播,过10s之后自动重新开始广播,如此反复。

#define DEFAULT_DISCOVERABLE_MODE             GAP_ADTYPE_FLAGS_GENERAL
// Duration of slow advertising duration in ms (set to 0 for continuous advertising)
#define DEFAULT_ADV_DURATION             20000
GAP_SetParamValue( TGAP_GEN_DISC_ADV_MIN, DEFAULT_ADV_DURATION );
uint16 gapRole_AdvertOffTime = 10000;
GAPRole_SetParameter( GAPROLE_ADVERT_OFF_TIME, sizeof( uint16 ), &gapRole_AdvertOffTime );

普通可发现模式修改广播间隔的方法如下:

GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MIN, advInt );//单位是0.625ms
GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MAX, advInt );	//单位是0.625ms


参考博文:http://blog.youkuaiyun.com/zhuangjitongxue/article/details/49805595

<think> 我们使用中文回答 问题:蓝牙hcitool 和hciconfig命令可以如何通过HCI命令修改蓝牙广播间隔? 回答: 在Linux系统中,可以使用`hcitool`和`hciconfig`工具来配置蓝牙设备。然而,直接使用这些工具修改蓝牙广播间隔并不是它们直接支持的功能,但我们可以通过发送自定义的HCI命令来实现。 HCI(Host Controller Interface)是主机与蓝牙控制器之间通信的接口。我们可以使用`hcitool cmd`命令发送原始的HCI命令。 修改广播间隔涉及到LE(低功耗蓝牙广播参数。具体来说,我们可以使用HCI命令设置广播参数,其中包括广播间隔。 设置广播参数的HCI命令是OGF=0x08, OCF=0x0006(HCI LE Set Advertising Parameters),其命令格式如下: ``` OCF: 0x0006 OGF: 0x08 (因此Opcode = 0x2006) 参数格式(共15个字节): - Advertising_Interval_Min: 2字节(单位:0.625ms) - Advertising_Interval_Max: 2字节(单位:0.625ms) - Advertising_Type: 1字节 - Own_Address_Type: 1字节 - Peer_Address_Type: 1字节 - Peer_Address: 6字节 - Advertising_Channel_Map: 1字节 - Advertising_Filter_Policy: 1字节 ``` 其中,广播间隔的最小值和最大值(Advertising_Interval_Min和Advertising_Interval_Max)决定了广播间隔的范围。注意,这两个值必须在0x0020(20ms)到0x4000(10.24s)之间,并且最大值必须大于等于最小值。 例如,如果我们想将广播间隔设置为100ms,那么我们可以将Advertising_Interval_Min和Advertising_Interval_Max都设置为100/0.625=160(即0x00A0)。 但是,请注意,`hcitool`和`hciconfig`在较新的Linux发行版中已经被弃用,推荐使用`bluetoothctl`和`btmgmt`。不过,如果系统仍然支持`hcitool`,我们可以这样发送命令: 1. 首先,确保蓝牙设备处于关闭状态: ``` hciconfig hci0 down ``` 2. 使用`hcitool cmd`发送设置广播参数的HCI命令: ``` hcitool cmd 0x08 0x0006 A0 00 A0 00 03 00 00 00 00 00 00 00 00 07 00 ``` 这里我们解释一下这个命令: - 0x08 0x0006:表示OGF和OCF。 - A0 00:Advertising_Interval_Min = 0x00A0(即160,160*0.625=100ms) - A0 00:Advertising_Interval_Max = 0x00A0(100ms) - 03:Advertising_Type(这里设置为可连接的非定向广播,即ADV_IND) - 00:Own_Address_Type(使用公共地址) - 00:Peer_Address_Type(公共地址) - 00 00 00 00 00 00:Peer_Address(由于是非定向,设置为0) - 07:Advertising_Channel_Map(使用37,38,39三个信道) - 00:Advertising_Filter_Policy(允许任何设备扫描和连接) 3. 然后,我们可以设置广播数据(可选)并开启广播。 4. 最后,启动蓝牙设备并开启广播: ``` hciconfig hci0 up hciconfig hci0 leadv ``` 注意:由于不同版本的蓝牙控制器可能对参数有不同要求,请参考蓝牙核心规范。另外,使用`hcitool`需要root权限。 由于`hcitool`在后续版本中被弃用,如果无法使用,可以考虑使用`btmgmt`工具。在`btmgmt`中,可以通过`adv-params`命令设置广播间隔,例如: btmgmt adv-params 100 100 0 00 但是,具体命令参数请参考`btmgmt`的帮助文档。 因此,通过上述HCI命令,我们可以修改蓝牙广播间隔。 但是,请注意:直接使用HCI命令需要了解蓝牙协议细节,且不同设备可能有不同的兼容性。 §§相关问题§§ 1. 在使用hcitool发送HCI命令时,如何确定具体的OGF和OCF值? 2. 除了广播间隔,HCI LE Set Advertising Parameters命令还可以设置哪些广播参数? 3. 在较新的Linux系统中,推荐使用哪些工具替代hcitool和hciconfig来配置蓝牙? 4. 如果设置广播间隔为100ms,为什么在命令中要传递0x00A0而不是100? 5. 在设置广播参数后,如何确认设置已经生效? </think>### 如何通过 HCI 命令修改蓝牙广播间隔 在 Linux 中,可以使用 `hcitool` 和 `hciconfig` 配合 HCI 原始命令修改蓝牙广播间隔。以下是详细步骤: #### 核心原理 通过 `hcitool cmd` 发送 HCI 命令 `LE Set Advertising Parameters` (OGF=0x08, OCF=0x0006),其参数包含广播间隔(单位:0.625ms)。公式为: ``` 广播间隔 (ms) = 参数值 × 0.625 ``` #### 操作步骤 1. **关闭蓝牙控制器**(确保配置前停止广播): ```bash sudo hciconfig hci0 down ``` 2. **设置广播参数**(关键步骤): ```bash sudo hcitool cmd 0x08 0x0006 \ [Min_Interval_LSB] [Min_Interval_MSB] \ [Max_Interval_LSB] [Max_Interval_MSB] \ [其他参数...] ``` - **间隔值计算**(以 100ms 为例): ``` 100ms / 0.625ms = 160 → 十六进制 0x00A0 LSB = 0xA0, MSB = 0x00 ``` - **完整示例**(设置 100ms 广播间隔): ```bash sudo hcitool cmd 0x08 0x0006 \ A0 00 A0 00 \ # 最小/最大间隔=100ms 00 00 00 00 00 00 00 00 00 00 00 ``` *注:后 11 字节为其他参数广播类型、地址类型等),此处用 0 填充默认值* 3. **启用广播**: ```bash sudo hciconfig hci0 up sudo hciconfig hci0 leadv # 开启低功耗广播 ``` #### 验证方法 1. 检查 HCI 事件: ```bash sudo hcidump -t -x ``` 观察返回事件 `Command Complete`(事件码 0x0E)是否包含状态码 0x00(成功)。 2. 使用蓝牙扫描工具(如 `hcitool lescan`)实测广播间隔。 #### 注意事项 1. **有效范围**:广播间隔需在 20ms (0x0020) 至 10.24s (0x4000) 之间 2. **参数对齐**:最小间隔 ≤ 最大间隔 3. **权限要求**:所有命令需 `sudo` 权限执行 4. **兼容性**:不同蓝牙芯片可能对参数有额外限制
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值