我手上这块 BT2106C Auracast 蓝牙广播模块,从拿到样板开始折腾,到广播音源真正稳定跑起来,前后花了三周。真正坐下来写代码的时间其实不到两天,剩下绝大部分时间都耗在参数配置、射频匹配、以及"手机为什么就是扫不到广播"这类问题上。所以这篇东西我不打算写成说明书式的教程,也不会照着数据手册复述一遍功能列表,而是想把完整开发过程中真正值钱的那部分——选型逻辑、协议关键点、调试方法论、踩坑记录——如实讲一遍。
如果你以前只是玩过 HC-05、HC-06 这种串口透传模块,或者拿 ESP32 做过普通 BLE 数据转发,那你需要先转个弯:Auracast 跟这两者完全不是一个套路。它维护的不是一条点对点链路,而是一条面向所有接收设备的"广播链路"。这个思维方式不转变过来,后面看代码、看日志、排查问题都会非常吃力。
这篇文章适合三类人:准备做广播音频产品的嵌入式工程师、想搞清楚 LE Audio 实际落地情况的产品经理、以及纯粹对 Auracast 底层机制感兴趣的技术爱好者。基础弱一点也没关系,涉及协议的地方我会尽量用大白话加生活类比讲清楚,保证你能跟着走完整个开发思路。
1. 先搞清楚 Auracast 到底改变了什么
1.1 传统蓝牙音频的天然上限
蓝牙音频在过去十几年里,基本就是 A2DP 协议的天下。它的工作方式是一台手机作为音源 source,通过 ACL 连接链路,跟一只耳机建立点对点的音频流。哪怕是最新的 TWS 双耳耳机,本质上也是一条连接链路内部做了数据分发,并没有突破"一对一"这个模型。
这个模型带来几个很现实的痛点。博物馆想给现场观众提供多语言导览,总不能让每个观众都去跟某台设备配对;健身房想播放统一的电视节目声音,也没办法搞一台手机广播给全场;更典型的是助听场景——听力障碍人士在剧院、车站、机场这些公共场所,传统蓝牙技术基本上帮不上什么忙,因为没有任何一对一的链路可以满足"很多人同时听同一路声音"的需求。
1.2 Auracast 的模型:把蓝牙音频变成"收音机"
Auracast 做的事情,用一个类比就能说明白:把蓝牙音频从"打电话"变成"听广播"。音源设备(Broadcast Source)通过低功耗蓝牙以周期广播的方式向外发送音频数据流,任何支持 Auracast 接收的设备——手机、耳机、助听器——都可以在附近"调台"收听。接收端的数量没有上限,而且不需要跟音源建立连接、不需要配对、不需要授权(除非广播方主动做了加密)。
这个模型来自蓝牙 5.2 引入的 LE Audio 规范里的 Broadcast Audio(广播音频)部分,后来蓝牙 SIG 把它正式命名为 Auracast。底层传输走的是 BIS(Broadcast Isochronous Stream,广播同步流),多个 BIS 组成一个 BIG(Broadcast Isochronous Group,广播同步组)。A2DP 像打电话,你必须知道对方号码、拨通之后双方独占线路;Auracast 像收音机,发射塔把信号发出去,谁有收音机谁就能听,换频道也没有成本。"一对多、无连接"这四个字,就是 Auracast 最核心的价值。
1.3 为什么最终选了 BT2106C
选型阶段我对比过几类方案。传统蓝牙音频 SoC 大多是经典蓝牙加 A2DP 的老架构,价格确实便宜,但要支持 LE Audio 需要额外的软件适配,功耗和延迟都不占优势。另一边是手机或者高端可穿戴设备用的方案,原生支持 LE Audio,但外围电路复杂、芯片成本也高,不适合做小体积的广播模块。
我手上的 BT2106C 属于专门为 LE Audio 设计的低功耗蓝牙音频 SoC:集成 MCU、DSP 和 LC3 编解码器,支持蓝牙 5.4 的广播同步流角色,外围只需要晶振、电源和音频输入就能工作。它最打动我的几个点:
- 原生支持 Auracast 的 Broadcast Source 和 Broadcast Receiver 双角色,SDK 里自带广播的完整示例工程;
- LC3 编解码跑在片内 DSP 上,不占用主控 CPU,留给上层业务逻辑的算力很充足;
- 支持 I2S 和模拟音频输入,对接外部音源(DAC、麦克风、HDMI 音频分离板)非常灵活;
- 整体物料成本比"主控 MCU + 独立蓝牙芯片 + 独立 codec"的三芯片方案低得多。
当然它也有短板。芯片原厂的技术文档相对简略,很多关键细节要自己去翻头文件、读例程来推断;SDK 的代码组织方式也是典型的"芯片厂风格",跟通用嵌入式工程的组织习惯有差距。这些坑后面我会专门讲。
1.4 整个系统的角色与数据流向
这套系统里各角色的分工是这样的:
| 角色 | 设备 | 作用 |
|---|---|---|
| 音源 | PC、手机、HDMI 音频分离板 | 输出模拟或数字音频给广播模块 |
| 广播源 | BT2106C 模块 | 接收音频输入,LC3 编码,按 BIG 周期广播 |
| 接收端 | 支持 Auracast 的手机、耳机、助听器 | 搜索广播、选择频道、解码播放 |
音频流向是:外部音源 → I2S 或模拟输入 → BT2106C 内部 DSP 做 LC3 编码 → 封装成 BIS 数据包 → 蓝牙射频周期性发出。接收端在自己的射频监听窗口里捕获广播通告,解析出 BASE 信息后就知道音频编码格式,再解码播放。整条链路不建立任何 ACL 连接、没有任何握手交互,这就是跟 A2DP 最本质的区别。
2. 硬件准备和开发环境搭建
2.1 最小系统与音频输入方案
我拿到的模块是邮票孔封装,出厂时已经把 BT2106C 芯片、晶振、电源、天线都集成在小板上了,外围引脚引出电源、UART、I2S、GPIO 和模拟音频输入。自己做底板的时候,最需要注意的就是电源。
蓝牙射频发射的瞬间电流尖峰非常大。广播模式下如果把发射功率设在 +8 dBm 左右,峰值电流可能到 60 到 80 mA。底板如果用普通的 LDO 供电,输入输出压差又大的话,瞬态跌落会导致射频杂散超标,严重时模块直接复位。我这边用的是一颗 3.3V/300mA 的 LDO,输入 5V,输出端加了 10uF、1uF、100nF 三级电容组合,实测广播发射时电压跌落控制在 50 mV 以内。
音频输入我建议优先走 I2S。原因很简单:Auracast 的广播质量上限取决于你喂给编码器的源数据,模拟输入容易引入地环路噪声和底噪,调试的时候很难判断问题出在射频链路还是音频链路。我先后用模拟 LINE IN 和 I2S 输入做了对比,同样的广播参数,I2S 输入出来的声音明显更干净。如果产品必须用模拟输入,注意音频地和数字地单点连接,走线尽量远离天线区域。
2.2 天线匹配那点事
天线是所有射频项目里最容易出现"差之毫厘谬以千里"的地方。模块虽然自带天线,但焊到底板上之后,周围的地铜皮、器件、外壳都会影响天线的阻抗和辐射效率。我的做法是:模块天线区域正下方和周边 3 毫米内全部禁铜,底板上预留一组 π 型匹配网络(串联电感加两个并联电容),先按原厂参考值焊接,再用网分实测模块天线端的 S11 参数。
第一次实测在 2.44 GHz 附近回波损耗只有 -6 dB 左右,距离 -10 dB 的合格线差得很远,意味着有相当一部分能量被反射回来,没有真正辐射出去。后来把并联电容从 1 pF 换成 0.8 pF,S11 才压到 -13 dB。这一步对广播距离的影响是数量级的,后面踩坑部分我会展开讲。
2.3 SDK 与工具链准备
厂商 SDK 基于 C 语言,工程组织分三层:芯片驱动层、协议栈层、应用层。编译工具链是 ARM 核标准的 GCC,配套有烧录工具和串口日志抓取工具。我是在 Windows 上用 VS Code 写代码、命令行编译,再用官方烧录工具下载固件。串口日志默认 115200 8N1,上电后能看到协议栈版本、MAC 地址、启动状态等信息。
给第一次上手的朋友一个忠告:拿到 SDK 后不要急着改代码,先把厂商自带的 broadcast source 示例工程原样编译烧录进去,确认模块能正常启动、日志正常输出,再做任何修改。这样后面出了问题,你心里至少有一个"已知能跑的基线"可以回退。
2.4 怎么快速确认 demo 真的在广播
示例烧录进去之后,怎么确认它真的在发广播?两个办法:
- 看串口日志。正常状态下会周期打印广播任务的状态,类似 "BIG interval: 10000 us, BIS count: 1, LC3 48k 2ch" 这样的信息;
- 用射频抓包工具。逻辑分析仪不行,得用支持 2.4 GHz 抓包的硬件配合 Wireshark,能看到周期广播包和 BIG 数据包的完整时序。
我建议第二步一定要做。因为广播链路的问题靠日志只能看到"软件认为自己正常",而抓包能看到真实的空中时序、数据包间隔、重传情况,这是排查"手机收不到"最直接的依据。
3. Auracast 广播开发的核心环节
3.1 写代码前必须建立的观念:广播不是连接
开发 Auracast 广播源之前,先建立一个观念:发送端和接收端之间没有任何连接。没有连接意味着没有应答、没有确认、没有流控。BIG 的重传机制只是发送端在预定时间片里盲目重发副本,接收端如果错过了所有副本,这一帧音频就丢了。
这跟写普通 BLE 外设完全是两种思路。BLE 外设是准备好数据等中心设备来读,或者用 Notify 推送;Auracast 广播是"我说我的,你听你的"。所以调试的时候不能寄希望于"连上去看状态",唯一的调试手段就是抓包加观察接收端表现。这个观念转不过来,后面很多排查工作会走弯路。
3.2 BIG/BIS 参数配置逻辑
Auracast 广播底层的关键参数都围绕 BIG 和 BIS 展开。SDK 里广播源的配置项通常包括下面这些:
| 参数 | 含义 | 我使用的值 | 说明 |
|---|---|---|---|
| 采样率 | LC3 编码采样率 | 48000 Hz | 兼容性最好 |
| 声道数 | 单声道/双声道 | 2(立体声) | 音质测试建议立体声 |
| 码率 | LC3 编码码率 | 128 kbps/ch | 按音质需求调整 |
| 帧长 | 每帧音频时长 | 10 ms | LE Audio 标准值 |
| 广播事件间隔 | 两个广播事件的间隔 | 10000 us(10 ms) | 与帧长对应 |
| 子事件间隔 | BIG 内部各流的发送间隔 | 5000 us | 给重传留空间 |
| 重传次数 | 每个包在后续子事件的重复次数 | 2 | 提升抗干扰能力 |
这些参数之间有强约束关系。比如 10 ms 帧长对应 10 ms 的广播事件间隔,你要在这个周期内把两个声道的音频数据包以及它们的重传副本全部发完。如果重传次数调大,就必须把子事件间隔缩短,否则一个周期内塞不下这么多包。SDK 通常会在配置时做合法性校验,参数配得不合理会直接报错——这其实是个很好的保护机制,避免你带着非法配置上线。
3.3 广播可发现性:PBA 和 BASE
接收端怎么知道附近有一个 Auracast 广播?靠的是 BLE 的周期广播(Periodic Advertising)外加广播公告信息(PBA,Public Broadcast Announcement)。PBA 里面携带 BASE 信息,BASE 描述了广播里有哪些音频流、用的什么编码参数、是否加密、广播名叫什么。
也就是说,光启动 BIG 数据流还远远不够,必须同时把 PBA 的周期广播开起来,接收端才能"搜到"这个电台。如果只配了数据流、没配公告,抓包能看数据包在空口上发,但手机完全扫不到。这个细节是我第一次调试时踩得最久的坑,后面专门说。
提示:可以把 BIG 理解成"节目的声音信号",PBA 理解成"电台的频率和节目介绍"。发射塔不播节目介绍,听众就不知道这里有台可听。
3.4 广播流程的代码骨架
SDK 的广播源接口大致长这样(不同厂家的函数命名会有差异,逻辑是相通的):
#include "auracast_broadcast.h" static void app_audio_rx(uint8_t *pcm_data, uint32_t len) { // 外部 I2S/DMA 把 PCM 数据喂进来 auracast_broadcast_send(pcm_data, len); } void app_auracast_bcast_init(void) { auracast_broadcast_cfg_t cfg = {0}; cfg.broadcast_name = "Museum-Audio-01"; cfg.broadcast_duration = 0; // 0 = 持续广播 cfg.codec_type = AU_LC3; cfg.sample_rate = 48000; cfg.channel_mode = AU_STEREO; cfg.bitrate = 128; // kbps/ch cfg.frames_per_packet = 1; cfg.retransmit_count = 2; cfg.encrypted = false; auracast_broadcast_init(&cfg); auracast_broadcast_start(); }实际工程中,音频数据通常通过 DMA 中断或者编解码器回调送进来,需要提前做好环形缓冲,防止 send 函数在中断上下文里被阻塞。我给广播发送任务分配了较高优先级,PCM 数据到达后直接拷贝进协议栈发送队列,绝不在回调里做打印、LED 翻转这类耗时操作。之前试过在回调里加调试打印,音频直接卡成拖拉机——中断优先级和临界区问题在这个场景下暴露得特别明显。
4. 调试与验证:怎么确认广播真的"能收"
4.1 用手机验证:最直观,但别把它当唯一标准
调试过程中最快速的验证方式是手机。目前安卓 13 及以上系统原生支持 Auracast 接收,但入口藏得比较深,一般在"设置 → 已连接的设备 → 右上角菜单 → 广播音频"这种层级里。不同品牌位置差异很大,三星在"设置 → 连接 → 蓝牙 → 广播"下面,小米在"蓝牙设置 → 广播音频",找不着就直接在系统设置里搜索"广播"两个字。
手机验证有两个明显的坑。第一,很多手机系统层面支持,但厂商驱动没有开放广播接收入口,搜不到不代表广播有问题;第二,手机扫描广播有缓存,改了广播参数之后经常要关闭蓝牙再打开,甚至重启手机才能看到更新。所以手机测试只能用来做"最粗的确认",不能作为唯一验证手段。
4.2 模块对模块:工程上最靠谱的验证路径
我后来又拿了两块 BT2106C 的板子,一块跑广播源代码,一块烧接收端示例工程,接收端 I2S 输出接一个小功放和 3W 音箱。这样整条链路都掌握在自己手里,参数改完立刻能听到效果,排查问题完全不需要依赖外部设备。
接收端日志会打印收到的广播信息,包括广播名、编码参数、是否加密。如果接收端稳定显示、音箱出声正常,说明广播源的基础链路是通的;之后再拿手机去收,基本就没什么意外。这个方法强烈推荐,它能把"我的广播有没有问题"和"手机支不支持 Auracast"这两个变量彻底分开。
4.3 抓包验证与射频实测
最严谨的验证还是抓包。用 2.4 GHz 抓包工具配合 Wireshark,重点看三件事:周期广播(PBA)是否在稳定发送、间隔是否符合配置;每个广播事件里的 BIG 数据包数量对不对、重传副本是否在预期时间片内出现;BASE 信息能不能被正确解析。
射频端的实测数据我整理了一个简表,供参考:
| 测试项 | 结果 |
|---|---|
| 中心频率 | 2402 ~ 2480 MHz,按配置跳频 |
| 发射功率 | +8 dBm(可配置) |
| 空旷距离(手机接收) | 约 60 米以内稳定 |
| 空旷距离(模块接收) | 约 120 米稳定 |
| 室内穿一堵墙 | 稳定,两堵墙后开始丢包 |
| 广播源平均功耗 | 约 22 mA @ 3.3V |
手机接收距离明显短于模块,因为手机的天线和射频前端并不是为远距离接收广播优化的,这个结果符合预期。如果做的是室内广播产品,60 米的覆盖半径已经相当充裕。
5. 三周里消耗最多时间的四个坑
5.1 手机死活扫不到广播:PBA 没开的教训
这是最折磨人的一个坑。广播源日志显示 BIS 在正常发送,抓包也能看到数据包,但手机打开"广播音频"列表就是空的。我一度怀疑是芯片的 PBA 配置没生效,翻了很久 SDK 源码才找到真正原因:SDK 里广播源有两个独立的使能开关,一个管数据流(BIG/BIS),一个管广播发现(周期广播/PBA)。我把数据流打开了,但周期广播的使能没打开,等于电台在发射节目信号,却忘了发"电台频率和节目介绍",收音机根本不知道存在这个台。
这个问题的完整排查链路复盘一下,给大家留个参考:
- 先抓包,确认空口上有没有周期广播包。如果没有,问题大概率在 PBA 配置,而不是数据流;
- 确认周期广播使用的通道。建议选 37、38、39 主广播通道之外的通道,避免跟常规广播冲突;
- 确认广播名非空,BASE 信息里的编码参数没有非法值,比如声道数不能为 0;
- 手机侧必须关闭再重新打开蓝牙,清掉旧扫描缓存,再进广播列表。
5.2 LC3 采样率兼容性:44.1k 的教训
把广播配置里的采样率从 48000 改成 44100 之后,模块对模块接收一切正常,手机也显示能搜到广播,但点进去就是不出声。换支持 Auracast 的耳机试,同样静音。
原因在于:蓝牙 SIG 在 LE Audio 规范里把 48 kHz 列为强制的必选支持项,而 44.1 kHz 属于可选支持。很多接收端,尤其是手机系统级的接收栈,只实现了强制要求的部分,遇到 44.1 kHz 会直接解析失败或者静音。这个坑告诉我们一个非常实际的原则:做 Auracast 广播源,如果没有特殊原因,采样率一律用 48 kHz。44.1k 和 48k 的音质差异远小于兼容性问题带来的麻烦。
5.3 复杂射频环境下的音频卡顿和断续
在办公室环境下测试时,隔了两道工位就开始爆音卡顿。抓包一看,丢包率明显升高,尤其是有人用微波炉、USB 3.0 设备和周围一堆蓝牙设备同时工作的时候,2.4 GHz 频段拥挤得一塌糊涂。
我的解决思路是组合拳:重传次数从 1 加到 3;缩短子事件间隔,让重传副本尽早发出去;用 WiFi 分析仪扫一下现场信道占用情况,把广播通道选在相对干净的位置。如果应用场景允许,还可以把码率降到 96 kbps/ch,单帧数据量更小、发送窗口更短,抗干扰能力会明显提升。需要强调的是,这些参数之间互相影响,改一个要测一轮,别一次性全改。
5.4 天线匹配不实测的代价
这个坑跟 2.2 节呼应。第一版底板我按参考设计的匹配参数直接抄了,没有实测 S11,结果空旷距离只有不到 20 米,室内隔一堵墙就没声。上矢量网分实测才发现,天线端的回波损耗只有 -6 dB,意味着不少能量被反射回来,根本没辐射出去。
调整匹配花了我三天,反复焊换元件、上机实测、再跑距离测试,最终定下串联 2.2 nH 电感加并联 0.8 pF 电容的组合,S11 在整个 2.4 到 2.485 GHz 频段内都低于 -10 dB,空旷距离从 20 米直接拉到 60 米以上。这个教训最值钱的一点是:参考设计给的匹配值只是起点,不是终点;每块板的 layout 不同、寄生参数不同,匹配结果必须实测验证。有条件的话,天线区域一定要预留多点可调试的焊盘。
6. 实测效果与后续可以做的事
6.1 最终交付的实测效果
广播链路稳定之后,我做了连续 6 小时的长时间运行测试。音频不间断,手机从进入覆盖范围内开始约 2 到 3 秒就能搜到广播,点选之后约 500 ms 出声,这个延迟主要来自接收端的播放起播缓冲,不是射频传输延迟。音频主观听感在 128 kbps LC3 立体声下接近 A2DP 高质量模式,对语音广播、背景音乐、助听类应用来说完全够用。
最终交付清单大致是:
- 广播源模块尺寸 18mm 乘 22mm,邮票孔封装,可以直接贴在产品主板上;
- I2S、模拟双音频输入,支持 48 kHz 立体声 LC3 编码;
- 广播距离室内约 40 米(穿一堵墙),空旷环境 60 米以上;
- 平均功耗 22 mA,适合做带电池的移动广播设备;
- 支持广播名自定义、加密开关、发射功率可调、通道可配置。
6.2 我接下来打算试的扩展方向
Auracast 广播源一旦跑通,能做的事就多了。我目前列了几个方向:
- 加密广播:给博物馆、会议室、付费内容场景做加密授权接收,不是所有靠近的人都能听;
- 动态广播切换:多个音源轮播,比如车站里不同站台发布不同信息,这个主要靠上层应用逻辑实现;
- 接在 HDMI 音频分离器后面,做成电视或显示器的 Auracast 发射器。公共场所的电视声音让观众自己戴耳机收听,既不吵到别人,又照顾到听力障碍人群;
- 跟现有信息屏、欢迎屏联动,播报内容走 Auracast,静默配置走普通 BLE,两个通道互不干扰。
另外我还在测一个功能:让 BT2106C 在 Auracast 广播的同时,通过 UART 接收外部 MCU 指令动态修改广播名。这个如果能稳定,后面做"多区域可管理广播"的落地项目会方便很多。
最后分享两个我自己反复在用的技巧。第一,调试 Auracast 广播时,一定要把抓包、接收端日志、实听三个手段同时用起来,三者互相印证,才能快速定位问题出在射频层、协议层还是音频链路。第二,每次改动只改一个参数,并且记录改动前后的行为差异。广播链路涉及的变量太多,贪多求快只会把自己绕进去。
这块 BT2106C 广播模块后续如果配套接收端的成熟方案,我打算再做一轮"广播源加接收端加手机"三方互通的完整测试,覆盖更多品牌手机和耳机的兼容性,到时候再写一份结果分享出来。如果你也在做 Auracast 相关的开发,欢迎多交流踩坑经验。