"); //-->
//***************************FileName:Project.c**********************//
//***************************ICC****R6.30编译**************************//
#i nclude <io8535v.h> //AT90S8535寄存器定义;
#i nclude <macros.h> //AT90S8535宏定义;
#i nclude "zimo.h" //点阵LED字模
#define uchar unsigned char //数据类型定义
#define uint unsigned int //数据类型定义
uchar Key_Value; //按键键值;
uchar State_Flag; //站点标志;
uchar Ack_Flag; //确认标志;
uchar Pre_Flag; //预报标志;
uchar Move_Flag; //滚动标志;
uchar Spec_Flag; //特殊信息标志;
uchar EOM_Flag=1; //信息结束标志;
uchar Pst_Flag; //上、下行标志;
uchar State=1; //站数;
uchar Spec; //特殊信息数;
uchar Speed=20; //文字滚动速度;
uchar Word_Number; //显示字数;
//语音芯片第1~16段分别保存16站的站名信息
//第17段保存报站信息“到了,请要下车的乘客依次从后门下车”
//第18、19段分别保存预报信息“前方到站”、“请要下车的乘客做好下车准备”
//第20段保存欢迎信息及公交车线路说明
//第21、22段保存特殊提示信息
uchar Snd_Info[]={0,17}; //报站声音信息
uchar Snd_Pre_Info[]={18,0,19}; //预报声音信息
uchar Snd_Spec[]={21,22}; //特殊声音信息
uchar Snd_Welc=20; //欢迎声音信息
//本例公交车语音报站系统包含16站
//所有的站名都以“第n站”代替,其中n为当前站数,n<16
//报站时显示屏滚动显示“第n站到了”
//预报站时显示屏显示“前方到站第n站”
//其中“第n站”字模存放在二维数组State n[3][32]中
//“到了”字模存放在二维数组DL[2][32]中
//“前方到站”字模存放在二维数组QFDZ[4][32]中
uchar text[32]; //当前显示文字
uchar next[32]; //下一个显示文字
#pragma interrupt_handler Key_Scan:2 //定义按键中断INT0的中断服务程序
#pragma interrupt_handler Receive_EOM:3//定义语音中断INT1的中断服务程序
//****************************延时程序*******************************//
void delay(int t)
{while(t--) ;}
//****************************语音芯片驱动程序***********************//
void Set_CE(uchar level) //定义ISD2560使能线为PA^4
{if(level==1) PORTA |=0x10;
else PORTA &=0xef;
}
void Set_PD(uchar level) //定义ISD2560的PD线为PA^3
{if(level) PORTA |=0x08;
else PORTA &=0xf7;
}
void Set_PR(uchar level) //定义ISD2560的PR线为PA^2
{if(level) PORTA |=0x04;
else PORTA &=0xfb;
}
void Set_A6(uchar level) //定义ISD2560的A6/8/9线为PA^1
{if(level) PORTA |=0x02;
else PORTA &=0xfd;
}
void Set_A0(uchar level) //定义ISD2560的A6/8/9线为PA^1
{if(level) PORTA |=0x01;
else PORTA &=0xfe;
}
//****************************语音搜索和播放程序****************************//
void Seek_Segment(uchar s) //语音搜索程序
{Set_PD(1); //语音芯片复位
delay(20000);
Set_PD(0);
Set_PR(1); //放音模式
Set_A0(1); //M0模式
while(s--) //快进s段
{Set_CE(0);
Set_CE(1);
do NOP();
while(EOM_Flag); //检测EOM标志位,为0时有效
EOM_Flag=1;}
Set_A0(0); //M6模式
}
void Play(void) //语音播放程序
{Set_CE(0); //CE线低电平触发芯片的放音操作
Set_CE(1);
do NOP();
while(EOM_Flag); //检测EOM标志位,为0时有效
EOM_Flag=1; //重新赋EOM标志位为1
}
//****************************语音报站程序****************************//
void Inform(uchar m) //报站
{uchar i;
if(Pst_Flag) Snd_Info[0]=m; //若为上行方向,顺序报站
else Snd_Info[0]=17-m; //若为下行方向,逆序报站
Set_PD(1); //语音芯片复位
delay(20000);
Set_PD(0);
for(i=0;i<2;i++)
{Seek_Segment(Snd_Info[i]); //搜索相应语音信息段
Play();} //播放
}
void Pre_Inform(uchar m) //报站
{uchar i;
if(Pst_Flag) Snd_Pre_Info[1]=m; //若为上行方向,顺序预报站
else Snd_Pre_Info[1]=17-m; //逆序预报站
Set_PD(1); //语音芯片复位
delay(20000);
Set_PD(0);
for(i=0;i<3;i++)
{Seek_Segment(Snd_Pre_Info[i]); //搜索相应语音信息段
Play();} //播放
}
void Special(uchar m) //播放特殊信息
{Set_PD(1); //语音芯片复位
delay(20000);
Set_PD(0);
Seek_Segment(Snd_Spec[m]); //搜索相应语音信息段
Play(); //播放
}
void Welcome() //欢迎信息
{Set_PD(1); //语音芯片复位
delay(20000);
Set_PD(0);
Seek_Segment(Snd_Welc); //搜索相应语音信息段
Play(); //播放
}
公交语音提示(2)
//****************************I2C驱动程序****************************//
void Set_SCL(uchar i) //定义MAX6959时钟线为PA^7
{if(i) PORTA |=0x80;
else PORTA &=0x7f;
}
void Set_SDA(uchar i) //定义MAX6959数据线为PA^6
{if(i) PORTA |=0x40;
else PORTA &=0xbf;
}
void Start() //I2C总线的开始条件
{Set_SDA(1); //SDA=1;
Set_SCL(1); //SCL=1;
delay(100); //等待时钟信号变高
Set_SDA(0); //SDA=0;
delay(100);
Set_SCL(0); // SCL=0;
}
void Stop() //I2C总线结束条件
{Set_SDA(0); //SDA=0;
delay(100);
Set_SCL(1); //SCL=1;
delay(100); //等待时钟信号变低
Set_SDA(1); //SDA=1;
delay(100);
Set_SCL(0); //SCL=0;
}
void Ack() //I2C总线应答
{Set_SDA(0); //SDA=0;
delay(50);
Set_SCL(1); //SCL=1;
delay(100);
Set_SCL(0); //SCL=0;
delay(50);
Set_SDA(1); //SDA=1;
}
void Nack() //I2C总线应答非
{Set_SDA(1); //SDA=1;
delay(50);
Set_SCL(1); //SCL=1;
delay(100);
Set_SCL(0); //SCL=0;
delay(50);
Set_SDA(0); //SDA=0;
}
void Check_Ack() //I2C总线应答检查
{Set_SDA(1); //SDA=1;
Set_SCL(1); //SCL=1;
Ack_Flag=0; //清除应答标志;
DDRA&=0xbf; //设置SDA为输入
if(!((PINA & 0x40)>>6))
{delay(50);
Set_SCL(0); //SCL=0;
delay(100);}
else
{Ack_Flag=1; //收到应答;
delay(50);
Set_SCL(0); //SCL=0;
delay(100);}
DDRA |=0xff; //重新设置SDA为输出
}
void Write_Bit0() //写1bit数据:0
{Set_SDA(0); //SDA=0;
Set_SCL(1); //SCL=1;
delay(100);
Set_SCL(0); //SCL=0;
}
void Write_Bit1() //写1bit数据:1
{Set_SDA(1); //SDA=1;
Set_SCL(1); //SCL=1;
delay(100);
Set_SCL(0); //SCL=0;
Set_SDA(0); //SDA=0;
}
void Write_Byte(uchar Data) //写一字节数据Data
{uchar i;
for(i=0;i<8;i++)
{if(Data & 0x80) Write_Bit1(); //传输位从高位到低位,先传最高位
else Write_Bit0();
Data <<=1;} //数据左移
}
uchar Read_Byte() //读一字节数据:返回值即读的数据
{uchar Read_Data=0xff; // Read_Data为读入的数据,初始值为0xff
uchar j;
for (j=0;j<8;j++)
{Set_SDA(1);
Set_SCL(1);
DDRA &=0xbf;
if((PINA & 0x40)==0)
{Read_Data <<=1;
Read_Data=(Read_Data & 0xfe);
Set_SCL(0);}
else
{Read_Data <<=1;
Read_Data =( Read_Data | 0x01);
Set_SCL(0);}}
DDRA |=0x40;
return(Read_Data);
}
//***************************写一字节数据****************************//
//向从地址为Slave的IIC器件的Address地址写一字节数据Data
void Write_1byte(uchar Slave,uchar Address,uchar Data)
{Start(); //开始
Write_Byte(Slave); //写I2C器件地址
do Check_Ack(); //检查应答位
while(Ack_Flag==1);
Write_Byte(Address); //送寄存器地址
do Check_Ack(); //检查应答位
while(Ack_Flag==1);
Write_Byte(Data); //写入一字节数据
do Check_Ack(); //检查应答位
while(Ack_Flag==1);
Stop(); //停止
}
//***************************写两字节数据****************************//
//向从地址为Slave的IIC器件的Address地址开始写两字节数据Data0,Data1
void Write_2byte(uchar Slave,uchar Address,uchar Data0,uchar Data1)
{Start(); //开始
Write_Byte(Slave); //写I2C器件地址
do Check_Ack(); //检查应答位
while(Ack_Flag==1);
Write_Byte(Address); //送寄存器地址
do Check_Ack(); //检查应答位
while(Ack_Flag==1);
Write_Byte(Data0);
do Check_Ack(); //检查应答位
while(Ack_Flag==1);
Write_Byte(Data1);
do Check_Ack(); //检查应答位
while(Ack_Flag==1);
Stop(); //停止信号
}
//***************************读一字节数据****************************//
//从从地址为Slave的IIC器件的Address地址处读一字节数据
uchar Read_1byte(uchar Slave,uchar Address)
{uchar data0,x;
do{
Start(); //开始信号
Write_Byte(Slave); //写I2C器件地址
Check_Ack(); //检查应答位
}while(Ack_Flag);
do{
Write_Byte(Address); //写寄存器地址
Check_Ack(); //检查应答位
}while(Ack_Flag);
do{
Start(); //开始
Write_Byte(Slave+1); //写I2C器件地址(+1表示为读操作)
Check_Ack(); //检查应答位
}while(Ack_Flag);
data0=Read_Byte(); //读1字节
Nack(); //读完发送一个Not Ack应答
Stop(); //停止
return data0; //返回读取数据
}
公交语音提示(3)
//***************************数字显示程序****************************//
void Led_Display(uchar Number)
{uchar d0,d1;
d0=Number/10; //取站数的个位
d1=Number%10; //取站数的十位
Write_2byte(0x70,0x20,d1,d0); //从显示位0开始连续显示两位
}
//***************************换下一个字显示**************************// *博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。
void change()
{unsigned char m;
if(!Pre_Flag) //报站情形
{switch(State) //判断站名
{case 1: //若为第1站
if(Word_Number<5) //判断已显示字数
{if(Word_Number<3) //若未显示完“第1站”,则
{for(m=0;m<32;m++) //依次换字显示“第1站”
next[m]=State1[Word_Number][m];}
else
for(m=0;m<32;m++) //依次换字显示“到了”
next[m]=DL[Word_Number-3][m];
Word_Number++;} //显示字数+1
else //若全部显示完,则
Word_Number=0; //显示字数清0
break;
case 2: //若为第2站
if(Word_Number<5) //判断已显示字数
{if(Word_Number<3) //若未显示完“第2站”,则
{for(m=0;m<32;m++) //依次换字显示“第2站”
next[m]=State2[Word_Number][m];}
else //否则
for(m=0;m<32;m++)
next[m]=DL[Word_Number-3][m]; //依次换字显示“到了”
Word_Number++;} //显示字数+1
else //若全部显示完,则
Word_Number=0; //显示字数清0
break;
case 3: //若为第3站
if(Word_Number<5) //判断已显示字数
{if(Word_Number<3) //若未显示完“第3站”,则
{for(m=0;m<32;m++)
next[m]=State1[Word_Number][m];} //依次换字显示“第3站”
else
for(m=0;m<32;m++)
next[m]=DL[Word_Number-3][m]; //依次换字显示“到了”
Word_Number++;} //显示字数+1
else //若全部显示完,则
Word_Number=0; //显示字数清0
break;
case 4: //若为第4站
if(Word_Number<5) //判断已显示字数
{if(Word_Number<3) //若未显示完“第4站”,则
{for(m=0;m<32;m++)
next[m]=State2[Word_Number][m];} //依次换字显示“第4站”
else //否则
for(m=0;m<32;m++)
next[m]=DL[Word_Number-3][m]; //依次换字显示“到了”
Word_Number++;} //显示字数+1
else //若全部显示完,则
Word_Number=0; //显示字数清0
break;
case 5: //若为第5站
if(Word_Number<5) //判断已显示字数
{if(Word_Number<3) //若未显示完“第5站”,则
{for(m=0;m<32;m++)
next[m]=State1[Word_Number][m];} //依次换字显示“第5站”
else //否则
for(m=0;m<32;m++)
next[m]=DL[Word_Number-3][m]; //依次换字显示“到了”
Word_Number++;} //显示字数+1
else //若全部显示完,则
Word_Number=0; //显示字数清0
break;
case 6: //若为第6站
if(Word_Number<5) //判断已显示字数
{if(Word_Number<3) //若未显示完“第6站”,则
{for(m=0;m<32;m++)
next[m]=State2[Word_Number][m];} //依次换字显示“第6站”
else //否则
for(m=0;m<32;m++)
next[m]=DL[Word_Number-3][m]; //依次换字显示“到了”
Word_Number++;} //显示字数+1
else //若全部显示完,则
Word_Number=0; //显示字数清0
break;
case 7: //若为第7站
if(Word_Number<5) //判断已显示字数
{if(Word_Number<3) //若未显示完“第7站”,则
{for(m=0;m<32;m++)
next[m]=State1[Word_Number][m];} //依次换字显示“第7站”
else //否则
for(m=0;m<32;m++)
next[m]=DL[Word_Number-3][m]; //依次换字显示“到了”
Word_Number++;} //显示字数+1
else //若全部显示完,则
Word_Number=0; //显示字数清0
break;
case 8: //若为第8站
if(Word_Number<5) //判断已显示字数
{if(Word_Number<3) //若未显示完“第8站”,则
{for(m=0;m<32;m++)
next[m]=State2[Word_Number][m];} //依次换字显示“第8站”
else //否则
for(m=0;m<32;m++)
next[m]=DL[Word_Number-3][m]; //依次换字显示“到了”
Word_Number++;} //显示字数+1
else //若全部显示完,则
Word_Number=0; //显示字数清0
break;
case 9: //若为第9站
if(Word_Number<5) //判断已显示字数
{if(Word_Number<3) //若未显示完“第1站”,则
{for(m=0;m<32;m++)
next[m]=State1[Word_Number][m];} //依次换字显示“第9站”
else //否则
for(m=0;m<32;m++)
next[m]=DL[Word_Number-3][m]; //依次换字显示“到了”
Word_Number++;} //显示字数+1
else //若全部显示完,则
Word_Number=0; //显示字数清0
break;
case 10: //若为第10站
if(Word_Number<5) //判断已显示字数
{if(Word_Number<3) //若未显示完“第10站”,则
{for(m=0;m<32;m++)
next[m]=State2[Word_Number][m];} //依次换字显示“第10站”
else //否则
for(m=0;m<32;m++)
next[m]=DL[Word_Number-3][m]; //依次换字显示“到了”
Word_Number++;} //显示字数+1
else //若全部显示完,则
Word_Number=0; //显示字数清0
break;
case 11: //若为第11站
if(Word_Number<5) //判断已显示字数
{if(Word_Number<3) //若未显示完“第11站”,则
{for(m=0;m<32;m++)
next[m]=State1[Word_Number][m];} //依次换字显示“第11站”
else //否则
for(m=0;m<32;m++)
next[m]=DL[Word_Number-3][m]; //依次换字显示“到了”
Word_Number++;} //显示字数+1
else //若全部显示完,则
Word_Number=0; //显示字数清0
break;
case 12: //若为第12站
if(Word_Number<5) //判断已显示字数
{if(Word_Number<3) //若未显示完“第12站”,则
{for(m=0;m<32;m++)
next[m]=State2[Word_Number][m];} //依次换字显示“第12站”
else //否则
for(m=0;m<32;m++)
next[m]=DL[Word_Number-3][m]; //依次换字显示“到了”
Word_Number++;} //显示字数+1
else //若全部显示完,则
Word_Number=0; //显示字数清0
break;
case 13: //若为第13站
if(Word_Number<5) //判断已显示字数
{if(Word_Number<3) //若未显示完“第13站”,则
{for(m=0;m<32;m++)
next[m]=State1[Word_Number][m];} //依次换字显示“第13站”
else //否则
for(m=0;m<32;m++)
next[m]=DL[Word_Number-3][m]; //依次换字显示“到了”
&nbs