/*
利用宏晶单片机IO口p1.5实现模拟串口TXD引脚发送数据
本程序利用宏晶STC11F系列     晶振12M  Timer1做波特率发生器


*/
#include <string.h>
#include "..\Main\STC_NEW_8051.H"

#define TIMER1_ENABLE  TL1=TH1; TR1=1;
#define TIMER1_DISABLE TR1=0;

/*******************************************************************************************/
//#define F_TM  F0
/*******************************************************************************************/

/*******************************************************************************************/
unsigned char bdata sta;
sbit	BIT	=sta^0;
#define F_TM  BIT
/*******************************************************************************************/
sbit TXD_DATA = P1^5; //模拟串口TXD引脚



void Port_Init(void)
{
	//P0口配置成 准双向口  I/O 口模式
	//设置为标准的数据I/O
	P0M0 = 0x00;										
	P0M1 = 0x00;
	//P1口配置成 (SCL)P1.0 (SDA)P1.1 准双向口  I/O 口模式
	//MISO端口P1.4设置为输入
	//SCK,MOSI端口P1.5\P1.6设置为推挽输出
	//CS端口P1.7设置为准双向I/O口
	//RXD2(P1.2)\TXD2(P1.3)设置为准双向I/O口 
	P1M0 = 0x00;
	P1M1 = 0x00;
	P1ASF = 0x00;
	//P2口配置成 准双向口  I/O 口模式
	//设置为标准的数据I/O
	P2M0 = 0x00;
	P2M1 = 0x00;
	//RXD1(P3.0)\TXD1(P3.1)设置为准双向I/O口 
	//TEN485\WDI\CD4099_D\SERRIAL_D\ENPRINT\ENTX设置为准双向I/O口 
	P3M0 = 0x00;
	P3M1 = 0x00;
	
	P4M0 = 0x00;
	P4M1 = 0x00;
	//配置NA/P4.4 EX_LVD/P4.6为I/O口
	//配置ALE/P4.5 为ALE信号
	P4SW = 0x10;
	//AUXR1 = 0x2a
	//bit6:PCA_P4 = 0,缺省PCA在P1口
	//PCA_P4 = 1,PCA/PWM从P1口切换到P4口
	//ECI从P1.2切换到P4.1口
	//PCA0/PWM0从P1.3切换到P4.2口
	//PCA1/PWM1从P1.4切换到P4.3口
	//bit5:SPI_P4 = 0,缺省SPI在P1口
	//SPI_P4 = 1,SPI从P1口切换到P4口
	//SPICLK从P1.7切换到P4.3口
	//MISO从P1.6切换到P4.2口
	//MOSI从P1.5切换到P4.1口
	//SS从P1.4切换到P4.0口
	//bit4:S2_P4 = 0,缺省UART2在P1口
	//S2_P4 = 1,UART2从P1口切换到P4口
	//TXD2从P1.3切换到P4.3口
	//RXD2从P1.2切换到P4.2口
	//bit3:GF2 通用标志位
	//bit2:ADRJ = 0 10位A/D转换结果的高8位放在ADC_RES寄存器,
	//低2位放在ADC_RESL寄存器
	//ADRJ = 1 10位A/D转换结果的高2位放在ADC_RES寄存器,
	//低8位放在ADC_RESL寄存器
	//bit0: DPS = 0 使用缺省数据指针DPTR0
	//DPS = 1 使用另一个数据指针DPTR1
//	AUXR1 = 0x80;	  //串口在P1口
	AUXR1 = 0x00;	  //串口在P3口
	//WAKE_CLKO = 0x8F
	//bit7:PCAWAKEUP 允许PCA上升沿/下降沿中断 唤醒POWERDOWN
	//bit6:RXD_PIN_IE 允许P3.0(RXD)下降沿置RI,也能使RXD唤醒POWERDOWN
	//bit5:T1_PIN_IE 允许T1/P3.5脚下降沿置T1中断标志,也能使T1唤醒POWERDOWN
	//bit4:T0_PIN_IE 允许T0/P3.4脚下降沿置T0中断标志,也能使T0唤醒POWERDOWN
	//bib3:LVD_WAKE = 1,允许在掉电模式下,LVD/P4.6低压检测中断唤醒CPU(STC12C5A60S2系列)
	//bit2:BRTCLKO = 1 ,允许P1.0脚输出时钟,输出时钟频率 = 1/2 BRT 益出率
	//BRT工作在1T模式时的输出频率CLKOUT2 = (Fosc/2)/(256 - BRT)
	//BRT工作在12T模式时的输出频率CLKOUT2 = (Fosc/2)/12/(256 - BRT)
	//BRTCLKO = 0 ,不允许BRT在1.0脚输出时钟
	//bit1:T1CLKO = 1 ,允许T1脚输出T1(P3.5)益出脉冲,输出时钟频率 = 1/2 BRT 益出率
	//BRT工作在1T模式时的输出频率CLKOUT1 = (Fosc/2)/(256 - BRT)
	//BRT工作在12T模式时的输出频率CLKOUT1 = (Fosc/2)/12/(256 - BRT)
	//BRTCLKO = 0 ,不允许T1脚输出T1(P3.5)益出脉冲
	//bit0:T0CLKO = 1 ,允许T0脚输出T0(P3.5)益出脉冲,输出时钟频率 = 1/2 BRT 益出率
	//BRT工作在1T模式时的输出频率CLKOUT0 = (Fosc/2)/(256 - BRT)
	//BRT工作在12T模式时的输出频率CLKOUT0 = (Fosc/2)/12/(256 - BRT)
	//BRTCLKO = 0 ,不允许T0脚输出T0(P3.5)益出脉冲
	WAKE_CLKO = WAKE_CLKO & 0xf8;
}

