原创 ATMEGA128L-直接朗读文本朗诵诗歌的语音合成芯片驱动

2009-6-26 18:51 4105 7 7 分类: MCU/ 嵌入式

/***********************************************************/
//Title:ATMEGA128L-直接朗读文本的语音合成芯片驱动-串口发送查询接收中断方式
//ICC-AVR : 2009-5-24 12:25:40
// Target : M128
// Crystal: 8.0000Mhz
//Author  :borlittle
//QQ:634172943
//Function:OSYNO6188 VOICE CHIP BEIJING driver
//备注   :本程序经调试好使,北京益世通利智能通讯技术有限公司
//OSYNO6188语音合成芯片驱动,不过串口如果查询接收不到数据可能造成死机
/***********************************************************/
#include <iom128v.h>
#include <macros.h>


#define uchar unsigned char      //定义无符号字符为 uchar
#define uint  unsigned int       //定义无符号整型
#define Crystal 8000000          //晶振8MHZ
#define Baud 1200                //波特率
#define prog_fj_datalength 26   


#define lj_datalength 6             //定义汉字语音数据内容字个数
#define prog_lj_datalength lj_datalength<<1  //定义汉字语音数据内容实际内存中个数


#define sj_datalength 7            //定义汉字语音数据内容字个数
#define prog_sj_datalength sj_datalength<<1  //定义汉字语音数据内容实际内存中个数


#define ks_datalength 4           //定义汉字语音数据内容字个数
#define prog_ks_datalength ks_datalength<<1  //定义汉字语音数据内容实际内存中个数


#define sd_datalength 5           //定义汉字语音数据内容字个数
#define prog_sd_datalength sd_datalength<<1  //定义汉字语音数据内容实际内存中个数
#define start_play  4
float V;
uint v1,v2,v3;
uchar erro_counter;          //错误重发次数计数器
uchar play_voice_signal;     //语音播放各函数重发标志
uchar music_count=0xB7;
uchar data_temp;            //串口接收数据缓冲
uchar usart0_data_counter=0;//串口接收中断计数


//正式应用
 uchar end[]={0x04};//结束字节
 uchar data0[2]={0x00,0x00};
 uchar set[]={0x01,0x80,0x84,0xC5,0x04};//帧数据设置
//发送起始字,不用中断,保持原来设置输出,波特率保持原来,正常工作不休眠
//不回传歌词,播放一遍,第一个字按姓处理,文本不朗读标点符号,‘1’不读为“幺1”
//反馈全部播音结束的回应,不要背景,音量6级 


 uchar music_data[2]={0x60,0xB0};
 uchar out_data[]={0x01,0x90,0x80,0x80,0x04,0x95};//改成DA 输出
 //改成PWM 输出: 0x01,0xa0,0x80,0x80,0x04,0xa5(其中0xa5为本数据帧校验字)
 //改成DA 输出: 0x01,0x90,0x80,0x80,0x04,0x95(其中0x95为本数据帧校验字)
 uchar usart0_data_receive[3]={0x0f,0x0f,0x0f};//接收串口数据
 //提示音数据
 uchar lj_data[]={"请输入轮径值"};
 uchar sj_data[]={"请输入测试时间"};
 uchar ks_data[]={"测试开始"};
 uchar sd_data[]={"千米每小时"};
 uchar fj_data[]={0xA3,0xB0,0xA3,0xB1,0xA3,0xB2,0xA3,0xB3,0xA3,0xB4,0xA3,0xB5,0xA3,0xB6,0xA3,0xB7,0xA3,0xB8,0xA3,0xB9,0xCA,0xAE,0xB0,0xD9,0xC7,0xA7};
//0,1,2,3,4,5,6,7,8,9,十,百,千


