HCI(Host Controller Interface,主机控制器接口)是一种标准化的通信协议,专门用于定义主机(Host)与控制器(Controller)之间的交互规则。它充当了高层软件与底层硬件之间的桥梁,确保指令和数据的可靠传输。
什么是HCI
HCI的核心作用是规范主机和控制器之间的通信接口。主机通常指运行高级协议栈和应用软件的处理器(如CPU),而控制器则是处理特定底层通信协议(如蓝牙射频、USB物理层)的硬件模块。HCI定义了双方交换命令、事件和数据的标准格式。
核心组件:
- 主机(Host):执行上层协议栈和应用逻辑。
- 控制器(Controller):负责底层信号处理和硬件驱动。
- HCI接口:统一的通信协议层,确保两者协同工作。
其协议栈模型可简化为:
控制器端 主机端
应用层 Application Layer
主机 Host
HCI接口 Host Controller Interface
控制器 Controller
物理层 Physical Layer
协议栈 Protocol Stack
驱动层 Driver
链路层 Link Layer
基带 Baseband
传输层 Transport Layer
UART/USB/SPI
应用场景
HCI概念广泛应用于多种通信协议中,主要实现方式包括:
HCI接口
├── 蓝牙HCI(主流应用)
├── USB HCI(较少直接使用)
└── 其他专有协议接口
典型应用:
- 蓝牙HCI:蓝牙协议栈中主机与蓝牙控制器之间的标准接口,用于设备配对、数据交换等。深入理解此类底层协议有助于优化网络/系统层面的通信性能。
- USB HCI:USB主机控制器接口,管理USB设备枚举和数据传输。
- 定制化协议:某些嵌入式或物联网设备会借鉴HCI设计私有接口。
蓝牙HCI接口
蓝牙HCI是HCI协议最典型的实现,构成了蓝牙协议栈的核心部分。
架构示意:
应用层
└── L2CAP(逻辑链路控制)
└── ACL/SCO数据通道
└── HCI层
└── 传输层(UART/USB/SPI)
└── 蓝牙控制器
数据包类型
蓝牙HCI定义了三种基本数据包类型,确保通信有序:
| 包类型 |
方向 |
用途 |
示例 |
| Command |
Host → Controller |
主机发送控制指令 |
复位、扫描 |
| Event |
Controller → Host |
控制器上报状态或结果 |
连接完成事件 |
| Data |
双向 |
传输应用数据 |
ACL/SCO数据 |
HCI数据包格式详解
Command包格式
Command包用于主机向控制器发送指令,结构如下:
// HCI Command包结构
typedef struct {
uint8_t packet_type; // 包类型:0x01 = Command
uint16_t opcode; // 操作码(OCF + OGF)
uint8_t parameter_length; // 参数长度
uint8_t parameters[]; // 参数数据(可变长度)
} hci_command_packet_t;
// 操作码组成
// OGF (Opcode Group Field): 高6位,命令组
// OCF (Opcode Command Field): 低10位,具体命令
#define HCI_OGF_LINK_CONTROL 0x01
#define HCI_OGF_LINK_POLICY 0x02
#define HCI_OGF_CONTROLLER_BASEBAND 0x03
#define HCI_OGF_INFORMATIONAL 0x04
#define HCI_OGF_STATUS 0x05
#define HCI_OGF_TESTING 0x06
#define HCI_OGF_LE_CONTROLLER 0x08
// 示例:Reset命令
#define HCI_RESET_OPCODE 0x0C03 // OGF=0x03, OCF=0x0003
发送Reset命令示例:
uint8_t reset_command[] = {
0x01, // 包类型:Command
0x03, 0x0C, // 操作码:Reset (OGF=0x03, OCF=0x0003)
0x00 // 参数长度:0
};
Event包格式
Event包由控制器主动发送,通知主机事件发生:
// HCI Event包结构
typedef struct {
uint8_t packet_type; // 包类型:0x04 = Event
uint8_t event_code; // 事件码
uint8_t parameter_length; // 参数长度
uint8_t parameters[]; // 参数数据(可变长度)
} hci_event_packet_t;
// 常见事件码
#define HCI_EVENT_INQUIRY_COMPLETE 0x01
#define HCI_EVENT_INQUIRY_RESULT 0x02
#define HCI_EVENT_CONNECTION_COMPLETE 0x03
#define HCI_EVENT_DISCONNECTION_COMPLETE 0x05
#define HCI_EVENT_COMMAND_COMPLETE 0x0E
#define HCI_EVENT_LE_META_EVENT 0x3E
Data包格式
Data包用于双向传输应用数据,如ACL数据:
// ACL Data包结构
typedef struct {
uint8_t packet_type; // 包类型:0x02 = ACL Data
uint16_t handle_flags; // 连接句柄 + 标志位
uint16_t data_length; // 数据长度
uint8_t data[]; // 数据内容
} hci_acl_data_packet_t;
// 标志位解析
#define HCI_ACL_HANDLE_MASK 0x0FFF // 低12位:连接句柄
#define HCI_ACL_PB_FLAG_MASK 0x3000 // 13-14位:Packet Boundary Flag
HCI传输层
HCI协议可以通过多种物理介质传输,适配不同硬件平台。
UART传输(H4协议)
UART是最常见的传输方式,采用H4协议封装:
// H4协议包格式(UART传输)
typedef enum {
H4_TYPE_COMMAND = 0x01,
H4_TYPE_ACL_DATA = 0x02,
H4_TYPE_SCO_DATA = 0x03,
H4_TYPE_EVENT = 0x04
} h4_packet_type_t;
// 发送Reset命令的H4封装
void send_reset_command_uart(void) {
uint8_t h4_packet[] = {
0x01, // H4类型:Command
0x01, // HCI包类型:Command
0x03, 0x0C, // 操作码:Reset
0x00 // 参数长度
};
uart_send(h4_packet, sizeof(h4_packet));
}
USB传输
USB传输通常使用Bulk端点,无需H4头部:
// USB HCI直接发送Command包
void send_reset_command_usb(void) {
uint8_t hci_command[] = {
0x01, // HCI包类型:Command
0x03, 0x0C, // 操作码:Reset
0x00 // 参数长度
};
usb_bulk_send(COMMAND_ENDPOINT, hci_command, sizeof(hci_command));
}
选择合适的传输层是嵌入式开发的关键,涉及网络/系统中串行通信与总线技术的知识。
应用示例:蓝牙BLE扫描器
以下是一个基于HCI的BLE扫描器实现框架,展示了实际开发流程:
#include "hci_interface.h"
// 开始BLE扫描
int ble_start_scan(void) {
// 1. 设置扫描参数
int ret = hci_le_set_scan_parameters(
0, // Passive scan
0x0010, // Scan interval: 10ms
0x0010 // Scan window: 10ms
);
if (ret != 0) return -1;
vTaskDelay(pdMS_TO_TICKS(100));
// 2. 启用扫描
ret = hci_le_set_scan_enable(1, 1); // Enable, filter duplicates
if (ret != 0) return -2;
printf("BLE scan started\r\n");
return 0;
}
// 处理LE Meta事件(如广告报告)
void handle_le_meta_event(const uint8_t *data, uint8_t length) {
if (length < 1) return;
uint8_t subevent_code = data[0];
switch (subevent_code) {
case 0x02: // LE Advertising Report
// 解析并处理广告数据
break;
default:
printf("Unknown LE subevent: 0x%02X\r\n", subevent_code);
break;
}
}
// 主程序
void app_main(void) {
hci_init(); // 初始化HCI接口
vTaskDelay(pdMS_TO_TICKS(1000));
ble_start_scan(); // 启动扫描
vTaskDelay(pdMS_TO_TICKS(30000)); // 运行30秒
hci_le_set_scan_enable(0, 0); // 停止扫描
printf("BLE scan stopped\r\n");
}
总结
HCI接口作为主机与控制器之间的标准化桥梁,具有以下关键优势:
- 协议标准化:统一了命令、事件和数据的交换格式,降低开发复杂度。
- 传输灵活性:支持UART、USB、SPI等多种物理层,适配不同硬件设计。
- 功能完整性:通过三种包类型覆盖控制、状态上报和数据传输全场景。
- 广泛适用性:除蓝牙外,其设计思想也可扩展至其他通信协议中。
掌握HCI协议对于深入理解嵌入式通信、物联网设备开发及底层网络优化至关重要。