目录
- 一、先看整体
- 二、系统与 RTOS
- 三、硬件驱动与电源管理
- 四、蓝牙连接与 Profile
- 五、TWS 双耳协同
- 六、音频系统
- 七、产品应用逻辑
- 八、数据保存与 OTA
- 九、日志、测试与问题定位
- 十、用来电场景串联各模块
- 十一、写在最后
- 参考资料
刚接触 TWS 耳机开发时,我对它的软件结构其实没有太完整的认识。
表面上看,耳机的功能似乎很简单:连接手机、播放音乐、接打电话,再加上一些按键和提示音。但真正打开一个 TWS SDK 后,会发现里面还有任务调度、设备驱动、充电管理、双耳通信、音频处理、数据保存和升级等很多内容。
不同芯片平台的目录结构、模块名称和实现方式并不一样。
一、先看整体
如果暂时不考虑具体芯片平台,TWS 耳机的软件大致可以分成下面几个部分:
graph TD
A["TWS 耳机软件"] --> B["系统与 RTOS"]
A --> C["硬件驱动与电源管理"]
A --> D["蓝牙连接与 Profile"]
A --> E["TWS 双耳协同"]
A --> F["音频系统"]
A --> G["产品应用逻辑"]
A --> H["数据保存与 OTA"]
A --> I["日志、测试与问题定位"]
这不是严格的分层架构。实际 SDK 中,各部分往往会互相调用,甚至放在同一个模块里。这样划分主要是为了看清楚:一个耳机功能背后,通常有哪些软件在配合。
| 软件模块 | 主要负责什么 | 常见内容 |
|---|---|---|
| 系统与 RTOS | 让程序和多个任务运行起来 | 任务、消息、定时器、内存、看门狗 |
| 驱动与电源 | 与耳机硬件交互 | GPIO、ADC、I2C、I2S、充电、休眠、唤醒 |
| 蓝牙连接 | 与手机建立和维护蓝牙业务 | 配对、回连、A2DP、AVRCP、HFP、BLE |
| 双耳协同 | 让左右耳保持一致 | 双耳组对、角色、状态同步、音频协同 |
| 音频系统 | 管理声音输入和输出 | 编解码、播放、录音、提示音、ANC、ENC |
| 产品应用 | 决定耳机具体怎样工作 | 按键、LED、佩戴检测、状态机、功能优先级 |
| 数据与升级 | 保存配置并更新固件 | 配对记录、用户设置、OTA、版本管理 |
| 调试与测试 | 帮助发现和定位问题 | 日志、异常信息、测试模式、量产支持 |
二、系统与 RTOS
TWS 耳机一般不是从上到下只执行一条固定流程。蓝牙事件、按键、音频、充电和定时任务可能在不同时间发生,因此软件需要同时管理多种事情。
这一部分通常包括:
- 系统启动和各模块初始化
- 任务或线程的创建与调度
- 事件、消息和队列
- 软件定时器
- 内存分配与任务栈
- 中断处理
- 看门狗和异常恢复
应用层开发中经常接触到的,并不是 RTOS 调度器本身,而是平台提供的任务、消息和回调接口。
例如,按键驱动检测到一次双击后,不一定会直接执行“切换降噪模式”。它可能先产生按键事件,再把事件投递给应用任务,最后由应用代码根据当前状态决定是否执行这个功能。
所以,当我们阅读一个新 SDK 时,找到事件入口和消息流转路径很重要。
三、硬件驱动与电源管理
耳机虽然体积不大,但里面仍然有不少硬件。软件需要通过不同接口读取状态或者控制这些器件。
常见内容包括:
- GPIO:NTC供电、LED、使能信号
- ADC:按键电压、其他模拟量
- UART:日志输出、机盒
- 充电与盒仓检测:识别 DC、入盒、出盒、开盖、关盖、充电和满电等状态
- 佩戴检测:红外、触摸或其他传感器
- I2C、SPI:传感器、外部芯片或存储器
- I2S、PCM:数字音频数据传输
驱动层负责把硬件状态转换成软件可以识别的数据或事件,应用层再决定怎样处理。
“耳机入盒”背后涉及盒仓状态检测、TWS 对耳同步、按键禁用、ANC 和音乐处理、DAC 控制及主从切换;关盖后还要关闭蓝牙并进入 FUNC_IDLE或 charge等其他模式。处理不完整,可能导致左右耳状态不一致、盒内仍播放声音或关盖后仍连接手机。
耳机进入低功耗前,要先确认没有正在播放的提示音、运行中的 ANC 或待处理的 App 和充电盒事件。确认可以休眠后,再关闭或降低 DAC、Sensor、LED、定时器和时钟的功耗。某个模块一直工作,耳机就可能睡不着;硬件没有关干净,休眠后的耗电也会偏高
四、蓝牙连接与 Profile
蓝牙部分很容易让人想到庞大的协议栈。按照 Bluetooth Core 的架构,蓝牙系统内部还可以继续分成 Host、Controller 以及它们之间的 HCI。
但在很多芯片平台的应用开发中,协议栈和底层控制器已经由芯片原厂提供。应用层更多是通过 SDK 接口接收蓝牙事件、配置功能,并维护产品需要的连接逻辑。
对 TWS 耳机来说,常见内容主要有以下几类。
配对与连接管理
这部分负责:
- 首次进入可发现、可连接状态
- 与手机完成配对并保存记录
- 开机后回连历史设备
- 连接失败后的超时和重试
- 清除记录和恢复出厂设置
- 多设备连接时选择当前活动设备
“蓝牙已经连接”也不是一个足够完整的状态。底层链路连上以后,音乐、媒体控制和通话对应的 Profile 还可能处于不同的连接阶段。
经典蓝牙音频
传统 TWS 耳机中经常接触到:
- A2DP:传输音乐音频
- AVRCP:播放、暂停、切歌和音量等媒体控制
- HFP:来电、接听、挂断以及通话语音
这几个 Profile 不是同一个功能。音乐可以播放,不代表通话链路一定正常;手机显示已连接,也不代表所有 Profile 都已经可用。
BLE 功能
BLE 在耳机中常用于配套手机 App、状态读取、参数控制或固件升级。
应用层经常看到的是 GATT 中的 Service 和 Characteristic,以及读、写、通知等操作。至于 BLE 底层链路如何收发数据,通常仍由平台协议栈处理。
五、TWS 双耳协同
普通蓝牙音箱设备只需要考虑和手机之间的关系,TWS 还多了一层左右耳之间的协作。
这一部分可能包括:
- 左右耳组对
- 双耳连接状态管理
- 角色分配或角色变化
- 音量、电量和模式等状态同步
- 按键操作同步
- 音乐和通话状态协同
- 双耳升级和版本一致性
需要注意的是,TWS 双耳协同并不是一个所有芯片平台都采用相同接口和相同内部实现的应用 Profile。实际项目中,它通常由芯片平台提供整套方案,因此中科蓝讯、杰理和恒玄 SDK 中看到的接口与处理方式可能差别很大。
应用层更常面对的问题是:什么状态需要同步、什么时候同步、重复消息怎样处理,以及一只耳机断开后另一只耳机应该怎样继续工作。
例如,用户在右耳切换了通透模式,左耳是否要同步更新?如果同步消息发送时双耳刚好断开,重连后是否需要再次校准状态?这些都属于产品应用需要考虑的内容。
六、音频系统
音频是 TWS 耳机的核心部分之一。
音乐播放可以先简单理解为:
手机音频 → 蓝牙接收 → 音频解码 → 音频处理 → DAC → 扬声器
通话时除了播放远端声音,还需要把本地麦克风采集的声音处理后发送给手机:
麦克风 → ADC → 通话音频处理 → 蓝牙发送 → 手机
音频软件通常还会涉及:
- SBC、AAC 等音频编解码
- 音频流的打开、停止与切换
- 采样率、位宽和声道
- 音量控制
- 提示音播放
- 音乐、通话和提示音的优先级
- ANC、ENC、AEC 或 EQ 等功能的接入
应用层一般不会自己从头实现音频编解码器或降噪算法,但需要知道这些模块在什么时候启动、使用什么参数,以及怎样接入产品功能。
一个常见问题是提示音与音乐或通话发生冲突。如果没有处理好音频资源和优先级,可能出现提示音没声音、音乐无法恢复,或者通话过程中播放了不合适的提示音。
七、产品应用逻辑
同一个芯片平台可以做出很多不同的耳机,真正形成产品差异的部分,很多都在应用逻辑里。
常见功能包括:
- 单击、双击、长按等按键操作
- LED 和提示音
- 开机、关机和恢复出厂设置
- 自动回连和配对超时
- 佩戴检测与自动播放暂停
- ANC、通透和普通模式切换
- 游戏低延迟模式
- 双设备连接
- 电量上报
- 入仓、出仓和充电处理
这些功能单独看通常不复杂,难点往往在它们组合以后。
例如,双击操作在听歌时可能是切歌,来电时可能是拒接,通话时又可能没有作用。应用代码必须先判断当前状态,再决定执行哪个动作。
八、数据保存与 OTA
耳机重新开机后,通常需要记住一些信息,例如:
- 手机配对记录
- TWS 双耳关系
- 用户设置的音量
- ANC 或其他功能模式
- 设备名称和部分产品配置
- 校准参数
这些内容一般保存在 Flash、NV或平台提供的其他持久化区域中。
保存数据时还要考虑默认值、写入时机、掉电保护和版本兼容。SDK 或产品配置升级后,如果旧数据格式不能被新固件正确识别,就可能出现配置异常。
OTA 则负责更新耳机固件。对于 TWS 产品,升级还要考虑左右耳的传输顺序、版本一致性、中断恢复和失败回退,通常比单设备升级更复杂。
九、日志、测试与问题定位
产品开发不可能只考虑正常流程,还需要为异常情况留下分析入口。
这一部分可能包括:
- 系统和蓝牙运行日志
- 关键状态变化记录
- 复位原因
- 异常地址或崩溃信息
- 测试模式
- 产测和校准接口
- 固件版本与配置识别
对于应用层问题,日志最重要的作用通常是还原时间线。
单独看到一句“连接失败”并不能说明原因。更有用的信息是:耳机当时处于什么状态、之前发生过什么事件、连接的是哪类设备、失败后有没有重试,以及另一只耳机在做什么。
如果问题可能位于平台底层,也需要先把应用侧能够确认的现象、版本、复现步骤、修改范围和日志整理清楚,再交给芯片原厂继续分析。
十、用来电场景串联各模块
前面列出了很多模块,但它们并不是各自独立工作的。
假设用户正在听音乐,这时手机收到一个来电,耳机软件可能会经历下面的过程:
- 蓝牙模块收到 HFP 来电状态。
- 应用层把产品状态从音乐切换到来电。
- 音频模块暂停或关闭音乐流,准备通话相关资源。
- TWS 模块把来电状态同步给另一只耳机。
- 提示音或铃声模块根据产品配置进行播放。
- 用户按键接听后,应用层处理按键事件。
- HFP 控制状态发生变化,通话语音链路建立。
- 通话结束后,音频和应用状态再恢复到音乐场景。
只要其中一个环节的状态或时序没有处理好,就可能出现单耳没有铃声、接听无效、通话没声音或者挂断后音乐无法恢复。
从这个例子也能看出,一个看起来简单的产品现象,背后可能同时涉及蓝牙、音频、TWS、按键和状态管理。
十一、写在最后
一副 TWS 耳机的软件并不只是蓝牙协议栈,也不只是几个按键功能。它更像是一个小型嵌入式系统:底层连接硬件,中间处理蓝牙和音频,上层再把各种事件组合成完整的产品行为。
作为应用层开发者来说,重点关注的是:
- 能不能看懂 SDK 的启动、状态机和事件处理链路
- 能不能分清蓝牙连接、Profile 和产品业务状态
- 能不能处理双耳同步与功能交叉
- 能不能根据日志逐步缩小问题范围
- 能不能把修改后的功能完整验证一遍
这篇先建立项目的整体结构。后面分析具体功能时,可以先确定他在系统中的位置,在沿调用链深入代码,避免一开始就被大量实现细节干扰。