//T1初始化
void Timer1_Init()
{
	TMOD &= 0x0F;
	TMOD |= 0x20;//用T1做定时器,工作在方式2
	//AUXR Bit  7     6     5           4     3      2    	  1  	  0
	//		  T0x12  T1x12  UART_M0x6  BRTR  S2SMOD  BRTx12  EXTRAM  S1BRS
	//T0x12 	= 0:定时器0是传统8051速度,12分频
	//			= 1:定时器0是传统8051速度,1分频
	//T1x12		= 0:定时器1是传统8051速度,12分频
	//			= 1:定时器0是传统8051速度,1分频
	//UART_M0x6  = 0:UART串口的模式0是传统12T的8051速度,12分频
	//			 = 1:UART串口的模式0是传统12T的8051速度6倍,2分频
	//BRTR(S2TR) = 0:不允许独立波特率发生器运行
	//			 = 1:允许独立波特率发生器运行
	//S2SMOD	 = 0:缺省      = 1:串口2 /UART2的波特率 *2
	//BRTx12(S2Tx12)	= 0:独立波特率发生器每12个时钟计数一次
	//					= 1:独立波特率发生器每1个时钟计数一次
	//EXTRAM	= 0:允许使用内部扩展的1024字节扩展RAM
	//			= 1:禁止使用内部扩展的1024字节扩展RAM
	//S1BRS		= 0:缺省,串口1波特率发生器选择定时器1,S1BRS是串口波特率发生器选择位
	//			= 1:独立波特率发生器作为串口1的拨特率发生器,此时定时器1得到释放,可以作为独立定时器使用
	AUXR &= 0xbF;//定时器1工作在12T模式下
	PCON=00;
	TR1=0; //在发送或接收才开始使用
	TF1=0;
	TH1=(256-104); 	//9600bps 就是 1000000/9600=104.167微秒 
			//执行的timer是104.167*12/12= 104
	TL1=TH1;	
	ET1=1;
	EA=1;
}


//发送一个字符
void Trans_Data(unsigned char inch)
{
	unsigned char ii;
	ii=0;
	F_TM=0;
	TXD_DATA=0; //start bit
	TIMER1_ENABLE; //启动TIMER1
	while(!F_TM);
	while(ii<8)
	{
		if(inch&1)
		{
			TXD_DATA = 1; 
		}
		else
		{
			TXD_DATA = 0;
		}
		F_TM=0;
		while(!F_TM);
		ii++;
		inch>>=1;
	}
	TXD_DATA=1;//stoop bit
	F_TM=0;
	while(!F_TM);
	TIMER1_DISABLE; //停止TIMER1
}

/*******************************************************************************************/
//Delay 100us
/*******************************************************************************************/
void Delay(unsigned int ns)  //12M晶振 ns=1延时42毫秒  ns=10延时428毫秒 ns=15延时640毫秒
{	
	unsigned int k;  
	while(ns--)      
	 { 
	     k = 30000;
		while(--k);
	 }
}
void main(void)
{ 


/****************需要发送的文本**********************************/ 
	code char  text[] =  {"[V5]欢迎使用深圳市海洋电子有限公司研制推出的OE6388语音合成模块。本演示程序采用单片机IO口模拟串口控制语音合成模块发音。[V1]这是音量最小的效果。[V10]这是音量最大的效果。[V5] [t0]这是语调最低的效果 [t10]这是语调最高的效果[t5] [m3]我是晓玲；[m51]我是尹小坚；[m52]我是易小强；[m53]我是田蓓蓓；[m54]我是唐老鸭；[m55]我是小燕子；[m3]"};
	unsigned  char  headOfFrame[5];
	unsigned  int  length;  
	unsigned  char  ecc  = 0;  			//定义校验字节
	unsigned  int i=0; 
	length =strlen(text); 			//需要发送文本的长度
	length+=2;
 

/*****************发送过程**************************************/           
	headOfFrame[0] = 0xFD ; 			//构造帧头FD
	headOfFrame[1] = length>>8 ; 			//构造数据区长度的高字节
	headOfFrame[2] = length&0xff; 		//构造数据区长度的低字节
	headOfFrame[3] = 0x01 ; 			//构造命令字：合成播放命令 
	headOfFrame[4] = 0x00 ; 			//构造命令参数：编码格式为GB2312
	Delay(16);//最小要延时640毫秒等待SYN6388上电复位完成	
	Port_Init(); //IO口配置
	Timer1_Init();//Timer1初始化 / 作为串口的波特率发生器


  
	for(i = 0; i<5; i++)   				//依次发送构造好的5个帧头字节
	{  
		//ecc=ecc^(headOfFrame[i]);		//对发送的字节进行异或校验	
		Trans_Data(headOfFrame[i]); 
	}

	for(i= 0; i<length; i++)	//依次发送待合成的文本数据
	{  
		//ecc=ecc^(text[i]); 	//对发送的字节进行异或校验	
		Trans_Data(text[i]); 
	}
		//Trans_Data(ecc);			//最后发送校验字节
	while(1);		
}

void IntTimer1() interrupt 3
{
   F_TM=1;
}
