【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 
    }       
}
​
这是一个很有意思的模块,快去学吧,你会爱上它的!
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值