【STM32F103】SYN6288语音合成模块

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 
    }       
}
​
这是一个很有意思的模块,快去学吧,你会爱上它的!
  • 31
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
### 回答1: 好的,我可以回答关于使用SYN6288语音合成模块STM32微控制器集成的问题。 首先,您需要了解SYN6288模块如何工作。该模块需要使用串口通信与微控制器进行通信,并使用控制指令来实现语音合成和播放。 为了将SYN6288模块STM32微控制器集成,您需要连接模块的串口引脚(RX和TX)到STM32的对应引脚。然后,您需要编写STM32的固件以向模块发送控制指令并接收从模块返回的数据。这可以通过使用STM32的串口库和适当的控制指令来完成。 在编写固件时,您还需要考虑如何将语音合成数据发送到SYN6288模块进行播放。您可以将语音数据存储在STM32的内部存储器或外部存储器中,并使用控制指令将数据发送到SYN6288模块进行播放。 总之,将SYN6288语音合成模块STM32微控制器集成需要一定的硬件和软件开发知识。如果您没有足够的经验,建议寻求专业帮助或参考相关文档和示例代码。 ### 回答2: syn6288语音合成模块是一种基于LC8976芯片的语音合成电路板,可通过串口与控制单元(如STM32)进行通信,以实现语音合成、播放等功能。该模块具有音量控制、语音速度控制、音调控制等多种功能,可以实现多种语音效果。 对于STM32来说,它可以作为语音合成模块的主控制单元,通过与syn6288模块进行通信,实现对语音合成的控制。通过STM32syn6288的组合使用,可以实现对语音播报、语音提示等应用场景的支持,例如语音播报温度、湿度等环境参数、语音提示用户操作指南等。 在应用时,需要将syn6288模块STM32进行连接,在程序中通过串口的通信方式,向syn6288发送指令实现语音播报。在进行语音合成前,需要将要合成语音文本通过串口发送给syn6288模块syn6288模块将会进行语音合成并将合成后的音频数据通过PWM输出声音信号。控制syn6288模块的各项参数可以通过串口指令进行设置,例如控制语音的音量大小、语速快慢、音调高低等。 总体而言,syn6288语音合成模块作为一种应用广泛的语音合成电路板,可以与多种控制单元进行通信,包括STM32等嵌入式系统,实现多方面的语音合成、播报等应用场景。同时,由于syn6288模块结构简单、使用方便,因此在实际应用中受到越来越多的重视和应用。 ### 回答3: syn6288语音合成模块是一款高质量、低成本的语音合成模块。它采用先进的数字信号处理技术,可实现自然、流畅的语音合成效果。此模块还支持多种语音、音调、语速、音量等参数的设置,可满足不同场景下的语音合成需求。 syn6288语音合成模块stm32的结合能够为嵌入式系统提供可靠的语音交互解决方案。在使用过程中,我们通常需要将模块stm32进行串口通信。通过串口指令,可以实现模块的初始化、语音合成语音播放、音调调节、语速调节、音量调节等功能。例如,我们可以通过以下指令实现语音合成: FE FE 0C 01 01 32 33 34 35 04 72 0D 0A 其中,FE FE为起始标志符;0C为指令长度;01为指令类型(语音合成);01为语音合成对象(表示“12345”);32 33 34 35为要合成的文字;04为校验和;72为结束标志符(ASCII字符“r”)。 通过以上指令,模块会将“12345”合成语音并存储在内部Flash中,返回“合成成功”指令。接着,我们可以通过以下指令实现语音播放: FE FE 02 01 00 FD 0D 0A 其中,02为指令长度;01为指令类型(播放语音);00为语音序号(表示刚才合成语音序号);FD为校验和。 通过以上指令,模块会从内部Flash中读取相应语音并进行播放。此外,我们还可以通过其他串口指令实现音调、语速、音量的调节以及其他功能的设置。 综上所述,syn6288语音合成模块stm32具有语音合成质量高、成本低、易于使用、功能丰富等特点,可以广泛应用于智能家居、智能机器人、语音交互设备等领域。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值