
HCI_LE_Set_Periodic_Advertising_Data 命令是低功耗蓝牙(BLE)核心规范中定义的一个主机控制接口(HCI)命令,用于设置周期性广播的数据。周期性广播是蓝牙5.1引入的一种新型广播模式,用于以固定间隔发送相同的数据包,适用于需要频繁发送相同信息的应用场景,例如环境传感器数据广播。
HCI_LE_Set_Periodic_Advertising_Data命令的主要目的是设置用于周期性广播协议数据单元(PDU)的数据。在发出此命令之前,必须使用HCI_LE_Set_Periodic_Advertising_Parameters命令为具有特定Advertising_Handle的广播集配置周期性广播参数(如间隔、持续时间等)。【0x003E/0x86】HCI_LE_Set_Periodic_Advertising_Parameters 命令全面解析_read periodic advertiser lis size-CSDN博客

在使用HCI_LE_Set_Periodic_Advertising_Data命令时,需要特别注意广播数据的长度和格式。主机应该确保只包含重要的数据部分,并根据需要分段设置数据。同时,还需要检查广播集的最大数据长度和当前可用的内存资源,以避免遇到内存容量超出的错误。通过仔细规划和错误处理,可以确保周期性广播的有效性和可靠性。
HCI_LE_Set_Periodic_Advertising_Data命令的行为取决于周期性广播的当前状态。在启用时,新数据将立即生效;在进行中时,控制器可能会选择使用旧数据或新数据;在禁用时,数据将被存储以供将来使用;在广播集移除时,所有数据都将被丢弃。了解这些行为对于正确配置和管理周期性广播至关重要。
HCI_LE_Set_Periodic_Advertising_Data命令时,蓝牙控制器将在后续的周期性广播事件中使用新的广播数据。这意味着,一旦广播数据被更新,所有后续的周期性广播都将包含这些新数据。HCI_LE_Set_Periodic_Advertising_Data命令时,周期性广播事件正在进行中,蓝牙控制器可能会选择在该事件中使用旧数据或新数据。规范中并没有明确要求控制器必须选择哪一种数据,因此这取决于具体实现。不过,从用户体验和数据一致性的角度来看,最好确保在广播数据更新时,不会有正在进行中的广播事件受到影响,或者至少这种行为应该是可预测的。HCI_LE_Set_Periodic_Advertising_Data命令时,蓝牙控制器将不会立即使用新数据。相反,它会存储这些数据,并在周期性广播再次为该广播集启用时使用它们。这意味着,即使广播当前未在运行,也可以预先设置广播数据,以便在需要时快速启用。在BLE的周期性广播中,只有重要的数据部分应该被包含在广播数据包中。这些数据部分是根据蓝牙核心规范([Vol 3] Part C, Section 11)中定义的格式来组织的。也就是说,在构建广播数据时,需要仔细选择包含哪些信息,以确保它们既符合规范,又能有效地传达所需的内容。蓝牙规范中的广播和扫描响应数据格式研究-CSDN博客
HCI_LE_Set_Periodic_Advertising_Data命令中的Operation参数来分段设置周期性广播数据。这允许主机在多个操作中逐步构建完整的广播数据集,而不是一次性发送所有数据。这种方法的优点是可以减少单个命令的数据负载,并提高命令处理的灵活性。Advertising_Handle参数标识的广播集所允许的最大长度。这个最大长度可以通过LE Read Maximum Advertising Data Length命令(见第7.8.57节)来查询。【0x003A】HCI_LE_Read_Maximum_Advertising_Data_Length命令全面解析-CSDN博客如果尝试设置的广播数据总长度超过了广播集的容量或当前可用的内存量,那么所有已设置的数据都将被丢弃,并且蓝牙控制器将返回错误代码Memory Capacity Exceeded(0x07)。Memory Capacity Exceeded错误时,主机应该采取适当的措施来处理这种情况。这可能包括减少广播数据的量、优化数据格式、检查并释放不必要的内存资源,或者尝试在稍后的时间点重新设置广播数据(如果此时内存资源可能已经变得可用)。Periodic_Advertising_Interval_Max。如果数据的总长度超过了上述任一限制,那么所有已设置的数据都将被丢弃,并且蓝牙控制器将返回错误代码Packet Too Long(0x45)。这意味着,在设置周期性广播数据时,需要考虑到广播间隔和数据长度的匹配,以确保数据能够在规定的时间内被完整传输。
当使用LE Coded PHY进行广播时,编码方式的选择取决于当前的广播参数:
Operation参数的值是0x01或0x03,则表示要开始设置新数据。Operation参数的值是0x04,则行为就跟再次发送当前的周期性广播数据一样。Operation是0x04,但周期性广播对于该广播集是禁用的,或者广播集中不包含数据,或者Advertising_Data_Length(广播数据长度)不为零,则控制器应返回错误代码Invalid HCI Command Parameters(0x12)。Operation不是0x03或0x04,并且Advertising_Data_Length为零,则控制器也应返回错误代码Invalid HCI Command Parameters(0x12)。Operation的值不是0x03或0x04,则控制器应返回错误代码Command Disallowed(0x0C)。Advertising_Handle参数对应的广播集不存在,则控制器应返回错误代码Unknown Advertising Identifier(0x42)。了解这些规则和限制对于正确设置和管理BLE设备的周期性广播数据至关重要。通过遵循这些规则,可以确保广播数据的正确性和有效性,同时避免不必要的错误和通信问题。
以下是HCI_LE_Set_Periodic_Advertising_Data命令的详细格式说明。
HCI_LE_Set_Periodic_Advertising_Data命令,OCF的具体值根据蓝牙核心规范的不同版本可能有所不同。具体值应参考所使用的蓝牙核心规范的版本。HCI_LE_Set_Periodic_Advertising_Data命令的参数通常包括以下几个部分:
以下是一个通用的HCI_LE_Set_Periodic_Advertising_Data命令的示例格式(请注意,实际使用时需要参考特定蓝牙协议栈的文档):
HCI_LE_Set_Periodic_Advertising_Data(
OpCode: 0xXXXX, // 操作码,具体值由蓝牙核心规范定义
Parameter_Length: X bytes, // 参数长度,根据实际参数数量和大小确定
Operation: 0xYY, // 操作类型,具体值应参考蓝牙核心规范
Advertising_Handle: 0xZZZZ, // 广播句柄,用于标识特定的广播集
Advertising_Data_Length: N, // 广播数据长度
Advertising_Data: // 广播数据本身,长度为N字节
... // 广播数据的具体内容
);在上面的示例中,OpCode是操作码,由OGF和OCF组成(在实际发送时,由于OGF在BLE命令中通常是固定的0x08,所以有时只明确给出OCF);Parameter_Length表示后续参数的总长度;Operation表示要执行的操作类型;Advertising_Handle是广播句柄;Advertising_Data_Length是广播数据的长度;Advertising_Data是广播数据本身。
在HCI_LE_Set_Periodic_Advertising_Data命令中,Advertising_Handle是一个唯一的标识符,用于区分设备上的不同广播集或广播实例。在BLE设备中,可以配置多个广播集,每个广播集都包含一组特定的广播参数和数据。Advertising_Handle就是用来标识这些不同广播集的。