//函数声明
void port_init(void);
void usart0_init(void);
void init_devices(void);
void usart0_char_send(uchar i);
void usart0_str_send(char *s);
uchar usart0_char_receive(void);
void usart0_receive_data(void);
uchar usart0_char_receive(void);
void delay_1ms(void);
void delay_nms(uint n);
uchar checkbyte(uchar *t,uchar length);
void delay_1us(void);
void delay_nus(uint n);
void number_voice(uchar number);
void speed_unit(void);
void read_speed(void);
void test_start_voice(void);
void wheel_voice(void);
void play_music(void);
void test_time_voice(void);
void delay_nthms(uint n);
void conv(uint M);
void resend(void);
void out_change(void);
/******************延时1us**************************/
void delay_1us(void)
{asm("nop");
}
/************将变量i分解成待显示数并存入数组***********/
void conv(uint M)   
{
v1=M/100;
delay_nus(3);
v2=(M/10)%10;
delay_nus(3);
v3=M%10;
}
/********************延时n us*************************/
void delay_nus(uint n)
{
   uint i="0";
  for (i=0;i<n;i++)
       delay_1us();
}
/*****************延时1毫秒子函数*******************/
void delay_1ms(void)
{
 uint i;
for(i=1;i<(8*143-2);i++) //8为晶振频率
;
}
/****************延时N毫秒子函数****************/
void delay_nms(uint n)
{
uint i;
for(i=0;i<n;i++)
delay_1ms();
}
/****************延时1秒子函数****************/
void delay_nthms(uint n)
{
uint i,j=1000*n;
for(i=0;i<j;i++)
delay_1ms();
}
/******************端口初始化*******************************/
void port_init(void)
{
 PORTE = 0xFF;   //设置RXD0和TXD0
 DDRE  = 0x02;
 
 PORTB = 0x10;   //设置PB4为上拉输入
 DDRB  = 0xEF;
 
 PORTD = 0X00;  //D口用于输出指示回应帧数据
 DDRD  = 0xFF;  //初始为低电平
}
/*****************串口0初始化*********************************/
void usart0_init(void)
{
 UCSR0B = 0x00;                     //禁止发送和接收
 UCSR0A = 0x02;                     //倍速异步模式USX0=1
 UCSR0C = 0x06;                     //0000 0110,UCSZ01=1,UCSZ00=1;8位字符,1位停止位
 UBRR0L=(Crystal/8/(Baud+1))%256;   //若为正常异步模式USX0=0则位(Crystal/16/(Baud+1))%256
 UBRR0H=(Crystal/8/(Baud+1))/256;   //参见ATMEGA128使用手册
 UCSR0B=0x98;        //允许发送和接收,接收结束中断使能
}
/******************初始化器件**************************************/
void init_devices(void)
{
 port_init();
 usart0_init();
 }
//****************发送一个字符******************************
void usart0_char_send(uchar i)
{
while(!(UCSR0A&(1<<UDRE0)));
UDR0=i;
}
/******************发送一个字符串*************************/
void usart0_str_send(char *s)
{
 while(*s)
 {
 usart0_char_send(*s);
 s++;
 }
}
/*********************发送一个数组**********************/
void usart0_str_sendArray(uchar *q,uchar len)
{
  uchar i;
  for(i=0;i<len;i++)  //控制字符个数
  {
    usart0_char_send(*q);
    q++;
  }
}


/*******************校验发送错误重发****************************/
//如果缺少重发则可能造成实际工作不稳定,有时能读有时不读的现象
void resend(void)
{
 erro_counter=0;
 erro_counter++;
if((usart0_data_receive[1]==0x10)&(erro_counter<4))
{
PORTD|=0X01;                         //指示发错
switch(play_voice_signal)
{
case 0: out_change();break;
case 1: test_start_voice();PORTD |=0X02;break;//重发,并指示
case 2: wheel_voice();PORTD |=0X02;break;
case 3: test_time_voice();PORTD |=0X02;break;
//case 4: number_voice();PORTD |=0X02;break;
case 5: read_speed();PORTD |=0X02;break;
case 6: play_music();PORTD |=0X02;break;
case 7: speed_unit();PORTD |=0X02;break;
default:delay_nms(1);PORTD |=0X02;break;
}


}
if(usart0_data_receive[1]==0x11)  //接收成功
PORTD|=0X04;
if(usart0_data_receive[1]==0x12)  //播放完成
PORTD|=0X08;
}
/****************中断接收服务处理子程序*******************************/
#pragma interrupt_handler usart0_RX_interrupt:iv_USART0_RX  //  19
void usart0_RX_interrupt(void)
{
  data_temp = UDR0;                    //从数据缓冲器中接收数据
 usart0_data_receive[usart0_data_counter]=data_temp;
 usart0_data_counter++;
 if(usart0_data_counter==3)           //如果已接收到的字符个数为3
    {
 resend();
 usart0_data_counter = 0;             //计数复位
 }
 
}  
/**********************计算异或校验字节*****************/
uchar checkbyte(uchar *t,uchar length)
{
   uchar i,checkword1;
   checkword1=*t;
   t++;
  for(i=1;i<length;i++)  //控制字符个数
  {
    checkword1=checkword1^(*t);
    t++;
  }
  return(checkword1);
}
/*****************播放方式输出(单独数据帧)改变指令*******************************/
void out_change(void)
{
play_voice_signal=0; 
usart0_str_sendArray(out_data,6);
}
/*****************测试开始提示发音*******************************/
void test_start_voice(void)
{
uchar checkword_set,checkword_ks_data,checkword;
play_voice_signal=1;
checkword_ks_data=checkbyte(ks_data,prog_ks_datalength);
checkword_set=checkbyte(set,5);
checkword=checkword_set^checkword_ks_data;


usart0_str_sendArray(set,4);
usart0_str_sendArray(ks_data,prog_ks_datalength);
usart0_str_sendArray(end,1);
usart0_char_send(checkword);
}
/*****************输入轮径值提示发音*******************************/
void wheel_voice(void)
{
 
uchar checkword_set,checkword_lj_data,checkword;
play_voice_signal=2;
checkword_lj_data=checkbyte(lj_data,prog_lj_datalength);
checkword_set=checkbyte(set,5);
checkword=checkword_set^checkword_lj_data;


usart0_str_sendArray(set,4);
usart0_str_sendArray(lj_data,prog_lj_datalength);
usart0_str_sendArray(end,1);
usart0_char_send(checkword);
}
/*****************输入测试时间提示发音*******************************/
void test_time_voice(void)
{
uchar checkword_set,checkword_sj_data,checkword;
play_voice_signal=3;
checkword_sj_data=checkbyte(sj_data,prog_sj_datalength);
checkword_set=checkbyte(set,5);
checkword=checkword_set^checkword_sj_data;


usart0_str_sendArray(set,4);
usart0_str_sendArray(sj_data,prog_sj_datalength);
usart0_str_sendArray(end,1);
usart0_char_send(checkword);
}
/*****************单数字按键发音*******************************/
void number_voice(uchar number)
{
 uchar number_data[2];
 uchar checkword_set,checkword_number,checkword,seek_number;
 play_voice_signal=4;
 seek_number=number<<1;
 number_data[0]=fj_data[seek_number];
 number_data[1]=fj_data[seek_number+1];
 checkword_set=checkbyte(set,5);
 checkword_number=checkbyte(number_data,2);
 checkword=checkword_number^checkword_set;
 usart0_str_sendArray(set,4);
 usart0_str_sendArray(number_data,2);
 usart0_str_sendArray(end,1);
 usart0_char_send(checkword);
}


