4、语音合成模块选型与驱动:SYN6288/JQ8900等模块对比、UART/I2C通信接口、语音合成指令集解析

好,咱们进入第四讲。这一讲我打算聊聊语音合成模块的选型和驱动。说实话,这块内容在电梯播报系统里特别关键——你想想看,要是语音模块选错了,或者驱动写得不顺手,整个系统听起来就像卡了嗓子的老式收音机,用户体验直接崩盘。

我个人习惯是,先看需求再选型。电梯里需要什么?无非就是「楼层到了」「电梯上行」「请勿倚靠」这些固定话术。但有些场景需要动态播报,比如「当前楼层:15层」,这就得靠语音合成芯片实时拼词了。所以,咱们得把市面上常见的模块拉出来遛遛。

4.1 主流语音合成模块对比

目前嵌入式圈子里,SYN6288和JQ8900是两大主力。我当年做第一个电梯项目时,在这俩之间纠结了好几天。后来发现,它们根本不是一个路数。

对比项 SYN6288 JQ8900
核心功能 文本转语音(TTS) 语音播放(预录音频)
通信接口 UART(默认9600bps) UART / I2C / 按键触发
语音合成方式 实时合成任意文本 播放已烧录的音频文件
音质 偏电子音,但可调语速语调 真人录音,音质好
典型应用 动态播报(如楼层号) 固定提示音(如「叮咚」)
价格 约15-25元 约8-15元

看到这个表,你应该明白了。SYN6288是「现编现唱」,你给它一串汉字,它立马合成语音。JQ8900是「放录音」,你得先把音频文件烧进去,它只管播放。我在项目中遇到过这样的情况:客户要求电梯到站时播报「欢迎光临XX大厦」,但大厦名字经常换。用JQ8900就得重新烧录,用SYN6288改个字符串就行。所以,动态场景我首选SYN6288。

选型核心原则:需要动态合成文本 → SYN6288;只需要播放固定音频 → JQ8900。如果预算充足且对音质要求高,也可以两者搭配使用。

4.2 UART与I2C通信接口详解

这两个模块都支持UART,但SYN6288只走UART,JQ8900还能走I2C。嗯,这里得掰扯清楚。

4.2.1 UART通信(通用异步收发)

说白了,UART就是三根线:TX、RX、GND。我习惯用STM32的USART1接语音模块,波特率设9600。为什么是9600?因为SYN6288默认就是这个速率,省得去改配置寄存器。

我曾经踩过一个坑:用115200波特率跟SYN6288通信,结果模块完全不响应。查了半天手册才发现,它最高只支持19200。所以,老老实实用9600最稳。

UART的驱动代码其实很简单,就是发一串十六进制指令。比如让SYN6288说「你好」:

// 发送语音合成指令示例(C语言伪代码)
uint8_t cmd[] = {
    0xFD,           // 帧头
    0x00, 0x06,     // 数据长度(6字节)
    0x01,           // 命令字:语音合成
    0x00,           // 命令参数:无
    '你', '好'      // 待合成文本(GB2312编码)
};
UART_Send(cmd, sizeof(cmd));

注意,文本必须是GB2312编码。我刚开始用UTF-8发过去,模块直接吐出一堆乱码。后来在代码里加了个编码转换函数才搞定。

4.2.2 I2C通信(仅JQ8900支持)

JQ8900的I2C模式适合引脚紧张的场景。它作为从机,地址是0x2A(7位地址)。我一般用硬件I2C,因为软件模拟太费CPU。

I2C的指令格式比UART简单,直接发设备地址+寄存器地址+数据就行。比如播放第3首音频:

// I2C播放指令示例
uint8_t addr = 0x2A << 1;  // 左移1位,加上读写位
uint8_t reg = 0x01;         // 播放控制寄存器
uint8_t data = 0x03;        // 播放第3首
I2C_Write(addr, reg, data);

我的小技巧:如果MCU的I2C引脚不够用,可以用两个GPIO模拟I2C时序。但注意,模拟I2C的速率别超过100kHz,否则JQ8900可能丢数据。

4.3 语音合成指令集解析

这部分是核心中的核心。你想想看,指令发不对,模块就是个哑巴。我当年啃SYN6288的指令集时,差点把手册翻烂了。下面我把最常用的指令提炼出来。

4.3.1 SYN6288指令格式

所有指令都遵循一个固定帧结构:

帧头(0xFD) + 数据长度(2字节) + 命令字(1字节) + 命令参数(1字节) + 数据(N字节)

数据长度 = 命令字 + 命令参数 + 数据的总字节数。这个很容易算错。我习惯用Excel做个计算模板,每次填数据自动算长度。

常用命令字:

  • 0x01:语音合成。参数为0时,合成后等待;参数为1时,合成后立即播放。
  • 0x02:停止合成。无参数,直接发0xFD 00 02 02 00。
  • 0x03:暂停合成。参数为0时暂停,参数为1时恢复。
  • 0x21:设置音量。参数范围0x00~0x0F(0最小,15最大)。
  • 0x22:设置语速。参数范围0x00~0x0F(0最慢,15最快)。

举个例子,设置音量为10(0x0A):

0xFD 0x00 0x03 0x21 0x0A

数据长度是3(命令字0x21 + 参数0x0A + 无数据)。

4.3.2 JQ8900指令集

JQ8900的指令更简单,因为它只管播放。UART模式下,指令格式是:

起始位(0x7E) + 数据长度(2字节) + 命令字(1字节) + 数据(N字节) + 校验和(1字节) + 结束位(0xEF)

常用命令:

  • 0x01:播放指定曲目。数据为曲目编号(0~65535)。
  • 0x02:暂停播放。无数据。
  • 0x03:恢复播放。无数据。
  • 0x04:停止播放。无数据。
  • 0x06:设置音量。数据为音量值(0~30)。

校验和的计算方式是:从数据长度到数据结束的所有字节累加,取低8位。我刚开始写JQ8900驱动时,校验和算错了好几次,模块就是不响应。后来写了个小函数自动算,再也没出过问题。

注意:JQ8900的音频文件命名必须遵循「序号+下划线+文件名」的格式,比如「01_开门.wav」「02_关门.wav」。否则模块找不到文件,会一直沉默。

4.4 实战中的避坑指南

最后,分享几个我亲身踩过的坑,希望能帮你省点时间。

  • 电源纹波问题:语音模块对电源很敏感。我曾经用LDO直接供电,结果喇叭里一直有滋滋声。后来在模块电源脚加了个100μF电解电容和0.1μF瓷片电容,问题解决。
  • 电平匹配:STM32是3.3V,SYN6288是5V。直接连会烧模块。我习惯用两个三极管搭个电平转换电路,或者直接用TXS0108E芯片。
  • 音频文件格式:JQ8900只支持16kHz、16bit、单声道的WAV文件。我一开始用48kHz的MP3转WAV,播放出来像快进一样。后来用Audacity统一转成16kHz才正常。
  • 指令间隔:SYN6288合成一句话需要时间(约0.5~2秒)。连续发指令会导致丢帧。我一般在每条指令后加个500ms延时,或者等模块返回「合成完成」状态再发下一条。

好了,这一讲就到这里。语音模块选型和驱动,说白了就是「选对芯片、接对线、发对指令」。下一讲咱们会深入讲音频文件的制作和烧录流程,到时候再聊。