当前位置: 首页 > news >正文

STM32 智能垃圾桶项目笔记(五):语音合成模块(SYN6288)配置与语音播报实现

本系列笔记是笔者学习 B 站 up 主 “技术探索者” STM32 系列视频所作的记录,不理解的地方推荐观看视频~

目录

  • 一、前言
  • 二、语音合成模块(SYN6288)核心内容
    • 2.1 模块特性与接线说明
    • 2.2 通信协议:帧格式与命令逻辑
    • 2.3 CubeMX 配置(串口 2 9600 波特率)
  • 三、代码实现(驱动 + 主程序)
    • 3.1 驱动文件(driver_SYN6288.c)
    • 3.2 主程序与中断回调函数
  • 四、关键疑问解答:为何串口 2 无需手动启动接收?
  • 五、下一篇预告:智能垃圾桶功能整合
  • 六、总结

一、前言

大家好,我是 Hello_Embed。上一篇我们完成了舵机(SG90)的控制,实现了 “定时转动” 功能。本次笔记聚焦智能垃圾桶的 “交互体验升级”—— 通过 SYN6288 语音合成模块 实现 “语音播报” 功能,比如开盖时播放 “欢迎使用”、关盖时播放 “谢谢使用”。

需要说明的是:SYN6288 仅负责 “文字转语音”(TTS),不涉及语音识别功能(语音识别后续若有需求再补充)。本次将从模块特性、通信协议、配置到代码实现,完整覆盖 “中文语音播报” 的核心流程。

二、语音合成模块(SYN6288)核心内容

2.1 模块特性与接线说明

2.1.1 核心特性

SYN6288 是一款低成本、高音质的语音合成模块,核心优势如下:

  • 功能:支持中文 / 英文文字转语音,可设置背景音乐、语速、音量;
  • 通信:基于串口(UART)通信,配置简单,仅需 4 根线;
  • 编码:支持 GB2312、GBK、BIG5、UNICODE 等编码(中文需用 GB2312 或 GBK);
  • 数据长度:单次最大支持 206 字节数据发送(满足日常播报需求);
  • 波特率:默认 9600(可通过命令修改,与蓝牙、超声波的串口波特率区分)。
2.1.2 接线图与原则

模块接线图如下:
请添加图片描述

接线原则(串口交叉连接,5V 供电)

SYN6288 引脚功能连接对象(STM32)说明
VCC电源正极5V 引脚模块仅支持 5V 供电,勿接 3.3V
GND电源负极GND 引脚必须与 STM32 共地,避免干扰
RXD模块接收端串口 2 TX(PA2)模块接收 STM32 发送的指令
TXD模块发送端串口 2 RX(PA3)模块向 STM32 反馈状态(可选)

2.2 通信协议:帧格式与命令逻辑

SYN6288 采用 “帧结构” 通信,所有指令(配置、语音播报)需按固定格式发送,核心帧格式如下:帧头(1字节) + 数据区长度(2字节) + 数据区(≤203字节)

各部分详细说明:
  1. 帧头:固定为 0xFD(模块仅识别此帧头的指令,避免误触发);
  2. 数据区长度:2 字节,高字节在前、低字节在后,代表 “数据区的总字节数”;
  3. 数据区:包含 4 部分,总长度需与 “数据区长度” 匹配:
    • 命令字(1 字节):如 0x01 代表 “语音合成”、0x00 代表 “参数配置”;
    • 命令参数(1 字节):如设置编码格式、背景音乐开关;
    • 待发送文本(≤200 字节):需按指定编码(如 GB2312)转换为字节数组;
    • 异或校验(1 字节):对 “帧头 + 数据区长度 + 数据区前 n-1 字节” 进行异或运算,确保数据传输无误。
示例:“宇音天下” 语音播报帧

以发送 8 字节 “宇音天下”(GB2312 编码)为例,帧结构拆解:
请添加图片描述

  • 帧头:0xFD
  • 数据区长度:0x00 0x0B(十进制 11,代表数据区共 11 字节);
  • 数据区:0x01(命令字:语音合成) + 0x01(命令参数:无背景音乐) + “宇音天下”8字节编码 + 异或校验值
  • 最终整帧数据符合 “帧头 + 长度 + 数据区” 的格式,模块接收后会解析并播报。
