SYN6288语音合成模块
刚刚例会被叫起来问这周学习遇到的问题。我把上篇学的LU-ASR01语音模块遇到的问题问了出来,就是我想让语音模块读取单片机发送给它的数据(这个牵扯到软串口、算法之类的)。然后学长给了我一个SYN6288模块(到手的那一刻就有点激动,感觉很好玩的样子,因为它上面还有一个白色的大扬声器)
一、简介
SYN6288语音合成模块是一种语音合成设备,其可实现文字转语音功能,将输入的文字信息通过内部的处理和合成,输出相对应的语音信息。SYN6288模块具有语音合成质量高、输出音质好、使用方便等特点,因此广泛应用于语音播报、语音提示、语音识别、智能家居、智能家电、安防监控等领域。
SYN6288语音合成模块的特性如下:
支持多语言:包括中文、英文、日文、韩文等多种语言。
支持音量、语速、语调控制:可以通过外部控制模块来调整合成语音的音量、语速和语调,满足不同场合和需求下的需求。
音频输出接口:模块内置了DAC接口,可以直接连接扬声器输出语音。
低功耗:工作电流小,运行稳定可靠。
支持外部控制:模块上有12个通用IO引脚,可对模块进行控制及调试。 (原文链接:STM32 使用SYN6288语音模块-CSDN博客)
二、引脚
这个模块只需要接4个引脚即可工作:
RXD—板子上的TXD TXD—板子上的RXD VCC—VCC(5V) GND—GND
BUSY引脚不接
[STM32F103ZET6]上(我代码用的串口3)
RXD:PB11————接模块TXD
TXD:PB10————接模块RXD
三、原理图
波特率出厂默认9600!!
四、代码
main.c
/*
SYN6288语音合成模块
项目功能:将文字转化成语音,并朗读出来,出厂默认波特率9600。
VCC--5V
RXD--PB10
TXD--PB11
GND--GND
*/
#include "sys.h"
#include "delay.h"
#include "stdio.h"
#include "usart.h"
#include "syn6288.h"
u8 SYN_StopCom[] = {0xFD, 0X00, 0X02, 0X02, 0XFD}; //停止合成
u8 SYN_SuspendCom[] = {0XFD, 0X00, 0X02, 0X03, 0XFC}; //暂停合成
u8 SYN_RecoverCom[] = {0XFD, 0X00, 0X02, 0X04, 0XFB}; //恢复合成
u8 SYN_ChackCom[] = {0XFD, 0X00, 0X02, 0X21, 0XDE}; //状态查询
u8 SYN_PowerDownCom[] = {0XFD, 0X00, 0X02, 0X88, 0X77}; //进入POWER DOWN 状态命令
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
delay_init();
USART3_Init(9600);
while(1)
{
//选择背景音乐2。(0:无背景音乐 1-15:背景音乐可选)
//m[0~16]:0背景音乐为静音,16背景音乐音量最大
//v[0~16]:0朗读音量为静音,16朗读音量最大
//t[0~5]:0朗读语速最慢,5朗读语速最快
SYN_FrameInfo(0, "[v2][m0][t5]早点去干饭 !");
delay_ms(1500);
delay_ms(1500);
delay_ms(1500);
delay_ms(1500);
delay_ms(1500);
delay_ms(1500);
//暂停合成,此时没有用到,用于展示函数用法
//YS_SYN_Set(SYN_SuspendCom);
}
}
syn6288.h
#ifndef __SYN6288_H
#define __SYN6288_H
#include "sys.h"
void SYN_FrameInfo(u8 Music, u8 *HZdata);
void YS_SYN_Set(u8 *Info_data);
#endif
syn6288.c
#include "syn6288.h"
#include "usart.h"
#include "string.h"
#include "delay.h"
//Music:选择背景音乐。0:无背景音乐,1~15:选择背景音乐
void SYN_FrameInfo(u8 Music, u8 *HZdata)
{
/****************需要发送的文本**********************************/
unsigned char Frame_Info[50];
unsigned char HZ_Length;
unsigned char ecc = 0; //定义校验字节
unsigned int i = 0;
HZ_Length = strlen((char*)HZdata); //需要发送文本的长度
/*****************帧固定配置信息**************************************/
Frame_Info[0] = 0xFD ; //构造帧头FD
Frame_Info[1] = 0x00 ; //构造数据区长度的高字节
Frame_Info[2] = HZ_Length + 3; //构造数据区长度的低字节
Frame_Info[3] = 0x01 ; //构造命令字:合成播放命令
Frame_Info[4] = 0x01 | Music << 4 ; //构造命令参数:背景音乐设定
/*******************校验码计算***************************************/
for(i = 0; i < 5; i++) //依次发送构造好的5个帧头字节
{
ecc = ecc ^ (Frame_Info[i]); //对发送的字节进行异或校验
}
for(i = 0; i < HZ_Length; i++) //依次发送待合成的文本数据
{
ecc = ecc ^ (HZdata[i]); //对发送的字节进行异或校验
}
/*******************发送帧信息***************************************/
memcpy(&Frame_Info[5], HZdata, HZ_Length);
Frame_Info[5 + HZ_Length] = ecc;
USART3_SendString(Frame_Info, 5 + HZ_Length + 1);
}
/************************************本函数用于配置,停止合成、暂停合成等设置 ,默认波特率9600bps。
****************************/
void YS_SYN_Set(u8 *Info_data)
{
u8 Com_Len;
Com_Len = strlen((char*)Info_data);
USART3_SendString(Info_data, Com_Len);
}
usart.h
#ifndef __USART_H
#define __USART_H
#include "stdio.h"
#include "sys.h"
#define USART3_REC_LEN 200 //定义最大接收字节数 200
#define EN_USART3_RX 1 //使能(1)/禁止(0)串口1接收
extern u8 USART3_RX_BUF[USART3_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern u16 USART3_RX_STA; //接收状态标记
//如果想串口中断接收,请不要注释以下宏定义
void USART3_SendString(u8 *DAT,u8 len);
void USART3_SendData(u8 data);
void USART3_Init(u32 bound);
#endif
usart.c
#include "sys.h"
#include "usart.h"
#include "timer.h"
#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{
int handle;
};
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{
while((USART3->SR & 0X40) == 0); //循环发送,直到发送完毕
USART3->DR = (u8) ch;
return ch;
}
#endif
void USART3_SendData(u8 data)
{
while((USART3->SR & 0X40) == 0);
USART3->DR = data;
}
void USART3_SendString(u8 *DAT, u8 len)
{
u8 i;
for(i = 0; i < len; i++)
{
USART3_SendData(*DAT++);
}
}
#if EN_USART3_RX //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误
u8 USART3_RX_BUF[USART3_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15, 接收完成标志
u16 USART3_RX_STA = 0; //接收状态标记
void USART3_Init(u32 bound)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能USART3,GPIOC时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
//USART3_TX GPIOC.10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
//USART3_RX GPIOC.11初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
//USART3 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3 ; //抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//USART 初始化设置
USART_InitStructure.USART_BaudRate = bound;//串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART3, &USART_InitStructure); //初始化串口1
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启串口接受中断
USART_Cmd(USART3, ENABLE); //使能串口1
TIM3_Int_Init(99, 7199); //10ms中断
USART3_RX_STA = 0; //清零
TIM_Cmd(TIM3, DISABLE); //关闭定时器7
}
void USART3_IRQHandler(void) //串口1中断服务程序
{
u8 Res;
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
{
Res = USART_ReceiveData(USART3); //读取接收到的数据
if((USART3_RX_STA & 0x8000) == 0) //接收未完成
{
if(USART3_RX_STA < USART3_REC_LEN) //还可以接收数据
{
TIM_SetCounter(TIM3, 0); //计数器清空 //计数器清空
if(USART3_RX_STA == 0) //使能定时器7的中断
{
TIM_Cmd(TIM3, ENABLE); //使能定时器7
}
USART3_RX_BUF[USART3_RX_STA++] = Res; //记录接收到的值
}
else
{
USART3_RX_STA |= 1 << 15; //强制标记接收完成
}
}
}
}
#endif
timer.h
#include "sys.h"
#include "usart.h"
#include "timer.h"
#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{
int handle;
};
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{
while((USART3->SR & 0X40) == 0); //循环发送,直到发送完毕
USART3->DR = (u8) ch;
return ch;
}
#endif
void USART3_SendData(u8 data)
{
while((USART3->SR & 0X40) == 0);
USART3->DR = data;
}
void USART3_SendString(u8 *DAT, u8 len)
{
u8 i;
for(i = 0; i < len; i++)
{
USART3_SendData(*DAT++);
}
}
#if EN_USART3_RX //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误
u8 USART3_RX_BUF[USART3_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15, 接收完成标志
u16 USART3_RX_STA = 0; //接收状态标记
void USART3_Init(u32 bound)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能USART3,GPIOC时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
//USART3_TX GPIOC.10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
//USART3_RX GPIOC.11初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
//USART3 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3 ; //抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//USART 初始化设置
USART_InitStructure.USART_BaudRate = bound;//串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART3, &USART_InitStructure); //初始化串口1
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启串口接受中断
USART_Cmd(USART3, ENABLE); //使能串口1
TIM3_Int_Init(99, 7199); //10ms中断
USART3_RX_STA = 0; //清零
TIM_Cmd(TIM3, DISABLE); //关闭定时器7
}
void USART3_IRQHandler(void) //串口1中断服务程序
{
u8 Res;
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
{
Res = USART_ReceiveData(USART3); //读取接收到的数据
if((USART3_RX_STA & 0x8000) == 0) //接收未完成
{
if(USART3_RX_STA < USART3_REC_LEN) //还可以接收数据
{
TIM_SetCounter(TIM3, 0); //计数器清空 //计数器清空
if(USART3_RX_STA == 0) //使能定时器7的中断
{
TIM_Cmd(TIM3, ENABLE); //使能定时器7
}
USART3_RX_BUF[USART3_RX_STA++] = Res; //记录接收到的值
}
else
{
USART3_RX_STA |= 1 << 15; //强制标记接收完成
}
}
}
}
#endif
timer.c
#include "timer.h"
#include "usart.h"
//通用定时器7中断初始化
//这里时钟选择为APB1的2倍,而APB1为42M
//arr:自动重装值。
//psc:时钟预分频数
//定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
//Ft=定时器工作频率,单位:Mhz
//通用定时器中断初始化
//这里始终选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
void TIM3_Int_Init(u16 arr,u16 psc)
{
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//TIM3时钟使能
//定时器TIM3初始化
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
TIM_Cmd(TIM3,ENABLE);//开启定时器7
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //子优先级2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
}
//定时器7中断服务程序
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)//是更新中断
{
USART3_RX_STA|=1<<15; //标记接收完成
TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIM3更新中断标志
TIM_Cmd(TIM3, DISABLE); //关闭TIM3
}
}
这是一个很有意思的模块,快去学吧,你会爱上它的!