| //*****************************************************//      ISD4002-89c51开发板演示例程    C51版本        *
 //              作者:中青世纪       Lell             *
 //                     2008.2.27                      *
 //                                                    *
 //      更多ISD4000使用心得请登陆中青世纪论坛         *
 //        http://www.atvoc.com/bbs                    *
 //                                                    *
 //*****************************************************
 #include <reg51.h>
 sbit SS   =     P1^0;              //片选
 sbit SCLK =     P1^1;              //ISD4003时钟
 sbit MOSI =     P1^2;              //数据输入
 sbit MISO =     P1^3;              //数据输出
 sbit LED =     P1^7;              //指示灯
 sbit ISD_INT=   P3^2;           //中断
 sbit AN =     P1^6;              //执行
 sbit STOP =     P1^5;             //复位
 sbit PR =     P1^4;              //PR=1录音? PR=0放音
 void    delay(unsigned int time)   //延迟n微秒
 {
 while(time!=0)
 {
 time-- ;
 }
 }
 void     delayms(unsigned int time)    //延迟n毫秒
 {    TMOD=0x01;
     for(time;time>0;time--){
 TH0=0xfc;
 TL0=0x18;
 TR0=1;
 while(TF0!=1)
 {;}
 TF0=0;
 TR0=0;
 }
 } //************************************//ISD4002 spi串行发送子程序,8位数据
 //************************************
 void spi_send(unsigned char isdx)
 {   unsigned char isx_counter;
 SS=0;     //ss=0,打开spi通信端
 SCLK=0;
 for(isx_counter=0;isx_counter<8;isx_counter++) //先发低位再发高位,依次发送。
 { if ((isdx&0x01)==1)
 MOSI=1;
 else
 MOSI=0;
 isdx=isdx>>1;
 SCLK=1;
 delay(2);
    SCLK=0;delay(2);
 }
 }
 //*******************************//发送stop指令
 //*******************************
 void isd_stop(void)
 {   delay(10);
 spi_send(0x30);
 SS=1;
 delayms(50);
 }
 //*******************************
 //发送上电指令,并延迟50ms
 //*******************************
 void isd_pu(void)
 {  delay(10);
 SS=0;
 spi_send(0x20);
 SS=1;
 delayms(50);
 }
 //*******************************
 //发送掉电指令,并延迟50ms
 //*******************************
 void isd_pd(void){ delay(10);
      spi_send(0x10);SS=1;
 delayms(50);
 }
 //*******************************
 //发送play指令
 //*******************************
 void isd_play(void)
 {
 LED=0;
 spi_send(0xf0);
 SS=1;
 }
 //*******************************
 //发送rec指令
 //*******************************
 void isd_rec(void)
 {
 LED=0;
 spi_send(0xb0);
 SS=1;
 }
 //*******************************
 //发送setplay指令
 //*******************************
 void isd_setplay(unsigned char adl,unsigned char adh)
 { spi_send(adl);    //发送放音起始地址低位adh=adh||0xe0;
 spi_send(adh);   //发送放音起始地址高位
 SS=1;
 }
 //*******************************
 //发送setrec指令
 //*******************************
 void isd_setrec(unsigned char adl,unsigned char adh)
 {
 spi_send(adl);    //发送放音起始地址低位
 adh=adh||0xa0;
 spi_send(adh);    //发送放音起始地址高位
 SS=1;
 }
 //************************************
 //芯片溢出,LED闪烁提醒停止录音
 //************************************
 void isd_overflow(void)
 {
 while(AN==0)
 {LED=1;
 delayms(300);
 LED=0;
 delayms(300);
 }
 }//************************************
 //检查芯片是否溢出(读OVF,并返回OVF值)
 //************************************
 unsigned char chk_isdovf(void)
 {
 SS=0;
 delay(2);
 SCLK=0;
 delay(2);
 SCLK=1;
 SCLK=0;
 delay(2);
 if (MISO==1){ SCLK=0;
 SS =1;     //关闭spi通信端
 isd_stop();     //发送stop指令
 return 1;     //OVF为1,返回1
 }
 else
 { SCLK=0;
 SS =1;         //关闭spi通信端
 isd_stop();     //发送stop指令
 return 0;     //OVF为0,返回0
 }}
 //************************************************************************//主程序
 //功能:1.录音时,按住AN键,LED点亮开始录音,松开AN即可停止录音
 //    再次按下AN键,LED点亮开始录第二段音,依次类推,直到芯片溢出。
 //     按stop键芯片复位
 //     2.放音时,按一下AN键,即播放一段语音。 按stop键芯片复位。
 //************************************************************************
 void main(void){unsigned char ovflog;
 while(1)
 {
 P0=P1=P2=P3=0xff;  //初始化
 while (AN==1)     //等待AN键按下
 {
 if (AN==0)                 //按键防抖动
 {delayms(20);}
 }
 isd_pu();     //AN键按下,ISD上电并延迟50ms
 isd_pd();
 isd_pu();
     if (PR==1)     //如果PR=1则转入录音部分{
 delayms(500);     //延迟录音
      isd_setrec(0x00,0x00);     //发送0x0000h地址的setplay指令do
 { isd_rec();    //发送rec指令
 while(AN==0)    //等待录音完毕
 {if (ISD_INT==0)     //如果芯片溢出,进行LED闪烁提示,
 isd_overflow();    //如果取消录音(松开AN键)则停止录音,芯片复位
 }
      if (ISD_INT==0)      break;LED=1;         //录音完毕,LED熄灭
 isd_stop();     //发送停止命令
 while(AN==1)     //如果AN再次按下,开始录制下一段语音
 {if(STOP==0)    //如果按下STOP按键,则芯片复位
 break;
 if (AN==0)
 delayms(500);
 }
 }while(AN==0);
     }else             //如果PR==0则转入放音部分
 {
 while(AN==0){;}
 isd_setplay(0x00,0x00);     //发送setplay指令,从0x0000地址开始放音
 do
 { isd_play();            //发送放音指令
 delay(20);
 while(ISD_INT==1)         //等待放音完毕的EOM中断信号
 {;}
 LED=1;
 isd_stop();         //放音完毕,发送stop指令
      if (ovflog=chk_isdovf())         //检查芯片是否溢出 ,如溢出则停止放音,芯片复位break;
 while(AN==1)     //等待AN键再次按下
 {if (STOP==0)
 break;
 if(AN==0)
 delayms(20);
 }
 }while(AN==0);     // AN键再次按下,播放下一段语音
 }
 isd_stop();isd_pd();
 }
 }
 注意:与ISD4002/03不同的是,由于ISD4004芯片的语音地址是16位,在发送带地址指令(如setplay,setrec,setmc)时,需要先发送两个字节的地址信息,再发送一个字节的命令字,ISD4004的程序编写与ISD4002/03的区别,仅此而已。
 例如,ISD4004的setplay指令程序应为:
 void isd_setplay(unsigned char adl,unsigned char adh)
 {
 delayms(1);
 spi_send(adl);     //发送放音起始地址低位
 delay(2);
 spi_send(adh);    //发送放音起始地址高位
 delay(2);
 spi_send(0xe0);    //发送setplay指令字节
 SS=1;
 }
 |