平台:NanoPi fire3
系统:Ubuntu core+Qt5.10(linux kernel 4.4)
语音模块:SYN6288A
模块链接:https://item.taobao.com/item.htm?spm=a1z09.2.0.0.6fa82e8dV9HJVN&id=575307622242&_u=51pfiddhc204
使用引脚信息
串口3对应设备结点/dev/ttySAC3
模块官方给了51单片机的程序,现在修改并移植到linux中运行
修改了其中两个头文件,如下
SYN6288.h
/***************************乐声电子科技有限公司****************************
** 工程名称:YS-SYN6288语音合成配套程序
** CPU: STC89LE52
** 晶振:22.1184MHZ
** 波特率:9600 bit/S
** 配套产品信息:YS-SYN6288语音合成模块
** http://yuesheng001.taobao.com
** 作者:zdings
** 联系:751956552@qq.com
** 修改日期:2012.8.25
** 说明:。。
/***************************乐声电子科技有限公司******************************/
#ifndef SYN6288_H
#define SYN6288_H
#include <stdlib.h>
#include "config.h"
/**************芯片设置命令*********************/
uint8_t SYN_StopCom[]={0xFD,0X00,0X02,0X02,0XFD};//停止合成
uint8_t SYN_SuspendCom[]={0XFD,0X00,0X02,0X03,0XFC};//暂停合成
uint8_t SYN_RecoverCom[]={0XFD,0X00,0X02,0X04,0XFB};//恢复合成
uint8_t SYN_ChackCom[]={0XFD,0X00,0X02,0X21,0XDE};//状态查询
uint8_t SYN_PowerDownCom[]={0XFD,0X00,0X02,0X88,0X77};//进入POWER DOWN 状态命令
/***********************************************/
/***********************************************************
* 名 称: YS-SYN6288 文本合成函数
* 功 能: 发送合成文本到SYN6288芯片进行合成播放
* 入口参数:Music(背景音乐选择):0无背景音乐。1-15:相关背景音乐
*HZdata:文本指针变量
* 出口参数:
* 说 明: 本函数只用于文本合成,具备背景音乐选择。默认波特率9600bps。
* 调用方法:例: SYN_FrameInfo(0,“乐声电子科技”);
**********************************************************/
int SYN_FrameInfo(uint8_t Music,uint8_t *HZdata, unsigned char *buf)
{
/****************需要发送的文本**********************************/
unsigned char *Frame_Info = buf;
unsigned char HZ_Length;
unsigned char ecc = 0; //定义校验字节
unsigned int i=0;
HZ_Length =strlen(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;
return 5+HZ_Length+1;
//PrintCom(Frame_Info,5+HZ_Length+1);
}
#endif
config.h
/******************** 飞音云电子***************
* File Name : config.h
* Author : http://yuesheng001.taobao.com/
* Version : zds0.0.3
* Date First Issued : 10/12/2011
* Description : public header file
*******************************************************/
#ifndef __CONFIG_H
#define __CONFIG_H
/*****相关宏定义***/
/* exact-width signed integer types */
typedef signed char int8_t;
typedef signed short int int16_t;
typedef signed int int32_t;
typedef signed long int int64_t;
/* exact-width unsigned integer types */
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long int uint64_t;
#endif
自己编写linux端程序
首先头文件
//标准输入输出头文件
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
//打开文件需要的头文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
//打开串口需要的头文件
#include <termios.h>
#include <unistd.h>
//语音模块的头文件
#include "SYN6288.h"
串口初始化函数
/*******************************************************************************************
函数名:set_opt();
函数作用:串口初始化
参数说明: 参数1:fd----open函数返回的文件句柄
参数2 :nSpeed----波特率设置(2400,4800,9600,115200)
参数3:nBits----数据位设置(7,8)
参数4:nEvent----校验位设置('O','E','N')
参数5:nStop----停止位(1,2)
*******************************************************************************************/
int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop){
struct termios newtio,oldtio;
//将旧的参数配置文件赋给fd指向的文件
if(tcgetattr(fd,&oldtio) != 0){
perror("SetupSerial 1");
return -1;
}
//清空结构体newtio中的数据
bzero(&newtio,sizeof(newtio));
newtio.c_cflag |= CLOCAL|CREAD;
newtio.c_cflag &= ~CSIZE;
//配置数据位
switch (nBits)
{
case 7:{
newtio.c_cflag |= CS7;
break;}
case 8:{
newtio.c_cflag |= CS8;
break;}
}
//配置校验位
switch (nEvent)
{
case 'O':{
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
break;}
case 'E':{
newtio.c_iflag |= (INPCK | ISTRIP);
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
break;}
case 'N':{
newtio.c_cflag &= ~PARENB;
break;}
}
//配置波特率
switch (nSpeed)
{
case 2400:{
cfsetispeed(&newtio,B2400);
cfsetospeed(&newtio,B2400);
break;}
case 4800:{
cfsetispeed(&newtio,B4800);
cfsetospeed(&newtio,B4800);
break;}
case 9600:{
cfsetispeed(&newtio,B9600);
cfsetospeed(&newtio,B9600);
break;}
case 115200:{
cfsetispeed(&newtio,B115200);
cfsetospeed(&newtio,B115200);
break;}
case 460800:{
cfsetispeed(&newtio,B460800);
cfsetospeed(&newtio,B460800);
break;}
default:{
cfsetispeed(&newtio,B9600);
cfsetospeed(&newtio,B9600);
break;}
}
//配置停止位
if(nStop == 1){
newtio.c_cflag &= ~CSTOPB;
}
else if(nStop == 2){
newtio.c_cflag |= CSTOPB;
}
//清空数据
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 0;
/*******************************************************************************************
函数名:tcflush();
函数作用:清空串口缓存器BUFFER中的数据
参数说明: 参数1:fd----open函数返回的文件句柄
参数2:TCIFLUSH----清除正受到的数据,且不会读出来
TCOFLUSH----清除正写入的数据,且不会发送至终端
TCIOFLUSH----清除所有正在发生的IO数据
函数返回值:成功返回0,失败返回-1
*******************************************************************************************/
tcflush(fd,TCIFLUSH);
/*******************************************************************************************
函数名:tcsetattr();
函数作用:设置串口参数函数
参数说明: 参数1:fd----open函数返回的文件句柄
参数2:TCSANOW----不等数据传输完毕就立刻改变属性
TCSADRAIN----等待所有数据传输结束才改变属性
TCSAFLUSH----清空输入输出缓冲区才改变属性
参数3:newtio----在旧的参数基础上修改后的参数
函数返回值:成功返回0,失败返回-1
*******************************************************************************************/
if((tcsetattr(fd,TCSANOW,&newtio)) != 0){
perror("com set error");
return -1;
}
return 0;
}
串口发送函数
static void UART_SendData(int fd,unsigned char *buffer,int count)
{
int j;
write(fd, buffer, count);
//打印发出的数据至屏幕
printf("send : ");
//清空输出流缓存区
fflush(stdout);
for(j=0;j<count;j++)
{
printf("%02X ",buffer[j]);
fflush(stdout);
}
printf("\n");
}
通过命令行传入要转语音的文本
int main(int argc, char **argv)
{
unsigned char *buffer = (unsigned char *)malloc(sizeof(unsigned char) * 200);
int bufSize;
int i, ret;
if(argc != 2)
{
printf("argument number error!!\n");
printf("%s \"the text you want to say\"\n", argv[0]);
return -1;
}
if((fd = open(uartPath,O_RDWR|O_NOCTTY)) < 0)
{
printf("can not open %s\n",uartPath);
return -1;
}
//printf("text: %s\n", argv[1]);
set_opt(fd,9600,8,'N',1);
bufSize = SYN_FrameInfo(0, argv[1], buffer);
UART_SendData(fd, buffer, bufSize);
free(buffer);
free(buffer_gb2312);
close(fd);
return 0;
}
交叉编译成功,测试后发现,语音模块说的东西和实际传入的不一样。
查看模块的数据手册,发现了这个一句话。
由于linux下的文字编码为utf-8,所以语音模块不能识别该编码。
接下来转换编码格式,将传入的utf-8的编码转换为GB2312
加入头文件
//字符编码转换
#include <iconv.h>
//字符编码转换
static int charset_convert(const char *from_charset, const char *to_charset,
char *in_buf, size_t in_left, char *out_buf, size_t out_left)
{
iconv_t icd = (iconv_t)-1;
size_t sRet = -1;
char *pIn = in_buf;
char *pOut = out_buf;
size_t outLen = out_left;
if (NULL == from_charset || NULL == to_charset || NULL == in_buf || 0 >= in_left || NULL == out_buf || 0 >= out_left)
{
return -1;
}
icd = iconv_open(to_charset, from_charset);
if ((iconv_t)-1 == icd)
{
return -1;
}
sRet = iconv(icd, &pIn, &in_left, &pOut, &out_left);
if ((size_t)-1 == sRet)
{
iconv_close(icd);
return -1;
}
out_buf[outLen - out_left] = 0;
iconv_close(icd);
return (int)(outLen - out_left);
}
static int charset_convert_UTF8_TO_GB2312(char *in_buf, size_t in_left, char *out_buf, size_t out_left)
{
return charset_convert("UTF-8", "GB2312", in_buf, in_left, out_buf, out_left);
}
在主程序中修改如下
bufSize = strlen(argv[1]);
buffer_gb2312 = (unsigned char *)malloc(sizeof(unsigned char) * bufSize);
ret = charset_convert_UTF8_TO_GB2312(argv[1], (size_t)bufSize, buffer_gb2312, (size_t)bufSize);
if (-1 == ret)
{
printf("failed convert UTF-8 to GB2312\n");
return -1;
}
bufSize = SYN_FrameInfo(0, buffer_gb2312, buffer);
UART_SendData(fd, buffer, bufSize);
交叉编译成功,测试后可以语音正常识别。
完整的源码放在github上,有需要可以自行下载。 名称为190531
https://github.com/ljy980330/opencv_face_sys
有任何问题可以在下面给我留言!大家一起学习!