(十)linux下使用串口控制语音模块

平台: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

 

有任何问题可以在下面给我留言!大家一起学习!

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值