🎧 蓝牙耳机
基于经典蓝牙 A2DP + HFP Profile 的音频设备,支持立体声音乐和通话功能。
📐 系统架构
flowchart TB
subgraph Headset["蓝牙耳机"]
MIC[麦克风] --> CODEC[音频 Codec]
CODEC --> BT[BLE+ 经典双模芯片]
BT --> ANT[天线]
BT --> AMP[功放]
AMP --> SPK[扬声器]
end
subgraph Phone["手机"]
APP[音乐 App] --> AUDIO[音频系统]
AUDIO --> BT2[BLE+ 经典双模芯片]
BT2 --> ANT2[天线]
end
ANT <-->|A2DP 音频流 | ANT2
ANT <-->|HFP 通话 | ANT2
ANT -.->|BLE 控制 | ANT2
style Headset fill:#e3f2fd,stroke:#007bff
style Phone fill:#d4edda,stroke:#28a745
📋 蓝牙音频 Profile
flowchart TB
subgraph Classic["经典蓝牙 Profile"]
A2DP["A2DP
音频传输"] AVRCP["AVRCP
远程控制"] HFP["HFP/HSP
免提通话"] end subgraph BLE["低功耗蓝牙"] BATTERY["电池服务"] FINDME["查找耳机"] FWUPD["固件升级"] end A2DP --> CODEC1{音频编码} CODEC1 --> SBC[SBC] CODEC1 --> AAC[AAC] CODEC1 --> APTX[aptX] CODEC1 --> LDAC[LDAC] style Classic fill:#fff3cd,stroke:#ffc107 style BLE fill:#e3f2fd,stroke:#007bff
音频传输"] AVRCP["AVRCP
远程控制"] HFP["HFP/HSP
免提通话"] end subgraph BLE["低功耗蓝牙"] BATTERY["电池服务"] FINDME["查找耳机"] FWUPD["固件升级"] end A2DP --> CODEC1{音频编码} CODEC1 --> SBC[SBC] CODEC1 --> AAC[AAC] CODEC1 --> APTX[aptX] CODEC1 --> LDAC[LDAC] style Classic fill:#fff3cd,stroke:#ffc107 style BLE fill:#e3f2fd,stroke:#007bff
📊 A2DP 音频传输流程
sequenceDiagram
participant Phone as 手机
participant Headset as 蓝牙耳机
Note over Phone,Headset: 1. 经典蓝牙连接
Phone->>Headset: Inquiry/Page
Headset-->>Phone: 连接完成
Note over Phone,Headset: 2. 服务发现 (SDP)
Phone->>Headset: SDP 查询 A2DP
Headset-->>Phone: 返回 A2DP/AVRCP UUID
Note over Phone,Headset: 3. A2DP 信令
Phone->>Headset: L2CAP 连接 (信令通道)
Phone->>Headset: 配置 Codec (SBC)
Headset-->>Phone: 配置确认
Note over Phone,Headset: 4. 音频流传输
Phone->>Headset: L2CAP 连接 (媒体通道)
loop 持续传输
Phone->>Headset: RTP 音频包 (10ms)
end
Note over Phone,Headset: 5. 播放控制
Phone->>Headset: AVRCP Play/Pause
Headset-->>Phone: 执行确认
📦 A2DP 数据包结构
// A2DP 音频数据包结构
// 基于 L2CAP ACL 数据
typedef struct {
// L2CAP Header (4 bytes)
uint16_t l2cap_len; // L2CAP 数据长度
uint16_t l2cap_cid; // Channel ID (媒体通道)
// RTP Header (12 bytes)
uint8_t rtp_v_p_x_cc; // Version, Padding, Extension, CC
uint8_t rtp_m_pt; // Marker, Payload Type
uint16_t rtp_seq; // Sequence Number
uint32_t rtp_timestamp; // Timestamp
uint32_t rtp_ssrc; // SSRC
// AVDTP Media Payload
uint8_t frame_count; // 帧数量
uint8_t frame_len[4]; // 每帧长度
uint8_t audio_data[]; // SBC/AAC 音频数据
} a2dp_packet_t;
// SBC 音频帧头
typedef struct {
uint8_t sync_word; // 同步字 0x9C
uint8_t freq_samp; // 采样率 + 块数 + 声道 + 分配方法
uint8_t subbands; // 子带数 + 联合声道
uint8_t snr_alloc; // 信噪比 + 比特池
uint8_t scale_factor[]; // 缩放因子
uint8_t audio_data[]; // 音频数据
} sbc_frame_t;
// 典型配置:44.1kHz, 立体声,SBC
// 每包约 120-150 bytes,每 10ms 发送一次
📈 完整连接流程
flowchart TD
A[开机] --> B[BLE 广播]
B --> C{手机连接?}
C -->|是 | D[BLE 配对]
C -->|否 | B
D --> E[经典蓝牙可发现]
E --> F{经典蓝牙连接?}
F -->|是 | G[建立 A2DP+HFP]
F -->|否 | E
G --> H{音频播放?}
H -->|是 | I[A2DP 流传输]
H -->|否 | J{来电?}
I --> K[播放音乐]
J -->|是 | L[HFP 通话]
J -->|否 | M[待机]
K --> N{暂停/结束?}
L --> N
N -->|是 | M
N -->|否 | I
M --> O{断开?}
O -->|是 | B
O -->|否 | M
style A fill:#28a745,color:#fff
style I fill:#007bff,color:#fff
style L fill:#ffc107,color:#000
style B fill:#dc3545,color:#fff
💻 HFP 通话控制
// HFP AT 命令交互
// 通过 RFCOMM 通道传输
// 耳机发送 AT 命令
const char *hfp_at_commands[] = {
"AT+BRSF=1023\r\n", // 支持的功能
"AT+CIND=?", // 查询指示器
"AT+CLCC=?", // 查询当前通话
"ATA\r\n", // 接听电话
"AT+CHUP\r\n", // 挂断电话
"AT+CKPD=200\r\n", // 按键按下 (多功能键)
};
// 手机响应
const char *hfp_responses[] = {
"+BRSF: 1023", // 功能确认
"+CIND: (\"batt\",(0-5))", // 电池指示器
"OK", // 命令成功
"RING", // 来电提醒
"+CLCC: 1,1,4,0,\"123456789\"", // 通话列表
};
// HFP 事件处理
void hfp_event_handler(hfp_event_t event) {
switch (event) {
case HFP_EVENT_CALL_INCOMING:
// 来电:播放铃声
play_ringtone();
break;
case HFP_EVENT_CALL_CONNECTED:
// 通话建立:切换音频路由
audio_route_to_speaker();
break;
case HFP_EVENT_CALL_ENDED:
// 通话结束:恢复待机
audio_route_to_idle();
break;
case HFP_EVENT_AUDIO_CONNECTED:
// A2DP 音频连接
a2dp_streaming_start();
break;
}
}
🎵 音频编码对比
| 编码 | 码率 | 延迟 | 音质 | 兼容性 |
|---|---|---|---|---|
| SBC | 328 kbps | ~150ms | ★★★☆☆ | 100% (强制支持) |
| AAC | 256 kbps | ~100ms | ★★★★☆ | iOS/Android |
| aptX | 352 kbps | ~70ms | ★★★★☆ | Qualcomm 芯片 |
| aptX HD | 576 kbps | ~150ms | ★★★★★ | 高端设备 |
| LDAC | 990 kbps | ~150ms | ★★★★★ | Sony/Android |
| LC3 | 160-345 kbps | ~40ms | ★★★★☆ | LE Audio (蓝牙 5.2+) |
🔋 低功耗设计
功耗模式
- 播放中: 30-50mA
- 通话中: 40-60mA
- 待机: 3-5mA
- 休眠: <50μA
省电策略
- 无音频时进入 Sniff 模式
- BLE 广播替代经典蓝牙
- 自动关机 (30 分钟无操作)
- 入耳检测暂停播放
🔍 调试要点
常见问题
- 连接失败:清除配对重试
- 音频卡顿:干扰/距离过远
- 不同步:重新配对
- 通话无声:检查 HFP 路由
推荐工具
- Frontline: 协议分析仪
- Ellisys: 蓝牙分析仪
- Wireshark: HCI 抓包
- Audio Tester: 音质测试
🆕 LE Audio (蓝牙 5.2+)
flowchart TB
subgraph LEA["LE Audio 特性"]
LC3[LC3 编码
低功耗高音质] MULTI[多设备连接
同时播放] BROADCAST[广播音频
公共场所] HEARING[助听器支持
低功耗] end subgraph Classic["经典音频"] A2DP2[A2DP] HFP2[HFP] end LEA --> BENEFIT[优势
低功耗 + 多设备 + 广播] Classic --> LIMIT[限制
功耗高 + 单连接] style LEA fill:#d4edda,stroke:#28a745 style Classic fill:#fff3cd,stroke:#ffc107
低功耗高音质] MULTI[多设备连接
同时播放] BROADCAST[广播音频
公共场所] HEARING[助听器支持
低功耗] end subgraph Classic["经典音频"] A2DP2[A2DP] HFP2[HFP] end LEA --> BENEFIT[优势
低功耗 + 多设备 + 广播] Classic --> LIMIT[限制
功耗高 + 单连接] style LEA fill:#d4edda,stroke:#28a745 style Classic fill:#fff3cd,stroke:#ffc107