新闻  |   论坛  |   博客  |   在线研讨会
公交语音提示
tvb2058 | 2007-09-14 11:07:20    阅读:6235   发布文章

 
 

//***************************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段保存报站信息“到了,请要下车的乘客依次从后门下车”
//1819段分别保存预报信息“前方到站”、“请要下车的乘客做好下车准备”
//20段保存欢迎信息及公交车线路说明
//2122段保存特殊提示信息
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)               //定义ISD2560PD线为PA^3     
{if(level)    PORTA |=0x08;
 else         PORTA &=0xf7;
}

void Set_PR(uchar level)               //定义ISD2560PR线为PA^2
{if(level)    PORTA |=0x04;
 else         PORTA &=0xfb;
}

void Set_A6(uchar level)               //定义ISD2560A6/8/9线为PA^1
{if(level)    PORTA |=0x02;
 else         PORTA &=0xfd;
}

void Set_A0(uchar level)               //定义ISD2560A6/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);              
}

//***************************写一字节数据****************************//
//向从地址为SlaveIIC器件的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();                               //
停止
}

//***************************写两字节数据****************************//
//向从地址为SlaveIIC器件的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();                         //
停止信号
}

//***************************读一字节数据****************************//
//从从地址为SlaveIIC器件的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

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
推荐文章
最近访客