在发送HCI_LE_Set_Periodic_Advertising_Data命令时,必须确保指定的Advertising_Handle是有效的,并且与要更新的广播集相匹配。如果Advertising_Handle无效或不存在,BLE控制器可能会返回错误代码,指示未知的广播标识符。
Operation(操作)用于明确指示蓝牙设备或控制器要执行的具体操作类型。通过设置Operation字段的值,蓝牙设备可以灵活地控制周期性广播数据的传输和更新。

Advertising_Data_Length表示广播数据的长度。它确保了BLE控制器在广播过程中能够准确地读取和发送指定长度的数据。如果数据长度超过BLE广播包的最大限制,则BLE控制器可能会忽略超出部分或返回错误。

注意:在发送设置广播数据的命令之前,应用层需要确保提供的广播数据符合BLE规范的要求,包括数据长度和内容。
Advertising_Data参数指定了要在周期性广播中发送的数据内容。广播数据的内容决定了其他BLE设备在扫描到该广播时能够获取到的信息。因此,正确设置广播数据对于设备发现、服务广播、设备配对与连接等过程至关重要。

在发送命令之前,应用层应进行参数验证以确保数据的正确性和合法性。如果命令执行失败,应用层需要根据错误代码进行相应的错误处理,并可能需要重试命令或采取其他恢复措施。
当HCI_LE_Set_Periodic_Advertising_Data命令执行完成后,会生成一个HCI_Command_Complete事件,这是BLE技术中常见的通信机制。
1. 事件代码
2. 参数:
3. 处理:
注意:
Status(状态码)是一个关键的返回参数,用于告知主机(Host)命令的执行结果。通过解析HCI_Command_Complete事件中的返回参数,主机可以了解命令的执行结果,并据此进行后续操作或错误处理。