/*****************播放音乐*******************************/
void play_music(void)
{
uchar checkword_set,checkword_music_data,checkword;
play_voice_signal=6;
checkword_music_data=checkbyte(music_data,2);
checkword_set=checkbyte(set,5);
checkword=checkword_set^checkword_music_data;


usart0_str_sendArray(set,4);
usart0_str_sendArray(music_data,2);
usart0_str_sendArray(end,1);
usart0_char_send(checkword);
}
/*****************播报速度语音*******************************/
void read_speed(void)
{
uchar checkword_set,checkword,seek_number,number;//定义校验数据变量
uchar checkword_consd1_data,checkword_consd2_data,checkword_consd3_data;
uchar checkword_shi_data,checkword_bai_data;
uchar con_data[3];
uchar bai_data[2],shi_data[2];//定义字库语音码变量
uchar v1_data[2],v2_data[2],v3_data[2];
play_voice_signal=5;
conv(V);//转换速度值
con_data[0]=v1;con_data[1]=v2;con_data[2]=v3;//获取转换后的值


//将每个值对应查出其字库语音码
number=con_data[0];
seek_number=number<<1;
v1_data[0]=fj_data[seek_number];
v1_data[1]=fj_data[seek_number+1];
number=con_data[1];
seek_number=number<<1;
v2_data[0]=fj_data[seek_number];
v2_data[1]=fj_data[seek_number+1];
number=con_data[2];
seek_number=number<<1;
v3_data[0]=fj_data[seek_number];
v3_data[1]=fj_data[seek_number+1];


number=10;
seek_number=number<<1;
shi_data[0]=fj_data[seek_number];
shi_data[1]=fj_data[seek_number+1];
bai_data[0]=fj_data[seek_number+2];
bai_data[1]=fj_data[seek_number+3];



 checkword_set=checkbyte(set,5);
 checkword_shi_data=checkbyte(shi_data,2);
 checkword_bai_data=checkbyte(bai_data,2);
 
if(con_data[0]!=0) //百位不为0,朗读从百位开始
{
if(con_data[2]==0)//个位为0
{


if(con_data[1]==0)//十位个位都为0
{
 checkword_consd1_data=checkbyte(v1_data,2);
 checkword=checkword_consd1_data^checkword_set;
 checkword=checkword_bai_data^checkword;
 
 usart0_str_sendArray(set,4);
 usart0_str_sendArray(v1_data,2);
 usart0_str_sendArray(bai_data,2);
 usart0_str_sendArray(end,1);
 usart0_char_send(checkword);



}
else{  //只有个位为0
 checkword_consd1_data=checkbyte(v1_data,2);
 checkword_consd2_data=checkbyte(v2_data,2);
 checkword=checkword_consd1_data^checkword_set;
 checkword=checkword_consd2_data^checkword;
 checkword=checkword_shi_data^checkword;
 checkword=checkword_bai_data^checkword;
 
 usart0_str_sendArray(set,4);
 usart0_str_sendArray(v1_data,2);
 usart0_str_sendArray(bai_data,2);
 usart0_str_sendArray(v2_data,2);
 usart0_str_sendArray(shi_data,2);


 
 usart0_str_sendArray(end,1);
 usart0_char_send(checkword);
}
}
else if((con_data[1]==0)&(con_data[2]!=0)) //只有十位为0
 {
 checkword_consd1_data=checkbyte(v1_data,2);
 checkword_consd2_data=checkbyte(v2_data,2);
 checkword_consd3_data=checkbyte(v3_data,2);
 checkword=checkword_consd1_data^checkword_set;
 checkword=checkword_consd2_data^checkword;
 checkword=checkword_consd3_data^checkword;
 checkword=checkword_bai_data^checkword;
 
 usart0_str_sendArray(set,4);
 usart0_str_sendArray(v1_data,2);
 usart0_str_sendArray(bai_data,2);
  usart0_str_sendArray(v2_data,2);
 usart0_str_sendArray(v3_data,2);
 usart0_str_sendArray(end,1);
 usart0_char_send(checkword);
 }
else//个位、十位全不为0
{
 checkword_consd1_data=checkbyte(v1_data,2);
 checkword_consd2_data=checkbyte(v2_data,2);
 checkword_consd3_data=checkbyte(v3_data,2);
 checkword=checkword_consd1_data^checkword_set;
 checkword=checkword_consd2_data^checkword;
 checkword=checkword_consd3_data^checkword;
 checkword=checkword_shi_data^checkword;
 checkword=checkword_bai_data^checkword;
 
 usart0_str_sendArray(set,4);
 usart0_str_sendArray(v1_data,2);
 usart0_str_sendArray(bai_data,2);
 usart0_str_sendArray(v2_data,2);
 usart0_str_sendArray(shi_data,2);
 usart0_str_sendArray(v3_data,2);
 usart0_str_sendArray(end,1);
 usart0_char_send(checkword);
}
}


else  //百位为0
{
if(con_data[1]==0)//十位为0,只朗读个位
{
 checkword_consd3_data=checkbyte(v3_data,2);
 checkword=checkword_consd3_data^checkword_set;
 
 
 usart0_str_sendArray(set,4);
 usart0_str_sendArray(v3_data,2);


 usart0_str_sendArray(end,1);
 usart0_char_send(checkword);
}
else if (con_data[2]==0)//只朗读十位,不朗读个位
{
checkword_consd2_data=checkbyte(v2_data,2);
 checkword=checkword_consd2_data^checkword_set;
 checkword=checkword_shi_data^checkword;
 
 usart0_str_sendArray(set,4);
 usart0_str_sendArray(v2_data,2);
  usart0_str_sendArray(shi_data,2);
 usart0_str_sendArray(end,1);
 usart0_char_send(checkword);
}
else //朗读十位和个位
{
 checkword_consd2_data=checkbyte(v2_data,2);
 checkword_consd3_data=checkbyte(v3_data,2);
 checkword=checkword_consd2_data^checkword_set;
 checkword=checkword_consd3_data^checkword;
 checkword=checkword_shi_data^checkword;
 
 usart0_str_sendArray(set,4);
 usart0_str_sendArray(v2_data,2);
 usart0_str_sendArray(shi_data,2);
 usart0_str_sendArray(v3_data,2);
 usart0_str_sendArray(end,1);
 usart0_char_send(checkword);
}
}


}
/*****************播放速度单位*******************************/
void speed_unit(void)
{
uchar checkword_set,checkword_sd_data,checkword;
play_voice_signal=7;
checkword_sd_data=checkbyte(sd_data,prog_sd_datalength);
checkword_set=checkbyte(set,5);
checkword=checkword_set^checkword_sd_data;


usart0_str_sendArray(set,4);
usart0_str_sendArray(sd_data,prog_sd_datalength);
usart0_str_sendArray(end,1);
usart0_char_send(checkword);
}


/***************主函数*****************************/
void main(void)
{
uchar i;
CLI();        //总中断禁止  
init_devices();  //初始化
SEI();
out_change();
delay_nms(800);//发送完改波特率或改输出方式的系统包后,要暂停几百毫秒,再改主机的波特率
delay_nms(800);
while(1)
{
if((PINB&0x10)!=0x10) //通过按键测试其连播性能,PB4被拉低?
{
V=114;
read_speed();


}
}
}
 

文章评论0条评论)

登录后参与讨论
我要评论
0
7
关闭 站长推荐上一条 /2 下一条