资讯详情

资讯详情

基于BT2106C的Auracast蓝牙广播模块开发实战:LE Audio一对多音频实现

做嵌入式这么久我印象里的蓝牙一直是“配对—连接—使用”三步走不管是耳机、音箱还是开发板永远都是一对一的点对点链路。直到我拿到 BT2106C 这颗支持 Auracast 的蓝牙广播模块第一次体验到“打开广播旁边任何一台手机都能直接收听”的状态才意识到蓝牙音频“一对多”的时代真的来了。这篇文章主要分享我在 BT2106C 上开发 Auracast 蓝牙广播模块的完整过程包括方案选型、环境搭建、广播参数计算、接收端联调、问题排查和实际效果。如果你也在做 LE Audio、广播音频或者想把手头设备变成“音频发射台”这篇内容应该能帮你少走不少弯路。1. 先搞懂Auracast这一轮蓝牙音频升级到底改了什么1.1 从点对点链路到一对多广播的跨越传统蓝牙音频最让人难受的地方就是连接模型手机连耳机、手机连音箱一次只能让一个音源服务一个或者有限的几个接收端。哪怕用 TWS 耳机左右耳转发本质上还是在一条私有链路里做转发不是真正意义上的“广播”。很多人问过我蓝牙不是早就支持一对多了吗这里要分清楚传统蓝牙 BR/EDR 的“多点连接”和 Auracast 的“广播”是两回事。BR/EDR 的 piconet 里虽然可以挂多个从设备但音频流走的是 ACL 链路一对一传输接收端要两两建立连接带宽和管理开销都很大做不到真正意义上的“谁在旁边都能听”。Auracast 是蓝牙技术联盟基于 LE Audio 规范推出的广播音频方案底层靠的是 BISBroadcast Isochronous Stream广播等时流。这个名字听起来拗口实际上可以把它理解成“收音机电台”发射端把音频数据通过蓝牙广播频道持续对外发送接收端只要知道频率、同步信息和广播密钥就可以进入频道直接收听不需要配对不需要握手也不限制接收人数。这个模型解决了一个传统蓝牙怎么都绕不过去的问题音频内容如何高效地分发给无限多个终端。我刚接触的时候也犯过迷糊以为 Auracast 就是普通的 BLE 广播带一点数据。实际上区别非常大。普通 BLE 广播发的是无连接的小包数据不关心时序接收端收到多少算多少BIS 则要创建 BIGBroadcast Isochronous Group在等时通道上按严格的时间间隔发送音频帧接收端通过 AUX_SYNC_IND 同步到广播的时间基准然后按固定节奏收包。正因为有时序保证它才能承载 LC3 编码后的连续音频流。BT2106C 这颗模块正是把“创建 BIG、管理 BIS、编码音频、周期广播”这一整套流程封装成了可以调用的 SDK 接口开发者的工作重心从底层协议实现转移到业务逻辑和参数调优上。1.2 BT2106C模块在项目里的真实定位我手上这块 BT2106C 模块严格说是一个高度集成的蓝牙 SoC 平台芯片内部集成了射频收发、基带、MCU、音频编解码器和电源管理模块上还引出了 UART、I2S、GPIO、麦克风输入和喇叭输出。对我做产品原型来说这相当于一颗“音频广播单芯片方案”不用再额外挂一颗 MCU 去控制蓝牙协议栈所有逻辑都可以在一个 SoC 内完成开发成本一下子就降下来了。模块在 Auracast 体系里可以扮演两种不同角色。第一种是 Broadcaster也就是广播源负责采集音频、用 LC3 编码器编码、封装成 BIS 包并通过 BIG 广播出去第二种是 Receiver也就是接收端负责同步到广播组、解码 LC3 并输出到本地播放设备。实际开发中发现同一颗 BT2106C 可以配置成任意一种角色切换起来也不复杂这让我在打样阶段省了很多事不用专门买两个不同型号的板子同一块开发板刷不同配置就能同时验证发射和接收两条链路。还要提一个容易忽略的概念Auracast 不只是“公开广播”一种形态。按蓝牙 SIG 的划分广播可以是 Public Broadcast完全公开任何兼容设备都能收、Discoverable Broadcast可被发现的广播接收端需要先从辅助广播流拿到广播信息再进入和 Private Broadcast加密广播接收端必须拿到 Broadcast Code 才能解密。这部分能力在后来的接口设计中特别重要因为很多实际场景并不希望所有设备都能随便收听。比如付费内容分发就必须走 Private Broadcast 这条路。BT2106C 的 SDK 对这三种模式都提供了配置入口我后面会具体讲参数怎么选。2. 方案选型为什么是BT2106C而不是其他模块2.1 从经典蓝牙方案迁移要考虑哪些事在定下 BT2106C 之前我其实对比过好几条技术路线。最传统的是用一颗经典蓝牙音频 SoC比如 CSR 系列再做软件层面的“一拖多”传输。但这条路的问题很明显音频数据始终要走 ACL 链路接收端必须先建立连接一旦接收端数量增多带宽和时延都会恶化而且整个系统还是“主从模型”不是并行广播跟 Auracast 想解决的场景根本不匹配。另一个方案是直接用一颗普通 BLE MCU 自己做等时通道协议例如用 nRF52 系列但 BLE 的普通 GATT 通道不支持等时传输要自己造 BIS 数据封装和时钟同步开发量一下子变成做协议栈的级别对于一个想快速验证产品原型的团队来说不划算。从技术演进角度说LE Audio 已经成为蓝牙 5.2 及以上版本的标配能力未来新出货的手机、耳机、助听器基本都会原生支持 Auracast。忍住前期适配的阵痛直接基于 LE Audio 来做比以后再做二次迁移要省力得多。我评估的基本思路是优先选集成了音频前端、协议栈和 Auracast 例程的 SoC而不是什么都自己拼。BT2106C 吸引我的点有三个第一它原生支持 BIS 发射和接收不需要自己造协议第二内置 LC3 编解码器音频数据可以直接在 SoC 内部完成编码第三SDK 里有广播音频的完整参考例程我不需要从零看几千页协议文档。2.2 关键规格参数怎么看才不踩坑直接贴一份我拿到的模块核心参数方便后面解释各种选择参数数值/说明我的评估蓝牙版本5.3部分配置支持5.4满足 LE Audio 和 Auracast 的协议要求支持角色Broadcaster / Receiver / 普通 BLE 外设一套硬件同时验证两端节省打样成本音频编码LC3 传统 SBC/AAC双模兼容广播走 LC3经典蓝牙走 SBC/AAC过渡期好用音频接口I2S / 模拟 MIC / 差分喇叭输出可以直接接麦克风或音频 Codec适应性好控制接口UART/GPIO/SPI 可选方便做主控联动比如触发播放或切广播供电范围2.8V~4.2V可以直接用锂电池供电适合便携设备待机功耗微安级别具体看配置如果做助听器、耳机类产品续航压力小看参数表时不要只看蓝牙版本还要关注“是否支持 Broadcaster”和“是否支持 LE Audio 协议栈”。有些蓝牙 5.3 的芯片只做了普通 BLE 兼容但音频广播的协议栈并没有开源给你这种后期会很痛苦。BT2106C 好就好在它把 Auracast 相关的协议栈和例程都放出来了我烧录完直接把广播 demo 跑起来就能看到声音这点在实际开发里的价值非常高。另外要注意LC3 编码器虽然是 LE Audio 标配但不同厂商实现的质量和码率档位有差异。如果你的应用需要低延迟或高音质尽量选支持多种采样率和码率动态切换的方案。3. 开发环境搭建拿到模块之后第一件事不是写代码3.1 硬件连接与第一次烧录很多人拿到开发板第一件事就去找代码工程我建议先把硬件环境确认一遍否则后面排查问题会非常被动。BT2106C 模块我这边用的最小系统包括模块核心板、一个 3V3 稳压电源我用的是锂电池 LDO 模块输入 3.7V 输出 3.3V、一个烧录器SWD 接口也可用串口下载、一个 USB 转 TTL 串口用于查看日志、外加一个 I2S 或模拟输入的音频源。第一次上电后先用万用表量模块的 VDD 引脚确保供电稳定再确认时钟是否起振。如果手边有逻辑分析仪或频谱仪看一眼射频口附近的电容电感有没有对应频段的信号基本能排除硬件虚焊问题。第一次烧录固件时我用的是官方提供的烧录工具选择对应的目标芯片型号加载 SDK 编译出来的固件 bin 文件点击下载。烧录速度不算快但胜在稳定。要特别提醒烧录之前务必先备份原厂固件。有些模块出厂带有 RF 校准信息或 mac 地址如果不备份后面自己刷错固件可能连最基本的功能都验证不了。我习惯把原厂固件用 bin 文件的形式保存到本地并记录版本号这样出问题还能回退。烧录完成后打开串口调试助手波特率一般是 115200日志输出就能看到芯片启动信息包括协议栈版本、MAC 地址、蓝牙地址类型等等。看到这些基础信息后才开始跑第一个官方例程。整个过程听起来琐碎但能把连接、供电、日志通道这些问题一次性排干净后面调试时就不会分心。3.2 SDK结构讲解与第一个广播例程官方 SDK 解压后目录结构大同小异apps 目录放上层应用示例stack 或 ble 目录放协议栈库drivers 放芯片外设驱动tools 放编译和烧录脚本。我重点看 apps 下面的auracast_broadcaster和auracast_receiver两个工程这两个就是做广播音频最核心的参考。首次编译前先检查 makefile 或 CMakeLists 里的芯片型号是否匹配然后指定编译工具链路径执行编译命令make -j8如果 SDk 自带 IDE也可以直接在 IDE 里打开工程编译。编译成功后会生成fusion_bt2106c.hex或类似文件按 3.1 节的步骤烧录进芯片即可。这里有个值得说的坑很多示例工程默认打开的是“经典蓝牙音频”功能需要你在工程配置里手动开启 LE Audio 和 Auracast 相关宏定义。我一开始没有认真看预编译配置结果板子上电后只有经典蓝牙可以连进不了广播模式折腾了小半天才发现是把宏开关关掉了。建议你在编译前搜索一下ENABLE_LE_AUDIO或AURACAST_ENABLE这类开关确认已经打开。第一个例程跑起来后模块就默认进入广播状态。用手机上的 Auracast 测试应用扫描应该能看到带 “Auracast” 字样的广播名称。看到这个恭喜你最基础的链路已经通了。4. 发射端开发让BT2106C成为一台真正的“广播电台”4.1 音频流与BIG广播链路是怎么建立的要让模块对外广播音频核心是完成一条音频采集 - LC3 编码 - BIS 分组 - BIG 广播的流水线。从 SDK 代码角度看典型初始化流程包括初始化音频编解码器、设置音频采样率与通道数、配置 broadcast 参数、创建 BIG、启动周期广播。这里最难理解的是 BIG 和周期广播的关系。简单说BIG 是把多个 BIS 逻辑上组合成一个广播组每个 BIS 承载一路独立的音频流比如左声道和右声道可以各占一个 BIS或者多个语言音轨各占一个 BIS。接收端要进入某个 BIS得先听到 BIG 的广播信息再根据自身需求选择对应的 BIS 进行同步。以我这边实际写的简化代码为例关键流程大致如下void auracast_broadcast_start(void) { // 初始化音频编解码器LC3 48kHz 单声道码率 96kbps audio_codec_init(CODEC_LC3, 48000, 1, 96000); // 配置广播等时组 bt_big_create_param_t big_param {0}; big_param.num_bis 1; // 1路音频流 big_param.sdu_interval_us 10000; // 每10ms发送一帧音频 big_param.max_sdu_size 120; // 每个SDU最多120字节 big_param.phy BT_PHY_2M; // 使用2M PHY big_param.packing BT_ISO_PACKING_SEQUENTIAL; big_param.encrypted false; // 公开广播不做加密 bt_big_create(big_param); // 开始周期性广播通知周围接收端 bt_periodic_adv_start(...); }这段代码是伪码风格真实 SDK 的接口名可能略有差异但逻辑顺序是一致的核心要做三件事定音频规格、定 BIG 参数、启动周期广播。很多开发新手卡在这三个环节的先后关系上。实际调测下来一定先把音频编码器初始化好再创建 BIG。因为 BIG 创建时要填写 SDU 大小这个大小取决于 LC3 的码率和 SDU 间隔如果音频编码器没起来你根本算不出正确的 SDU 大小。更稳妥的做法是先调通音频采集通路确认麦克风或 I2S 有数据进来再配置广播参数这样一旦没声音你能很快判断是音频采集的问题还是广播链路的问题。4.2 广播参数计算SDU、码率与间隔的关系参数计算是广播音频开发里最值得认真对待的部分。很多人直接抄例程参数结果音质差或者延迟高却不知道原因。我以最常见的配置为例LC3 48kHz 单声道、96kbps 码率、SDU interval 10ms计算一下每包数据应该装多少字节。LC3 的码率是 96kbps也就是每秒 96000 比特等于每秒 12000 字节。如果每 10ms 发送一个 SDU那么每个 SDU 承载的音频字节数就是1 秒有 1000ms10ms 一个间隔所以一秒钟有 100 个 SDU每个 SDU 的字节数 12000 / 100 120 字节再算上蓝牙协议栈的 BIS 数据头、广播事件头的开销实际 PDU 里要留一点冗余空间所以 max_sdu_size 设置成 120 字节刚好如果还要加前向纠错或重传就要把 max_sdu_size 留出余量。如果换成 32kHz 单声道且码率降为 64kbps则每秒字节数为 8000每 10ms 间隔一个 SDU每包就是 80 字节。这个计算逻辑在所有 LC3 配置下都适用。SDU 间隔和码率不是随便填的。间隔太短每个包携带的音频数据少延迟低但空口包数量多功耗升高间隔太长每个包携带数据多延迟增加但空口效率高。BT2106C 上是 ARM Cortex-M 内核跑协议栈处理能力没问题但射频空口资源是有限的。如果同一个区域有多套 BIG 广播尽量选不同 SDU 间隔或广播事件偏移减少碰撞。还有一个我踩过的坑LC3 帧时长和 SDU 间隔必须对齐。LC3 编码器默认支持 10ms 帧如果你的编解码器配置的是 20ms 帧但 SDU interval 是 10ms接收端会出现严重的数据错位表现出来就是声音断断续续但没有报错。我后来把所有帧时长相关配置统一改为 10ms问题才消失。建议你在调试前先确认编解码器的“帧时长设置”和广播参数里的“SDU interval”保持一致。5. 接收端联调用手机和开发板验证广播效果5.1 接收端配置与同步流程发射端开启广播后接收端的工作流程是相反的先扫描到周期广播再根据广播里的 BIGInfo 信息去同步 BIG接着锁定目标 BIS最后从 BIS 里解出 LC3 包并送音频解码器播放。BT2106C 做接收端时代码逻辑主要分为三步初始化接收引擎、设置要同步的广播地址和 BIS 编号、等待 BIG 同步事件。实际调试时我一开始直接把广播地址写死在接收端代码里用串口打印同步状态。示例代码如下void auracast_receiver_start(uint8_t *broadcast_addr) { bt_bis_sync_param_t sync_param {0}; memcpy(sync_param.adv_addr, broadcast_addr, BD_ADDR_LEN); sync_param.bis_index 1; // 同步第一个BIS sync_param.encryption false; // 对应公开广播 sync_param.auto_resync true; // 掉线后自动重连 bt_bis_sync_start(sync_param); }同步完成后串口日志会出现类似BIG sync established的信息随后开始上报解码后的 PCM 数据到本地播放器。如果方便也可以直接用 I2S 接到外部 DAC再输出到功放和喇叭这样就能实时听到广播内容。整个同步过程通常需要几百毫秒取决于接收端扫描到周期广播的速度和射频环境。在实际验证中我发现用手机做接收端更直观。Android 13 及以上系统原生支持 LE Audio配上 Auracast 相关的测试应用扫描广播列表、点击进入收听整个过程不需要配对这个体验对非嵌入式背景的人来说也很容易理解。我把 BT2106C 当发射端用一台 Android 手机和一个耳机开发板同时接收验证多设备共用一路音频流的效果结果确实是一台发射多台可听完全没有传统蓝牙连接数限制。5.2 实测数据与主观听感发射端配置是 LC3 48kHz、96kbps、2M PHY接收端用同一颗 BT2106C 开发板外接喇叭。空旷区域测试中广播距离大约 45 米时声音依然连续超过 50 米后开始出现偶发断音室内隔一堵墙体时距离明显缩短实测稳定距离约 15 米穿过两堵墙后基本不可用。这个结果和应用场景是匹配的Auracast 广播更多用在开放空间的公共广播而不是追求穿墙性能。延迟方面从音频输入到接收端声音输出整体端到端实测约 120ms。这个延迟包含采集、LC3 编码、空口传输、解码和播放几个环节人耳直观感受就是“画面和声音稍微差了一点点”但用于语音广播或音乐播放完全没问题。如果做需要严格音画同步的场景比如电视伴音还需要在产品层面加入延迟补偿方案单纯靠 Auracast 自身比较难做到超低同步。主观听感层面96kbps 的 LC3 单声道广播音质已经明显优于传统 FM 收音机在语音广播里人声饱满清晰背景底噪很低换到 128kbps 时音乐表现会更好一些但空口占用的带宽也上去了。作为广播音频方案我个人认为 96kbps 是一个比较均衡的档位在音质、覆盖距离和设备功耗之间都表现稳定。6. 踩坑记录与排查技巧这些坑我替你踩过了6.1 常见问题速查开发过程中我遇到过不少问题有一些是配置疏忽有一些是环境干扰整理成表格方便你直接对照排查问题现象可能原因解决动作手机扫描不到广播协议栈宏开关未打开周期广播未启动检查 AURACAST_ENABLE确认 bt_periodic_adv_start 执行成功能扫到广播但无声音SDU 大小和码率不匹配LC3 帧时长不一致重新计算 SDU将编解码帧时长统一为 10ms声音断断续续空口碰撞SDU interval 设置过短环境干扰严重调整广播间隔切换 2M PHY检查同频干扰距离远不如预期PHY 选择不当发射功率配置过低确认 PHY 为 2M检查 TX Power 设置多台接收设备不同步BIS 通道选择或广播地址错误确认所有接收端同步同一 BIG 和 BIS 编号加密广播无法解密Broadcast Code 未正确派生或传错确保发射端和接收端配置相同的 Broadcast Code偶然白屏或死机供电不稳定SDU 缓冲不足检查电源纹波增加音频缓冲内存表格里最容易被忽略的是“SDU 缓冲不足”的问题。BIG 广播到达接收端时射频处理有硬件缓冲但应用层解码也需要软件缓冲。如果 SDU 帧比较大或者设备同时处理多路 BIS建议把接收缓冲区至少开到最大 SDU 的两倍防止瞬时拥塞丢包。这个问题的排查难度比较大因为表现为偶发性卡顿很难稳定复现。6.2 调试利器与独有的排查经验如果你手头有蓝牙协议分析仪会省非常多时间。我用的是一款支持 LE Audio 抓包的软件狗可以直接看到 BIG 广播事件、BIS 子事件、LC3 数据包和 CRC 错误计数比单纯看串口日志强太多。没有协议分析仪也没关系BT2106C 的协议栈日志可以打开底层 HCI 级别的监听把广播事件和等时事件打出来只是信息量比较大需要过滤关键词观察。分享一个排查成本最低但很有效的方法先用最简单的配置跑通再一步步加功能。第一次调试时不要一上来就开加密广播也不要一开始就用多路 BIS。先跑公开广播、单 BIS、固定广播地址确认声音能出后再逐项加需求。这样如果出现问题每一步都能明确知道是新增功能引入的问题而不是在复杂系统里猜。另外发射端和接收端之间最好保留一条 UART 日志通道两边的日志加时间戳便于对齐事件。我遇到过接收端同步成功后 2 秒就掉线的问题就是通过对齐两边日志发现发射端在 BIG 建立后因为某线程优先级问题把周期广播停了。这个问题光看接收端日志很难定位两边日志同步排除才算根治。7. 实际应用场景与影响范围广播音频能做的不只是放音乐7.1 哪些行业和产品会率先受益开发完这套发射端和接收端之后我脑子里冒出的第一个想法是这不就是一套可以嵌入任何公共设备的万能广播系统吗最典型的场景是机场、高铁站、大型会议室里的广播播报。以前每个候机口都要配独立喇叭和独立音频源走线复杂内容切换也麻烦如果用 BT2106C 做发射端把广播内容通过 Auracast 广播出去旅客戴着自己的耳机就能收听到对应登机口的信息不需要额外租借设备也不受距离限制这就是公共广播的增量体验。另一个受益明显的领域是博物馆和展览馆导览。传统导览机需要游客租借设备维护成本高疫情期间还有卫生隐患。展馆在每个展品旁部署 BT2106C 广播模块手机扫码或者直接通过 Auracast 发现广播就能收听对应展品的语音讲解。因为 Auracast 支持多个 BIS 音轨还可以同时推送外语讲解通道游客根据自己的语言习惯选择不同 BIS体验上比传统单声道导览强太多。助听器市场也是 Auracast 的重要目标。很多国家和地区在推进助听器与公共广播之间的互通标准将来在剧院、教堂、课堂等场景助听器可以直接接收现场音频广播不再需要调频辅助设备。BT2106C 这类模块如果做成低功耗小体积方案嵌入助听器或辅听设备里能很大程度提升听障人士的生活便利性。加上 Auracast 支持私有加密广播付费内容和隐私内容也能安全分发这给商业场景留下了更多想象空间。7.2 对蓝牙音频产品开发格局的影响从开发者的视角看Auracast 带来的不只是“新增一个功能”而是把蓝牙音频的交互模型从“连接导向”改成了“内容导向”。用户不再需要关心配对的设备名称和密码只需要关心“我身边有哪些广播源我想听哪一个”。这个变化会倒逼产品设计改变音箱、耳机、车载、电视等设备未来都会加入广播接收能力设备之间不再是互相竞争的主从关系而是变成“音频内容的分发终端”。对于芯片和模块厂商来说谁能把 Auracast 的协议栈做得稳定、接口做得简洁、参数配置做得灵活谁就有机会在下一波蓝牙音频设备换代中占据主动。BT2106C 这种集成了 MCU、射频、音频前端和协议栈的方案让中小团队不需要养一支蓝牙协议栈团队就可以快速做出产品这对整个行业生态的门槛降低是非常明显的。在做完这个项目之后我个人最大的体会是不要把 Auracast 当成一个遥远的新标准它离实际落地已经很近了。哪怕只是把现有的公共广播设备加上一颗模块也能立刻获得“手机原声直收”的新体验。最后再分享一个小技巧如果后续要做量产或认证尽早把 RF 天线匹配和频谱校准放到开发流程里广播类产品在密集环境下的共存表现往往比单台实验室测试更能决定用户体验。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →