0755-82922363

杰理AC6951C双蓝牙方案——两颗芯片拼出"A蓝牙+B蓝牙+外音"三合一音频系统

ChatGPT_Image_2026年5月7日_10_08_20.png
杰理AC6951C双蓝牙方案——两颗芯片拼出"A蓝牙+B蓝牙+外音"三合一音频系统

最近做了一个双蓝牙音箱项目:一台音箱能同时接两部手机的蓝牙音乐,还能接外部LINE_IN音源。单颗AC695x只有一路A2DP,不够用,于是用了两颗AC6951C,A芯片管一路蓝牙,B芯片管另一路蓝牙+外音+IIS输出,两颗芯片之间用UART传状态模拟开关切音频

这篇文章重点讲两件事:硬件上两颗芯片怎么连的,以及软件状态机怎么决定谁出声


一、为啥要搞这个组合

先过一下AC6951C的底子:

  • 32-bit RISC CPU @ 120MHz(杰理自研pi32指令集)
  • 蓝牙5.0,BLE + EDR,A2DP / AVRCP / HFP / SPP
  • 128KB SRAM,外挂 SPI NOR Flash(最大16MB)
  • 24-bit Audio DAC,差分/单端输出,SNR > 95dB
  • LADC 2通道,支持 LINE_IN 模拟采样
  • I2S/IIS Master/Slave,最高 48kHz 立体声
  • 3×UART,10-bit SAR ADC(ADKEY),内置充电管理
  • 封装 QFN32 / QFN48

这颗芯片天生就是做蓝牙音箱的料——内置完整蓝牙协议栈,A2DP解码后直接DAC推功放,EQ/DRC/虚拟低音全片内跑,SDK成熟开箱即用。但它单颗只支持一路A2DP,不能同时连两部手机播歌。

客户要三路音源自由切换:手机A播歌、手机B播歌、外部LINE_IN。所以方案就是两颗AC6951C各跑一套蓝牙协议栈,硬件上用模拟开关合到一条音频通路:

  • A芯片:负责一路蓝牙,DAC模拟输出
  • B芯片:负责另一路蓝牙 + LINEIN采集 + DAC/IIS双输出
  • 两者之间:UART传蓝牙状态,模拟开关切音频来源

二、硬件怎么接的
image.png

┌───────────────────────┐UART1(AT指令)┌───────────────────────┐
│ A 芯片 │ ───────────────────────────── → │ B 芯片 │
│(AC6951C A_SDK) ││(AC6951C B_SDK) │
││DAC模拟输出││
│手机A ── BT A2DP ──→ DAC ──→──┐ ││
│││ │手机B ── BT A2DP│
└───────────────────────┘│ ││
│┌──────────┐ ││
└──→ │ 模拟开关│ ──→ LADC ──→ DAC ──→ 喇叭│
 外部LINE_IN ────────→ │(io控制) │ │ ↓ │
└──────────┘ │IIS ──→ 外部DAC │
└───────────────────────┘

A芯片的DAC模拟输出和外部LINE_IN都接到一个模拟开关上,B芯片用PA9控制选通哪路,选通后经LADC采样,走DAC和IIS双路输出。

B芯片还用了几组GPIO做硬件控制:PB11控制功放静音(切换音源时先mute再unmute避免pop声),PC2/PC1/PC0三根线组合控制功放前端的音频路由(000=B蓝牙→喇叭,100=A蓝牙→喇叭,010=外音→喇叭),PA12做密码复位检测(长按10秒低电平恢复默认PIN码)。

IIS方面,B芯片配置成DAC+IIS双输出,IIS跑Master模式、48kHz,同时给外部DAC芯片送数字音频。

三条音频通路一目了然:

  • A蓝牙播放:手机A → A芯片BT解码 → A DAC → 模拟开关(PA9=LOW) → B LADC → B DAC+IIS → 喇叭
  • B蓝牙播放:手机B → B芯片BT解码 → B DAC+IIS → 喇叭
  • 外部LINE_IN:外部音源 → 模拟开关(PA9=HIGH) → B LADC → B DAC+IIS → 喇叭

三、软件状态机怎么跑的

A芯片很简单,就干两件事:正常当蓝牙音箱(连手机、收A2DP、DAC输出),以及把自己的蓝牙状态通过UART1用AT指令告诉B(AT+STATUS=CONNECTED/DISCONNECTED/PLAY/PAUSE)。A上电后主动把音量拉满,不依赖手机端音量同步。

B芯片是整个系统的"大脑"。它在UART1中断里收A的状态,通过系统事件投递到任务上下文解析,然后所有决策都围绕四个状态变量展开:A是否连接、A是否在播、B是否连接、B是否在播。

决策规则很直观:

  • 模拟开关(PA9):A或B任一在播,或A/B同时连接 → PA9拉低选通A的DAC;否则PA9拉高选通外部LINE_IN。切换时先静音等30ms再恢复,防pop声。
  • 功放路由(PA-SHDN):A在播→A蓝牙出声,B在播→B蓝牙出声,都没播→外音出声。
  • 任务切换:B在播歌就跑BT任务,B没播歌就切回LINEIN任务。

另外还做了两层保护:暂停10秒超时——A或B暂停后不立即判定停止,等10秒没恢复才切走,避免切歌时音源乱跳;后台A2DP回切拦截——B刚切走LINEIN的短窗口内,蓝牙底层试图自动抢回BT任务会被拦住。


四、踩过的坑

LINEIN播久了有规律POPO声:播几分钟后出现pop声,串口伴随 W 字符。查下来是LADC环形缓冲区溢出丢数据——LADC采样时钟和DAC回放时钟有微小频差,SDK原有的采样率补偿力度不够,加上双蓝牙后台+UART+IIS的额外CPU负载,缓冲区水位逐渐漂移直到溢出(对应杰理官方问题 154)。修法是把采样率补偿从单级改成三级(水位越偏离中心补偿越猛),同时把缓冲区从 *6(约17ms)加大到 *24(约70ms)。

蓝牙音量同步干扰:有些手机默认不开音量同步,上一个用户关了音量,下一个连上就没声音。修法是A和B都关掉音量同步(BT_SUPPORT_MUSIC_VOL_SYNC = 0),各自上电主动设最大音量。


一句话总结:两颗AC6951C,A只管连手机播歌并把状态告诉B;B是中枢,根据四个状态变量决定模拟开关接谁、功放路由怎么走、当前任务跑BT还是LINEIN。


上一篇:
杰理AC791 AI对话 TTS音频下行链路分析
下一篇:
没有了!
联系方式

地址:深圳市龙华区观湖街道观乐路5号多彩科创园B栋801

邮箱:steven@yunthinker.com