
HCI_LE_Set_Periodic_Advertising_Parameters 命令是蓝牙核心规范(Bluetooth Core Specification)中定义的一个主机控制器接口(HCI)命令,用于设置周期性广播(Periodic Advertising)的参数。周期性广播是低功耗蓝牙(BLE)5.1及更高版本中引入的一种广播模式,它允许设备以固定的间隔重复发送广播数据,适用于需要定期广播信息的场景,如传感器数据广播。
HCI_LE_Set_Periodic_Advertising_Parameters命令用于设置BLE设备的周期性广播参数。该命令通过HCI发送给BLE控制器,以配置设备在周期性广播模式下的行为。周期性广播是一种节能的广播模式,适用于需要持续广播数据但不需要频繁建立连接的应用场景。

BLUETOOTH CORE SPECIFICATION Version 5.4 | Vol 4, Part E page 2471
命令操作码 (OCF): 该命令有2个版本,一种是通过操作码组(OGF)和操作码(OCF)的组合来表示,即0x08(OGF,表示LE控制器命令组)和0x003E(OCF,表示设置周期性广播参数命令的指令部分)。另一种表示方式是直接给出完整的命令代码0x86(这是将OGF和OCF组合在一起的结果,但通常只在某些上下文中使用,如HCI命令的二进制表示)。
Num_Subevents、Subevent_Interval、Response_Slot_Delay、Response_Slot_Spacing和Num_Response_Slots等。这些参数提供了对周期性广播行为的更精细控制,例如允许设备在单个广播周期内发送多个子事件,以及控制响应槽的延迟和间隔等。(注意:并非所有这些参数都一定在5.1中引入,但它们是在后续版本中相对于5.0增加的扩展参数的一部分)。发送方:主机(Host)
接收方:BLE控制器(BLE Controller)
接口:主机控制器接口(HCI)
响应:该命令执行后,BLE控制器通常会返回一个状态码,以指示命令是否成功执行。状态码0x00表示成功,而其他值则表示不同类型的错误。
HCI_LE_Set_Periodic_Advertising_Parameters命令通常包含以下几个关键部分:
对应V2版本的命令,还包含以下参数:
以下是一个通用的HCI_LE_Set_Periodic_Advertising_Parameters命令的示例格式(请注意,实际使用时需要参考特定蓝牙协议栈的文档):
HCI_LE_Set_Periodic_Advertising_Parameters(
OpCode: 0xXXXX, // 操作码,具体值由蓝牙核心规范定义
Parameter_Length: X bytes, // 参数长度,根据实际参数数量和大小确定
Advertising_Handle: 0xYYYY, // 广播句柄,用于标识特定的广播集
Periodic_Advertising_Interval_Min: N, // 周期性广播间隔最小值
Periodic_Advertising_Interval_Max: M // 周期性广播间隔最大值
// 其他可能参数(取决于实现):
// Num_Subevents, Subevent_Interval, Response_Slot_Delay, Response_Slot_Spacing, Num_Response_Slots, ...
);在此示例中,0xXXXX是操作码的占位符,X bytes是参数长度的占位符,0xYYYY是广播句柄的示例值,N和M分别是周期性广播间隔的最小值和最大值的示例值。其他可能参数部分取决于蓝牙协议栈的具体实现和版本。
请注意,由于蓝牙BLE技术的不断发展和更新,新的参数和功能可能会被引入。因此,在实际开发中,建议参考最新的蓝牙核心规范和特定蓝牙协议栈的文档来获取最准确和详细的信息。
HCI_LE_Set_Periodic_Advertising_Parameters命令通常包含以下参数(注意:具体参数可能因蓝牙规范版本或设备实现的不同而有所差异)。
Advertising_Handle用于标识要配置的周期性广播实例的唯一句柄。这个句柄在蓝牙设备中是唯一的,用于控制器(通常是BLE芯片或模块)用来区分和管理不同广播集。当设备需要配置或管理多个周期性广播时,每个广播都会有一个唯一的Advertising_Handle。

Advertising_Handle对应的广播集不存在,那么控制器将不会执行该命令的配置操作。Unknown Advertising Identifier(未知广播标识符),其错误代码值为0x42。Periodic_Advertising_Interval_Min 和 Periodic_Advertising_Interval_Max 这两个参数用于定义周期性广播的最小和最大发送间隔。

Unknown Advertising Identifier(未知广播标识符),其错误代码值为0x42,表示不支持的功能或参数值。Periodic_Advertising_Properties参数是一个2个字节的字段,用于在周期性广播中指定广播数据包的格式和内容。通过设置不同的位,可以指示是否包含传输功率值以及其他可能的未来功能。这对于确保广播数据包的有效性和兼容性至关重要,并允许设备根据需要进行定制化的广播。

描述:该参数用于指示在广播数据包(PDU)中应该包含哪些字段。它是周期性广播属性的一部分,用于定义广播的类型(例如连接性广播或非连接性广播)以及是否包含其他特定信息,如传输功率值。
Include TxPower in the advertising PDU:如果第6位被设置(即值为1),则表示广播数据包中应包含传输功率值。传输功率值通常用于指示设备发送广播数据时的功率级别,这有助于接收方估计信号强度和可能的连接质量。
Reserved for future use:这些位目前被保留以供未来使用。这意味着在未来的蓝牙规范或设备实现中,这些位可能会被赋予特定的含义或功能。因此,在实现当前设备时,这些位应被设置为0(或根据具体规范进行初始化),并且不应被用于任何当前定义的功能。
在BLE的周期性广播中,使用子事件可以允许设备在单个广播事件中发送多个不同类型或内容的数据包。这对于需要向扫描者提供多种信息或数据更新的设备来说是非常有用的。然而,如果不需要发送多个子事件,就可以将Num_Subevents设置为0,并忽略与子事件相关的其他参数。

Num_Subevents参数用于指定每个周期性广播事件中要传输的子事件数量。子事件是广播数据包的一部分,它们可以在一个广播事件中连续发送。
Num_Subevents的值为0x00(即0)时,表示没有子事件需要传输。在这种情况下,与子事件相关的其他参数,如Subevent_Interval(子事件间隔)、Response_Slot_Delay(响应槽延迟)、Response_Slot_Spacing(响应槽间隔)和Num_Response_Slots(响应槽数量),都将被忽略。这是因为没有子事件需要发送,所以这些参数的设置就没有意义了。
Subevent_Interval 参数标识了周期性广播响应(PAwR)中子事件之间的时间间隔。

条件:该时间间隔应小于或等于广播集中周期性广播最小间隔(Periodic_Advertising_Interval_Min)除以广播集中子事件数量(Num_Subevents)的结果。
换句话说,如果想在单个周期性广播事件中发送多个子事件,那么每个子事件之间的时间间隔(Subevent_Interval)必须足够短,以确保所有子事件都能在给定的周期性广播间隔内发送完毕。这个间隔受到广播集中周期性广播最小间隔和子事件数量的限制。
例如,如果
Periodic_Advertising_Interval_Min是1秒(1000毫秒),并且想发送4个子事件(Num_Subevents为4),那么每个子事件之间的最大时间间隔(Subevent_Interval)将是250毫秒(1000毫秒 / 4)。这意味着必须在250毫秒内发送每个子事件,以确保所有子事件都能在1秒的周期性广播间隔内发送完毕。
在BLE的周期性广播中,如果广播者希望接收来自扫描者的响应(例如,连接请求或扫描响应),它可以在广播数据包中包含一个或多个响应插槽。这些响应插槽为扫描者提供了在特定时间窗口内发送响应的机会。Response_Slot_Delay 参数标识了在子事件开始时广播包开始与第一个响应插槽开始时之间的时间间隔。

条件:这个时间间隔应小于子事件间隔(Subevent_Interval)。
Response_Slot_Delay 参数定义了从子事件中的广播包开始到第一个响应插槽开始的时间。这个时间间隔允许扫描者在接收到广播包后有足够的时间准备并发送响应。然而,为了确保所有响应插槽都能在子事件间隔内被有效利用,Response_Slot_Delay 必须小于 Subevent_Interval。
例如,如果
Subevent_Interval是 100 毫秒,那么Response_Slot_Delay必须小于 100 毫秒,以确保第一个响应插槽在子事件结束之前开始。这样,扫描者就有机会在子事件间隔内发送响应,而不会因为延迟过长而错过响应插槽。
3.7. Response_Slot_Spacing在BLE的周期性广播中,广播者可以配置多个响应插槽以接收来自扫描者的响应。这些响应插槽在广播事件中按顺序排列,每个插槽都提供了一个特定的时间窗口供扫描者发送响应。Response_Slot_Spacing 参数用于确定两个连续响应插槽之间的时间间隔。这个时间间隔必须足够长,以确保扫描者有足够的时间来准备并发送响应,但也不能太长,以免浪费广播事件中的时间。