HCI_LE_Set_Periodic_Advertising_Data命令的返回事件主要包括状态码,用于指示命令的执行结果。同时,根据具体实现和蓝牙协议栈的不同,还可能包含其他相关信息作为返回参数。在执行该命令时,应注意命令的执行时机、参数验证、兼容性和错误处理等方面的问题。
以下是HCI_LE_Set_Periodic_Advertising_Data命令的一般执行流程。
实现HCI_LE_Set_Periodic_Advertising_Data命令的执行流程,通常涉及与蓝牙硬件控制器进行低级别的通信。通常通过特定的蓝牙协议栈API或HCI库来完成,而不是直接操作硬件寄存器(尽管在某些嵌入式系统中可能会这样做)。
以下是一个简化的代码示例,模拟了上述流程的关键部分。请注意,这个示例并不包含实际的蓝牙通信代码,因为那通常依赖于特定的蓝牙协议栈或硬件抽象层(HAL)。此外,由于蓝牙协议栈和API的差异,实际代码可能会有所不同。
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
// 假设的HCI命令结构体
typedef struct {
uint16_t opcode; // 操作码
uint8_t param_len; // 参数长度
uint8_t advertising_data[252]; // 广播数据,最大长度为252字节
} HCI_LE_Set_Periodic_Advertising_Data_Cmd;
// 假设的HCI事件结构体
typedef struct {
uint8_t event_code; // 事件代码
uint16_t opcode; // 命令操作码
uint8_t status; // 状态码
} HCI_Command_Complete_Event;
// 假设的发送HCI命令函数(实际实现依赖于蓝牙协议栈或HAL)
bool send_hci_command(const void* cmd, uint16_t cmd_len);
// 假设的接收HCI事件函数(实际实现依赖于蓝牙协议栈或HAL)
bool receive_hci_event(HCI_Command_Complete_Event* event);
// 假设的启用周期性广播函数(实际实现依赖于蓝牙协议栈或HAL)
bool enable_periodic_advertising(uint16_t interval, uint8_t num_events);
int main() {
// 准备广播数据
uint8_t advertising_data[] = {
// 这里填写实际的广播数据,例如设备名称、服务UUID等
};
uint8_t data_len = sizeof(advertising_data);
// 构建HCI_LE_Set_Periodic_Advertising_Data命令
HCI_LE_Set_Periodic_Advertising_Data_Cmd cmd;
cmd.opcode = 0xXXXX; // 填写实际的操作码
cmd.param_len = data_len;
memcpy(cmd.advertising_data, advertising_data, data_len);
// 发送命令
if (!send_hci_command(&cmd, sizeof(cmd))) {
printf("Failed to send HCI_LE_Set_Periodic_Advertising_Data command.\n");
return -1;
}
// 接收HCI_Command_Complete事件
HCI_Command_Complete_Event event;
if (!receive_hci_event(&event)) {
printf("Failed to receive HCI_Command_Complete event.\n");
return -1;
}
// 检查状态码
if (event.status != 0x00) {
printf("HCI_LE_Set_Periodic_Advertising_Data command failed with status 0x%02X.\n", event.status);
return -1;
}
// 如果需要,启用周期性广播
uint16_t interval = 1600; // 例如,1.6秒的广播间隔
uint8_t num_events = 0xFF; // 例如,无限次广播事件
if (!enable_periodic_advertising(interval, num_events)) {
printf("Failed to enable periodic advertising.\n");
return -1;
}
printf("Periodic advertising data set and advertising enabled successfully.\n");
return 0;
}
// 以下是假设的函数的占位符实现,实际实现应依赖于蓝牙协议栈或HAL
bool send_hci_command(const void* cmd, uint16_t cmd_len) {
// 实际发送HCI命令的代码
return true; // 假设发送成功
}
bool receive_hci_event(HCI_Command_Complete_Event* event) {
// 实际接收HCI事件的代码
// 这里应该填充event结构体以反映实际接收到的数据
event->status = 0x00; // 假设命令成功
return true; // 假设接收成功
}
bool enable_periodic_advertising(uint16_t interval, uint8_t num_events) {
// 实际启用周期性广播的代码
return true; // 假设启用成功
}请注意,上述代码中的send_hci_command、receive_hci_event和enable_periodic_advertising函数都是假设的,需要根据所使用的蓝牙协议栈或硬件抽象层(HAL)进行实际实现。这些函数通常与蓝牙控制器进行通信,并处理低级别的蓝牙协议细节。
此外,操作码(opcode)和广播数据的格式也需要根据具体蓝牙核心规范进行正确设置。在实际应用中,应该参考蓝牙协议栈或HAL的文档来获取正确的操作码和广播数据格式。
以下是HCI_LE_Set_Periodic_Advertising_Data一些可能的使用场景。
HCI_LE_Set_Periodic_Advertising_Data在BLE技术中具有广泛的应用前景。开发者在开发BLE应用时,应根据具体的应用场景和需求来选择合适的命令和接口,并仔细配置广播参数以确保最佳的广播效果和能源消耗。
以下是一些关于HCI_LE_Set_Periodic_Advertising_Data建议的注意事项。
HCI_LE_Set_Periodic_Advertising_Parameters正确配置了广播集。Operation值(通常是0x01或0x03)。如果想重新发送当前的数据以更新数据标识符(DID),则应使用Operation值0x04,但前提是当前广播集是有效的,且满足其他相关条件。如果Advertising_Data_Length为零,且Operation不是用于开始新数据的值,则控制器将返回错误。Invalid HCI Command Parameters错误,则应检查Operation和Advertising_Data_Length的值是否正确。如果返回Unknown Advertising Identifier错误,则应检查Advertising_Handle是否有效。请注意,由于不同设备的蓝牙协议栈实现可能存在差异,因此在实际应用中,还需要参考具体设备的文档和指南来确保正确设置和使用HCI_LE_Set_Periodic_Advertising_Data命令。
综上所述,使用HCI_LE_Set_Periodic_Advertising_Data命令时需要谨慎处理各种参数和条件,以确保周期性广播的有效性和可靠性。通过遵循这些规则和限制,可以避免不必要的错误和通信问题,从而提高BLE设备的性能和用户体验。