波特率与编码配置
  • 默认波特率:9600(无需修改,与手机蓝牙调试 APP 兼容性好);
  • 中文编码:必须使用 GB2312 或 GBK(否则会出现乱码 / 无语音),本次选择 GB2312(收录 6000+ 常用汉字,满足需求)。

2.3 CubeMX 配置(串口 2 9600 波特率)

使用 串口 2 与 SYN6288 通信(避免与串口 1/3 冲突),配置步骤如下:

  1. 进入 Connectivity → USART2,模式选择 Asynchronous(异步通信);
  2. 基本参数配置:
    • 波特率:9600(与模块默认波特率一致);
    • 数据位:8,停止位:1,校验位:None(标准串口参数);
  3. 使能中断:勾选 NVIC Settings → USART2 global interrupt(接收模块反馈信息);
  4. 引脚:串口 2 默认引脚为 PA2(TX)、PA3(RX),无需手动修改;
  5. 生成工程:确认基础配置不变,点击 Generate Code,编译无错误即可。

三、代码实现(驱动 + 主程序,仅加注释)

核心需求:① 封装驱动函数(构造语音帧、发送配置命令);② 主程序实现 “编码初始化 + 中文语音播报”;③ 中断回调处理串口 2 接收。

3.1 驱动文件(driver_SYN6288.c)

#include "driver_SYN6288.h"
#include <string.h>  // 用于 memcpy 函数(复制数组)// 声明串口2 句柄(CubeMX 自动生成在 usart.c 中,需确保包含 usart.h)
extern UART_HandleTypeDef huart2;/*** @brief  串口2 数据发送函数(SYN6288 专用)* @param  buf:待发送的字节数组* @param  len:待发送的字节数* @retval 无* @note   调用 HAL_UART_Transmit 阻塞发送,超时时间 1000ms*/
void SendStr5(unsigned char* buf, unsigned int len)
{// 向串口2 发送数据,超时 1000ms(确保模块有足够时间接收)HAL_UART_Transmit(&huart2, buf, len, 1000);
}/*** @brief  构造 SYN6288 语音合成帧并发送* @param  Music:背景音乐选择(0=无音乐,1~15=不同背景音乐)* @param  HZdata:待播报的文本字节数组(需按 GB2312 编码)* @retval 无* @note   帧结构:帧头(0xFD) + 数据区长度 + 命令字(0x01) + 命令参数 + 文本 + 异或校验*/
void SYN_FrameInfo(uint8_t Music, uint8_t *HZdata)
{unsigned char Frame_Info[50];// 存放整帧数据(最大支持 50 字节,满足短文本播报)unsigned char HZ_Lenth;// 待播报文本的字节长度unsigned char ecc = 0;// 异或校验值(初始化为 0)unsigned int i = 0;// 计算待播报文本的长度(HZdata 为 GB2312 编码的字节数组,strlen 统计字节数)HZ_Lenth = strlen((char*)HZdata);// -------------------------- 1. 构造帧头与数据区长度 --------------------------Frame_Info[0] = 0xFD;          // 帧头:固定为 0xFDFrame_Info[1] = 0x00;          // 数据区长度高字节:当前文本短,高字节为 0Frame_Info[2] = HZ_Lenth + 3;  // 数据区长度低字节:文本长度 + 3(命令字1 + 命令参数1 + 校验1)// -------------------------- 2. 构造命令字与命令参数 --------------------------Frame_Info[3] = 0x01;                  // 命令字:0x01 代表“语音合成”Frame_Info[4] = 0x01 | Music << 4;     // 命令参数:低4位 0x01(正常语速),高4位 Music(背景音乐)// -------------------------- 3. 计算异或校验 --------------------------// 第一步:对帧头+数据区长度+命令字+命令参数(前5字节)进行异或for(i = 0; i < 5; i++){ecc = ecc ^ (Frame_Info[i]);  // 异或运算:相同为 0,不同为 1}// 第二步:对待播报文本的每个字节进行异或(确保文本数据无传输错误)for(i = 0; i < HZ_Lenth; i++){ecc = ecc ^ (HZdata[i]);}// -------------------------- 4. 组装整帧数据并发送 --------------------------memcpy(&Frame_Info[5], HZdata, HZ_Lenth);  // 将文本字节数组复制到帧的第5位开始Frame_Info[5 + HZ_Lenth] = ecc;            // 帧的最后一位:异或校验值// 发送整帧数据:长度 = 前5字节(帧头+长度+命令) + 文本长度 + 1字节校验SendStr5(Frame_Info, 5 + HZ_Lenth + 1);
}/*** @brief  SYN6288 模块参数配置函数(发送配置命令)* @param  Info_data:配置命令字节数组(需按模块帧格式构造)* @retval 无* @note   用于发送编码设置、波特率修改等配置指令*/
void YS_SYN_Set(uint8_t *Info_data)
{uint8_t Com_Len;// 计算配置命令的总长度(Info_data 为完整的配置帧)Com_Len = strlen((char*)Info_data);// 发送配置命令到串口2SendStr5(Info_data, Com_Len);
}