Response_Slot_Spacing 参数标识了两个连续响应插槽开始时间之间的时间间隔。
条件:该时间间隔应小于或等于 10 × (Subevent_Interval - Response_Slot_Delay) / Num_Response_Slots 的结果。如果 Num_Response_Slots 参数设置为 1,则控制器应忽略 Response_Slot_Spacing 参数。
如果广播者只配置了一个响应插槽(Num_Response_Slots 为 1),则不需要考虑响应插槽之间的间隔,因为只有一个插槽可用。在这种情况下,控制器会忽略 Response_Slot_Spacing 参数。
然而,如果配置了多个响应插槽,则必须根据 Subevent_Interval(子事件间隔)和 Response_Slot_Delay(响应插槽延迟)来计算 Response_Slot_Spacing。这个计算确保了所有响应插槽都能在子事件间隔内被有效利用,同时给扫描者提供了足够的时间来发送响应。
在BLE的周期性广播中,广播者可以通过配置响应插槽来接收来自扫描者的响应。这些响应插槽为扫描者提供了在特定时间窗口内发送响应的机会。Num_Response_Slots 参数允许广播者指定它希望在子事件中接收多少响应。

Num_Response_Slots 参数标识了在子事件中配置的响应插槽的数量。
Num_Response_Slots 的值为 0x00,则表示在子事件中没有配置任何响应插槽。
如果 Num_Response_Slots 设置为 0x00,则意味着广播者不希望接收任何响应,因此不需要配置响应插槽。在这种情况下,Response_Slot_Delay(响应插槽延迟)和 Response_Slot_Spacing(响应插槽间隔)参数就不再适用,因为它们与响应插槽的配置和使用直接相关。
在BLE中配置周期性广播时可能遇到的错误情况和相应的错误代码。以下是这些描述的解释和详细阐述。
1. Invalid HCI Command Parameters (0x12):
Advertising_Handle 标识的广播集被配置为可扫描、可连接、传统或匿名广播,并且此时尝试将其配置为周期性广播,则控制器将返回此错误代码。2. Command Disallowed (0x0C):
3. Memory Capacity Exceeded (0x07):
Advertising_Handle 没有标识一个已经配置为周期性广播的广播集,并且控制器当前无法支持更多的周期性广播,则控制器将返回此错误代码。4. Packet Too Long (0x45):
Periodic_Advertising_Interval_Max 指定的周期性广播间隔内能够传输的最大长度,则控制器将返回此错误代码。5. 关于LE Coded PHY的编码:
请注意,这些错误代码和条件是基于蓝牙核心规范中的定义,并且可能因不同的蓝牙控制器实现而有所差异。因此,在实际应用中,建议查阅特定蓝牙控制器的文档以获取准确的错误代码和条件信息。
当HCI_LE_Set_Periodic_Advertising_Parameters命令执行完成后,蓝牙控制器将生成一个HCI_Command_Complete事件(Event Code 0x0E),其中包含状态码和广播句柄。如果命令成功执行,状态码为 0x00。如果失败,状态码将指示失败的原因。

HCI_Command_Complete 事件:包含了一个状态码,用于指示命令是否成功执行以及任何可能的错误。
在实际应用中,当主机发送HCI_LE_Set_Periodic_Advertising_Parameters命令后,会等待接收HCI_Command_Complete事件以确认命令的执行状态。如果命令成功执行,主机可以继续发送其他相关命令(例如,启用周期性广播、设置广播数据等)。如果命令执行失败,主机则需要根据状态码的值采取适当的错误处理措施。
返回HCI_Command_Complete事件还会包含Advertising_Handle参数,用于在后续的操作中引用或管理这个特定的周期性广播实例。例如,当需要停止周期性广播时,可以使用这个句柄作为参数来发送相应的HCI命令。

