1. 项目背景与需求解析
最近在调试杰理AC79系列蓝牙芯片时,遇到一个很有意思的需求:如何让中控耳机在通话过程中保持BLE广播状态。这个需求看似简单,但在实际开发中却遇到了不少技术难点。作为一款主打低功耗的蓝牙芯片,杰理方案在通话时通常会关闭BLE广播以节省功耗,但某些特定场景下(比如需要同时连接手机和智能家居设备),保持广播状态就变得非常必要。
我花了三周时间完整走通了整个修改流程,期间踩过不少坑,也总结出一些实用技巧。这个方案最终实现了在通话状态下:
- 维持BLE广播不中断
- 广播间隔可配置(实测最低可设20ms)
- 不影响通话质量和功耗表现
2. 技术方案选型
2.1 硬件平台特性
杰理AC79系列采用双模蓝牙架构:
- 经典蓝牙(BR/EDR)用于音频传输
- BLE用于设备发现和简单数据交互
默认情况下,当经典蓝牙建立语音链路时:
- 射频资源优先分配给语音通道
- BLE广播自动暂停
- 协议栈进入省电模式
2.2 修改思路
要实现通话中广播,核心是修改协议栈的资源分配策略。经过分析SDK源码,发现需要处理三个关键点:
- 射频时间片分配(关键参数:
bt_controller_schedule_table) - 协议栈状态机(修改
ble_stack_state_machine.c) - 电源管理策略(调整
power_manager模块)
注意:直接修改协议栈参数可能导致射频冲突,必须严格测试不同场景下的时序
3. 具体实现步骤
3.1 开发环境准备
- 工具链:杰理官方SDK(版本V2.3.6以上)
- 硬件:AC79N开发板+耳机模组
- 调试工具:Ellisys蓝牙分析仪
3.2 关键代码修改
在sdk/ble/controller目录下修改调度策略:
c复制// 修改射频调度表(间隔20ms)
const bt_controller_schedule_t schedule_table[] = {
{BLE_ADV, 20}, // BLE广播
{BT_SCO, 10}, // 语音通道
{BT_ACL, 5}, // 控制通道
{IDLE, 5} // 空闲时段
};
在ble_stack_state_machine.c中绕过状态检测:
c复制void ble_stack_state_check(void) {
// 注释掉原始状态检测
// if(get_bt_state() == BT_STATE_SCO_CONNECTED) {
// disable_ble_adv();
// }
}
3.3 功耗优化配置
修改power_manager.c中的电源策略:
c复制void power_manage(void) {
// 保持RF常开
set_rf_power_mode(RF_MODE_ACTIVE);
// 调整LDO输出电压
set_ldo_voltage(LDO_RF, 1.8V);
set_ldo_voltage(LDO_CORE, 1.2V);
}
4. 实测数据与调优
4.1 性能测试对比
| 测试项 | 修改前 | 修改后 |
|---|---|---|
| 广播间隔 | 不可用 | 20ms |
| 通话延迟 | 40ms | 45ms |
| 整机功耗 | 12mA | 18mA |
| 广播包成功率 | - | 98.7% |
4.2 参数调优经验
-
广播间隔选择:
- 20ms:最佳响应速度(适合实时控制)
- 100ms:平衡功耗与性能
- 不建议超过200ms(会导致设备发现延迟)
-
射频参数优化:
c复制// 在bt_controller_init()中添加:
set_ble_tx_power(0); // 0级功率(4dBm)
set_bt_tx_power(3); // 3级功率(6dBm)
5. 典型问题排查
5.1 常见故障现象
-
通话杂音:
- 检查射频调度表中的时间片分配
- 确保BT_SCO通道占比≥30%
-
广播丢包:
- 用频谱仪检查2.4G干扰
- 调整
set_ble_channel_map()避开WiFi信道
-
功耗异常:
- 检查LDO配置是否正确
- 确认没有进入
RF_MODE_FULL_ACTIVE状态
5.2 调试技巧
- 使用逻辑分析仪抓取RF_EN信号时序
- 通过
printf输出协议栈状态机转换日志 - 在Ellisys中过滤
ADV_IND包分析广播质量
6. 生产注意事项
-
射频认证:
- 必须重新进行BQB认证
- 特别注意调制谱(Modulation Spectrum)测试
-
批量生产测试项:
- 双模并发稳定性(持续通话+广播8小时)
- 不同电源电压下的射频性能(3.3V-4.2V)
- 高温(85℃)环境下的功耗测试
-
我们在量产时发现一个隐蔽问题:当电池电压低于3.5V时,BLE广播会偶发断连。最终通过修改DC-DC的切换阈值解决:
c复制// 在power_manager.c中修改:
set_dcdc_switch_threshold(3400, 3500); // 原值3300/3600
这个方案目前已在多个智能耳机项目量产,最关键的收获是:双模蓝牙的时序调度就像指挥交通,必须给每个"车辆"分配合理的"通行时间",同时留出足够的"缓冲地带"应对突发状况。