3.2 主程序与中断回调函数

#include "main.h"
#include "usart.h"
#include "gpio.h"
#include "driver_SYN6288.h"// 全局变量:语音模块(串口2)接收缓冲区(存储模块反馈的状态信息)
uint8_t SYS6288Rx = 0;
// 全局变量:蓝牙模块(串口3)接收缓冲区(上一篇定义,此处复用)
uint8_t Rx_dat = 0;/*** @brief  串口接收中断回调函数(处理串口3 蓝牙、串口2 语音的接收)* @param  huart:触发中断的串口句柄* @retval 无* @note   1. 串口3(蓝牙):接收指令控制 PA7 LED 亮灭;*         2. 串口2(语音):接收模块反馈,重启接收中断以持续接收*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{// 若中断来自串口3(蓝牙模块)if(huart->Instance == USART3){// 接收到 0xA1(十六进制):点亮 PA7 LEDif(Rx_dat == 0xa1){HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_RESET);// PA7 拉低,LED 亮}// 接收到 0xA2(十六进制):熄灭 PA7 LEDelse if(Rx_dat == 0xa2){HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET);  // PA7 拉高,LED 灭}// 重启串口3 接收中断(确保下次能继续接收蓝牙指令)HAL_UART_Receive_IT(&huart3, &Rx_dat, 1);}// 若中断来自串口2(语音模块)else if(huart->Instance == USART2){// 重启串口2 接收中断(接收模块反馈的状态,如“播报完成”信号)HAL_UART_Receive_IT(&huart2, &SYS6288Rx, 1);}
}int main(void)
{// 1. 初始化 HAL 库、外设(CubeMX 自动生成:串口2/3、GPIO 等)HAL_Init();MX_GPIO_Init();MX_USART2_UART_Init();MX_USART3_UART_Init();// -------------------------- 2. 初始化 SYN6288 语音模块 --------------------------// 配置命令:设置模块为 GB2312 编码(确保中文播报正常)// 帧结构解析:0xFD(帧头) + 0x00 0x08(数据区长度8字节) + 0x01(命令字:参数配置) + 0x00(命令类型:编码设置) + 0x01(编码:GB2312) + 0x00 0x00 0x00(保留) + 0x08(异或校验值)uint8_t initCmd[] = {0xFD, 0x00, 0x08, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08};YS_SYN_Set(initCmd);  // 发送编码配置命令HAL_Delay(500);        // 延时 500ms,等待模块初始化完成(避免后续指令发送失败)// -------------------------- 3. 播报中文语音:“你好嵌入式” --------------------------// helloStr:“你好嵌入式”的 GB2312 编码字节数组(0x00 为结束符)// 编码对应:0xC4E3=你,0xBAC3=好,0xC7B0=嵌,0xC8EB=入,0xCABD=式uint8_t helloStr[] = {0xC4, 0xE3, 0xBA, 0xC3, 0xC7, 0xB0, 0xC8, 0xEB, 0xCA, 0xBD, 0x00}; SYN_FrameInfo(0, (char*)helloStr);  // 发送语音帧:0=无背景音乐,helloStr=待播报文本// 4. 主循环(仅延时,无其他逻辑,专注测试语音播报)while (1){HAL_Delay(100);  // 延时 100ms,避免主循环空跑占用资源}
}

四、关键疑问解答:为何串口 2 无需手动启动接收?

上一篇中,蓝牙模块(串口 3)需在 main 中调用 HAL_UART_Receive_IT(&huart3, &Rx_dat, 1) 启动接收,而语音模块(串口 2)无需手动启动,核心原因如下:

  • 串口 3(蓝牙):模块上电后无主动信号输出,需手动调用 HAL_UART_Receive_IT 开启中断,才能检测后续的蓝牙指令;
  • 串口 2(语音):在调用 YS_SYN_Set(initCmd) 发送 “编码配置命令” 时,模块接收指令后会主动向 STM32 发送反馈信号(如 “配置成功” 信号),此反馈信号会触发串口 2 的接收中断,进入 HAL_UART_RxCpltCallback
  • 在回调函数中,已添加 HAL_UART_Receive_IT(&huart2, &SYS6288Rx, 1) 重启接收中断,因此后续模块的反馈信号能被持续接收,无需在 main 中手动启动。

五、下一篇预告:智能垃圾桶功能整合

至此,智能垃圾桶的四大核心模块(超声波测距、蓝牙通信、舵机控制、语音播报)已全部实现。下一篇将进行 功能整合,实现完整的 “智能开盖” 逻辑。

项目定位为 “练手级”,无需复杂结构,后续可根据需求用 3D 打印制作垃圾桶外壳,进一步完善硬件。

六、总结

本次笔记围绕 SYN6288 语音模块展开,核心收获包括:

  1. 掌握模块的串口接线与通信协议(帧头 0xFD + 数据区长度 + 数据区 + 校验);
  2. 理解中文语音播报的关键:需使用 GB2312/GBK 编码,并用 SYN_FrameInfo 构造语音帧;
  3. 区分不同串口的中断启动逻辑,解决 “为何串口 2 无需手动启动接收” 的疑问。

下一篇将是本项目的 “收尾篇”,通过整合四大模块,实现 “感知 - 决策 - 执行 - 交互” 的完整智能垃圾桶功能。请关注 Hello_Embed,见证项目最终落地!

http://www.dtcms.com/a/435255.html

相关文章:

  • 移动互联网开发应聘四川网站营销seo费用
  • 找北京赛车网站开发wordpress 自定义页面
  • MATLAB信号处理实用指南:从入门到精通
  • 成都住建局官网报名入口网址兴安盟seo
  • 中国建设银行手机网站下载安装托管的服务器如何做网站
  • P13977题解
  • 网络推广岗位职责和任职要求成都做整站优化
  • DAY 38 Dataset和Dataloader类 - 2025.10. 2
  • Privacy Eraser(隐私保护软件)多语便携版
  • C4D R20新增功能概述及体积对象SDF类型深度解析
  • 上海做网站公司推荐简单网上书店网站建设php
  • HarmonyOS应用开发深度解析:ArkTS语法精要与UI组件实践
  • 北京示范校建设网站wordpress快速发布
  • 常用网站布局土巴兔这种网站怎么做
  • toLua[四] Examples 03_CallLuaFunction分析
  • 建设景区网站推文企业网站排名怎么优化
  • 汽车信息安全测试与ISO/SAE 21434标准
  • Hadoop HA 集群安装配置
  • 10.2总结
  • 旅游网站建设最重要的流程如何制作公众号教程
  • 淄博建设局网站秀堂h5官网
  • 【动态规划DP:纸币硬币专题】P2834 纸币问题 3
  • springbatch使用记录
  • 平面设计师网站都有哪些网站突然被降权怎么办
  • 前向传播与反向传播(附视频链接)
  • 广州建设工程造价管理站橙色网站欣赏
  • ipv6之6to4配置案例
  • 太仓有专门做网站的地方吗沧州企业网站专业定制
  • gRPC从0到1系列【14】
  • JVM的内存分配策略有哪些?