以下是HCI_LE_Set_Periodic_Advertising_Parameters命令的执行流程归纳。
Advertising_Handle,用于标识这个周期性广播实例。HCI_LE_Set_Periodic_Advertising_Parameters命令的数据包。数据包包括操作码(OpCode)、参数长度(Parameter Length)和具体的参数值。HCI_Command_Complete事件。Advertising_Handle。HCI_Command_Complete事件。Advertising_Handle。0x00表示命令成功执行。Advertising_Handle以便后续使用。Advertising_Handle来启动周期性广播。HCI_LE_Periodic_Advertising_Enable命令来实现。下面提供简化的伪代码示例来演示HCI_LE_Set_Periodic_Advertising_Parameters命令的执行流程。
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
// 假设我们有一个函数来发送HCI命令并接收响应
// 这个函数在实际应用中需要根据具体的蓝牙栈和硬件平台来实现
int send_hci_command_and_wait_for_response(uint16_t opcode, uint8_t *params, int param_len, uint8_t *response, int *response_len) {
// 这里省略了实际的发送和接收逻辑
// 假设函数返回0表示成功,非0表示失败
return 0; // 伪代码:总是成功
}
// 周期性广播参数结构体
typedef struct {
uint16_t adv_interval_min;
uint16_t adv_interval_max;
...
} periodic_adv_params_t;
int main() {
int dev_id = hci_get_route(NULL);
if (dev_id < 0) {
perror("Failed to get HCI device id");
return EXIT_FAILURE;
}
// 配置周期性广播参数
periodic_adv_params_t adv_params = {
.adv_interval_min = 0x0800, // 最小广播间隔(单位:0.625ms)
.adv_interval_max = 0x0800, // 最大广播间隔(单位:0.625ms,这里设置为与最小间隔相同以实现固定间隔)
.adv_type = 0x02, // 周期性不可连接无定向广播
.own_address_type = 0x00, // 公共设备地址
.direct_address_type = 0x00,// 不使用直接地址
.direct_address = {{0}}, // 不使用直接地址
.channel_map = 0x07, // 使用所有3个广播通道
.filter_policy = 0x00 // 允许所有白名单外的设备扫描和连接请求(对于周期性广播,连接请求通常被忽略)
};
// 构建HCI_LE_Set_Periodic_Advertising_Parameters命令
uint8_t cmd_buf[HCI_MAX_CMD_LEN];
uint8_t *ptr = cmd_buf;
*ptr++ = 0x02; // OGF: Link Control Commands
*ptr++ = 0x0020; // OCF: LE Set Periodic Advertising Parameters
*ptr++ = sizeof(adv_params); // 参数长度(不包括操作码和参数长度字段本身)
// 复制参数到命令缓冲区(注意:这里需要根据实际参数结构进行字节序调整,可能涉及到大端/小端转换)
memcpy(ptr, &adv_params, sizeof(adv_params));
ptr += sizeof(adv_params);
// 发送命令并等待响应
uint8_t response_buf[HCI_MAX_EVENT_LEN];
int response_len;
int result = send_hci_command_and_wait_for_response(
hci_opcode_pack(0x02, 0x0020), // 操作码
cmd_buf, sizeof(cmd_buf) - (ptr - cmd_buf), // 参数和数据长度
response_buf, &response_len
);
if (result != 0) {
perror("Failed to send HCI_LE_Set_Periodic_Advertising_Parameters command");
return EXIT_FAILURE;
}
// 解析响应
uint8_t status = response_buf[1];
uint16_t advertising_handle = (response_buf[3] << 8) | response_buf[2]; // 假设广播句柄在响应的第2和第3个字节(大端格式)
if (status == 0x00) {
printf("Periodic advertising parameters set successfully. Advertising Handle: 0x%04X\n", advertising_handle);
// 使用advertising_handle启动周期性广播(这里省略了启动广播的代码)
} else {
printf("Failed to set periodic advertising parameters. Status: 0x%02X\n", status);
// 根据错误代码采取适当的错误处理措施
}
return EXIT_SUCCESS;
}请注意,这只是一个概念性的示例,并不能直接在任何平台上运行。实际使用中HCI_LE_Set_Periodic_Advertising_Parameters命令的执行流程是比较复杂的,涉及到与蓝牙硬件的底层交互,通常需要使用特定的蓝牙协议栈(如Bluedroid、BlueZ或厂商提供的SDK)和硬件抽象层(HAL)。此外,不同的蓝牙协议栈和硬件平台可能有不同的API和接口。
重要说明:
send_hci_command_and_wait_for_response函数是一个占位符,需要根据你的蓝牙协议栈和硬件平台来实现它。这通常涉及到与蓝牙驱动程序的交互,可能涉及到套接字编程、事件循环和回调等。
periodic_adv_params_t结构体是根据蓝牙核心规范中的参数定义的,但实际的参数结构和大小可能因蓝牙协议栈的实现而异。可能需要根据具体蓝牙协议栈的文档来调整这个结构体。
HCI_LE_Periodic_Advertising_Enable命令来启动广播。这个命令的发送和响应处理与上面的示例类似,但需要使用不同的操作码和参数。
bluetooth/bluetooth.h、bluetooth/hci.h和bluetooth/hci_lib.h),这些头文件通常是在Linux系统上可用的。如果在其他平台上工作,可能需要找到相应的头文件和库。
HCI_LE_Set_Periodic_Advertising_Parameters命令在BLE技术中主要用于配置和管理周期性广播,以下是其关键应用场景的梳理。
HCI_LE_Set_Periodic_Advertising_Parameters命令在BLE技术中具有广泛的应用场景,包括周期性广播设置、设备发现优化、能源管理、支持特定通信需求以及适用于BLE 5.1及更高版本的周期性广播模式。这些应用场景使得BLE技术更加灵活和高效,推动了其在物联网、智能家居等领域的广泛应用。
以下是对HCI_LE_Set_Periodic_Advertising_Parameters命令使用注意事项的整理归纳。
综上所述,使用HCI_LE_Set_Periodic_Advertising_Parameters命令时,需关注参数验证、广播状态管理、兼容性与电源效率、错误处理与隐私保护、事件掩码以及周期性广播使用等多个方面,以确保命令正确执行,满足实际应用需求。