isd4004语音模块全部资料,分享一下,共同学习
ISD4004模块和控制板的接线方法:
ISD4004模块 51单片机系统板
VCC VCC
GND GND
SS P1.0
MOSI P1.1
MISO P1.2
SCLK P1.3
IN P1.4
RAC P1.5
LED P1.6
isd4004模块电路图
单片机源程序如下(1.录25段,可重复查询地址):
- /* 忠兴编辑
- 经过长时间的调试,本程序已经通过验证?
- 请亲们方向使用。
- */
- /*====================================================================
- 调试要求:
- 1.MCU:AT89S52芯片
- 2.晶振:12MHz
- 使用说明:
- AN(本店的控制板上该按键标号为UP)为放音键
- SET_KEY(本店控制板上标号为SET)为录音键。
- 开机时只允许录音键使用,放音键不能使用。
- 允许放音后,录音键就失效。
- 录音操作:按住SET键就进入录音模式,放开就停止录音
- 再按就再进入录音模式,如此循环操作,将所
- 有的语言分段一次性录完。本程序最多录25段,
- 25段的时间不超过芯片的总时间
- 放音操作:录好因后,在不断电或不复位单片机的情况下
- 按AN键就放音,每按一次放一段。
- 录放音时操作时,1602会将该段语音的开始和结束地址进行显示。
- 本程序的功能就在这里,可以清晰的知道每段语音的起始地址,
- 并且在不断电或不复位单片机的情况下可进行循环查询地址。
- 4004系列语音的地址很不好找,相信有些亲们应该深有体会,
- 本人从网上找了很多通过ISP通信读取地址的程序经过验证都失败了,
- 可是很多时候又需要知道录音的地址,经过思考,终于想出了自己的方法
- 来知道录音地址。下面介绍一下。
- 本程序计算地址的原理:(以ISD4004-8为例进行介绍)
- 4004-08的录音时间是8分钟,也就是480秒
- 4004-08的开始地址是A0,结束地址是A15,这样共有A15-A0=2421个地址
- 约等于2400个地址,也就是说时间480秒,地址是2400个,根据这个推论:
- 录音1秒,就走了2400/480=5个地址,本程序的编程原理就是由录音的时间
- 来推算语音的起始地址和结束地址,经过验证,这样的编程原理是可行的。
- 本程序只适合知道自己录音的起始和结束地址,
- 对芯片原有的语音地址的查找不适合。
- 主意:录音时,按下录音键要等录音指示灯亮了才开始录音
- 录音完后松开录音键显示的地址才是本段语音的地址
- 放音时,要等本段语音播放完后显示的地址才是本段的地址0
- ====================================================================*/
- #include <reg52.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- //录音和放音键IO口定义:
- sbit AN=P2^6;//放音键控制接口
- sbit set_key=P2^7;//录音键控制口
- // ISD4004控制口定义:
- sbit SS =P1^0; //4004片选
- sbit MOSI=P1^1; //4004数据输入
- sbit MISO=P1^2; //4004数据输出
- sbit SCLK=P1^3; //ISD4004时钟
- sbit INT =P1^4; //4004中断
- sbit STOP=P3^4; //4004复位
- sbit LED1 =P1^6; //录音指示灯
- //===============================LCD1602接口定义=====================
- /*注意,P2.2到P2.4需要接上拉电阻
- ---------------------------------------------------
- =============================================================*/
- #define LCM_Data P0 //LCD1602数据接口
- sbit LCM_RW = P2^3; //读写控制输入端,LCD1602的第五脚
- sbit LCM_RS = P2^4; //寄存器选择输入端,LCD1602的第四脚
- sbit LCM_E = P2^2; //使能信号输入端,LCD1602的第6脚
- //***************函数声明************************************************
- void WriteDataLCM(uchar WDLCM);//LCD模块写数据
- void WriteCommandLCM(uchar WCLCM,BuysC); //LCD模块写指令
- uchar ReadStatusLCM(void);//读LCD模块的忙标
- void DisplayOneChar(uchar X,uchar Y,uchar ASCII);//在第X+1行的第Y+1位置显示一个字符
- void LCMInit(void);
- void DelayUs(uint us); //微妙延时程序
- void DelayMs(uint Ms);//毫秒延时程序
- void init_t0();//定时器0初始化函数
- void setkey_treat(void);//录音键处理程序
- void upkey_treat(void);//播放键处理程序
- void display();//显示处理程序
- void isd_setrec(uchar adl,uchar adh);//发送setrec指令
- void isd_rec();//发送rec指令
- void isd_stop();//stop指令(停止当前操作)
- void isd_powerup();//发送上电指令
- void isd_stopwrdn();//发送掉电指令
- void isd_send(uchar isdx);//spi串行发送子程序,8位数据
- void isd_setplay(uchar adl,uchar adh);
- void isd_play();
- //程序中的一些常量定义
- uint time_total,st_add,end_add=0;
- uint adds[25];//25段语音的起始地址暂存
- uint adde[25];//25段语音的结束地址暂时
- uchar t0_crycle,count,count_flag,flag2,flag3,flag4;
- uchar second_count=170,msecond_count=0;
- //second_count为芯片录音的起始地址,起始地址本来是A0,也就是160,
- //我们从170开始录音吧。
- #define Busy 0x80 //用于检测LCM状态字中的Busy标识
- /*===========================================================================
- 主程序
- =============================================================================*/
- void main(void)
- {
- LED1=0;//灭录音指示灯
- flag3=0;
- flag4=0;
- time_total=340;//录音地址从170开始,对应的单片机开始计时的时间就是340*0.1秒
- adds[0]=170;
- count=0;
- LCMInit(); //1602初始化
- init_t0();//定时器初始化
- DisplayOneChar( 0,5,'I'); //开机时显示000 ISD4004-X
- DisplayOneChar( 0,6,'S');
- DisplayOneChar( 0,7,'D');
- DisplayOneChar( 0,8,'4');
- DisplayOneChar( 0,9,'0');
- DisplayOneChar( 0,10,'0');
- DisplayOneChar( 0,11,'4');
- DisplayOneChar( 0,12,'-');
- DisplayOneChar( 0,13,'X');
- while(1)
- {
- display();//显示处理
- upkey_treat();//放音键处理
- setkey_treat();//录音键处理
- }
- }
- //*******************************************
- //录音键处理程序
- //从指定地址开始录音的程序就是在这段里面
- void setkey_treat(void)
- {
- set_key=1;//置IO口为1,准备读入数据
- DelayUs(1);
- if(set_key==0)
- {
- if(flag3==0)//录音键和放音键互锁,录音好后,禁止再次录音。如果要再次录音,那就要复位单片机,重新开始录音
- {
- if(count==0)//判断是否为上电或复位以来第一次按录音键
- {
- st_add=170;
- }
- else
- {
- st_add=end_add+3;
- }//每段语言间隔3个地址
- adds[count]=st_add;//每段语音的起始地址暂时
- if(count>=25)//判断语音段数时候超过25段,因为单片机内存的关系?
- //本程序只录音25段,如果要录更多的语音,改为不可查询的即可
- {//如果超过25段,则覆盖之前的语音,从新开始录音
- count=0;
- st_add=170;
- time_total=340;
- }
- isd_powerup(); //AN键按下,ISD上电并延迟50ms
- isd_stopwrdn();
- isd_powerup();
- LED1=1;//录音指示灯亮,表示录音模式
- isd_setrec(st_add&0x00ff,st_add>>8); //从指定的地址
- if(INT==1)// 判定芯片有没有溢出
- {
- isd_rec(); //发送录音指令
- }
- time_total=st_add*2;//计时初始值计算
- TR0=1;//开计时器
- while(set_key==0);//等待本次录音结束
- TR0=0;//录音结束后停止计时
- isd_stop(); //发送4004停止命令
- end_add=time_total/2+2;//计算语音的结束地址
- adde[count]=end_add;//本段语音结束地址暂存
- LED1=0; //录音完毕,LED熄灭
- count++;//录音段数自加
- count_flag=count;//录音段数寄存
- flag2=1;
- flag4=1;//解锁放音键
- }
- }
- }
- //=================================================
- //放音机处理程序
- //从指定地址开始放本段语音就是这段程序
- void upkey_treat(void)
- {
- uchar ovflog;
- AN=1;//准备读入数据
- DelayUs(1);
- if(AN==0)//判断放音键是否动作
- {
- if(flag4==1)//互锁录音键
- {
- if(flag2==1)//判断是否为录音好后的第一次放音
- {
- count=0;//从第0段开始播放
- }
- isd_powerup(); //AN键按下,ISD上电并延迟50ms
- isd_stopwrdn();
- isd_powerup();
- st_add=adds[count];//送当前语音的起始地址
- isd_setplay(st_add&0x00ff,st_add>>8); //发送setplay指令,从指定地址开始放音
- isd_play(); //发送放音指令
- DelayUs(20);
- while(INT==1); //等待放音完毕的EOM中断信号
- isd_stop(); //放音完毕,发送stop指令
- while(AN==0); //
- isd_stop();
- count++;//语音段数自加
- flag2=0;
- flag3=1;
- if(count>=count_flag)//如果播放到最后一段后还按加键,则从第一段重新播放
- {
- count=0;
- }
-
- }
- }
- }
- //************************************************?
- //发送rec指令
- void isd_rec()
- {
- isd_send(0xb0);
- SS=1;
- }
- //****************************************
- //发送setrec指令
- void isd_setrec(unsigned char adl,unsigned char adh)
- {
- DelayMs(1);
- isd_send(adl); //发送放音起始地址低位
- DelayUs(2);
- isd_send(adh); //发送放音起始地址高位
- DelayUs(2);
- isd_send(0xa0); //发送setplay指令字节
- SS=1;
- }
- //=============================================================================
- //**********************************************
- //定时器0中断程序
- void timer0() interrupt 1
- {
- TH0=(65536-50000)/256;
- TL0=(65536-50000)%256;
- t0_crycle++;
- if(t0_crycle==2)// 0.1秒
- {
- t0_crycle=0;
- time_total++;
- msecond_count++;
- if(msecond_count==10)//1秒
- {
- msecond_count=0;
- second_count++;
- if(second_count==60)
- {
- second_count=0;
- }
- }
- if(time_total==4800)time_total=0;
- }
- }
- //********************************************************************************************
- //定时器0初始化函数
- void init_t0()
- {
- TMOD=0x01;//设定定时器工作方式1,定时器定时50毫秒
- TH0=(65536-50000)/256;
- TL0=(65536-50000)%256;
- EA=1;//开总中断
- ET0=1;//允许定时器0中断
- t0_crycle=0;//定时器中断次数计数单元
- }
- //******************************************
- //显示处理程序
- void display()
- {
- uchar x;
- if(flag3==1||flag4==1)//判断是否有录音过或者放音过
- {
- x=count-1;
- if(x==255){x=count_flag-1;}
- }
- DisplayOneChar( 0,0,x/100+0x30); //显示当前语音是第几段
- DisplayOneChar( 0,1,x/10%10+0x30);
- DisplayOneChar( 0,2,x%10+0x30);
- if(flag3==0)//录音时显示本段语音的起始和结束地址
- {
- DisplayOneChar( 1,0,st_add/1000+0x30);//计算并显示千位
- DisplayOneChar( 1,1,st_add/100%10+0x30);
- DisplayOneChar( 1,2,st_add/10%10+0x30);
- DisplayOneChar( 1,3,st_add%10+0x30);
- DisplayOneChar( 1,4,'-');
- DisplayOneChar( 1,5,'-');
- DisplayOneChar( 1,6,end_add/1000+0x30);
- DisplayOneChar( 1,7,end_add/100%10+0x30);
- DisplayOneChar( 1,8,end_add/10%10+0x30);
- DisplayOneChar( 1,9,end_add%10+0x30);
- }
- if(flag4==1)//放音时显示本段语音的起始和结束地址
- {
- DisplayOneChar( 1,0,adds[x]/1000+0x30);
- DisplayOneChar( 1,1,adds[x]/100%10+0x30);
- DisplayOneChar( 1,2,adds[x]/10%10+0x30);
- DisplayOneChar( 1,3,adds[x]%10+0x30);
- DisplayOneChar( 1,4,'-');
- DisplayOneChar( 1,5,'-');
- DisplayOneChar( 1,6,adde[x]/1000+0x30);
- DisplayOneChar( 1,7,adde[x]/100%10+0x30);
- DisplayOneChar( 1,8,adde[x]/10%10+0x30);
- DisplayOneChar( 1,9,adde[x]%10+0x30);
- }
- }
- //======================================================================
- // LCM初始化
- //======================================================================
- void LCMInit(void)
- {
- LCM_Data = 0;
- WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号
- DelayMs(5);
- WriteCommandLCM(0x38,0);
- DelayMs(5);
- WriteCommandLCM(0x38,0);
- DelayMs(5);
- WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号
- WriteCommandLCM(0x08,1); //关闭显示
- WriteCommandLCM(0x01,1); //显示清屏
- WriteCommandLCM(0x06,1); // 显示光标移动设置
- WriteCommandLCM(0x0C,1); // 显示开及光标设置
- DelayMs(100);
- }
- //*=====================================================================
- // 写数据函数: E =高脉冲 RS=1 RW=0
- //======================================================================
- void WriteDataLCM(uchar WDLCM)
- {
- ReadStatusLCM(); //检测忙
- LCM_Data = WDLCM;
- LCM_RS = 1;
- LCM_RW = 0;
- LCM_E = 0; //若晶振速度太高可以在这后加小的延时
- LCM_E = 0; //延时
- LCM_E = 1;
- }
- //*====================================================================
- // 写指令函数: E=高脉冲 RS=0 RW=0
- //======================================================================
- void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测
- {
- if (BuysC) ReadStatusLCM(); //根据需要检测忙
- LCM_Data = WCLCM;
- LCM_RS = 0;
- LCM_RW = 0;
- LCM_E = 0;
- LCM_E = 0;
- LCM_E = 1;
- }
- //*====================================================================
- // 正常读写操作之前必须检测LCD控制器状态:E=1 RS=0 RW=1;
- // DB7: 0 LCD控制器空闲,1 LCD控制器忙。
- // 读状态
- //======================================================================
- unsigned char ReadStatusLCM(void)
- {
- LCM_Data = 0xFF;
- LCM_RS = 0;
- LCM_RW = 1;
- LCM_E = 0;
- LCM_E = 0;
- LCM_E = 1;
- while (LCM_Data & Busy); //检测忙信号
- return(LCM_Data);
- }
- //======================================================================
- //功 能: 在1602 指定位置显示一个字符:第一行位置0~15,第二行16~31
- //说 明: 第 X 行,第 y 列 注意:字符串不能长于16个字符
- //======================================================================
- void DisplayOneChar( unsigned char X, unsigned char Y, unsigned char ASCII)
- {
- X &= 0x1;
- Y &= 0xF; //限制Y不能大于15,X不能大于1
- if (X) Y |= 0x40; //当要显示第二行时地址码+0x40;
- Y |= 0x80; // 算出指令码
- WriteCommandLCM(Y, 0); //这里不检测忙信号,发送地址码
- WriteDataLCM(ASCII);
- }
- //======================================================================
- //spi串行发送子程序,8位数据
- void isd_send(uchar isdx)
- {
- uchar 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;
- DelayUs(2);
- SCLK=0;
- DelayUs(2);
- }
- }
- //======================================================================
- //stop指令(停止当前操作)
- void isd_stop()//
- {
- DelayUs(10);
- isd_send(0x30);
- SS=1;
- DelayMs(50);
- }
- //======================================================================
- //发送上电指令
- void isd_powerup()//
- {
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
2无限段录音程序,不可查询,单片机源程序如下:
- /* 忠兴店编辑
- 经过长时间的调试,本程序已经通过验证?
- 请亲们方向使用。
- */
- /*====================================================================
- 调试要求:
- 1.MCU:AT89S52芯片
- 2.晶振:12MHz
- 使用说明:
- SET_KEY(本店控制板上标号为SET)为录音键。
- 录音操作:按住SET键就进入录音模式,放开就停止录音
- 再按就再进入录音模式,如此循环操作,将所
- 有的语言分段一次性录完。
- 录音时操作时,1602会将该段语音的开始和结束地址进行显示。
- 主意:录音时,按下录音键要等录音指示灯亮了才开始录音
- 录音完后松开录音键显示的地址才是本段语音的地址,本程序可以录255段,
- 但是总时间不能超过8分钟,因为本程序不可查询语言的地址,所有每录
- 一段语言就用笔手动记下起始和结束地址。
- ====================================================================*/
- #include <reg52.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- //录音键IO口定义:
- sbit set_key=P2^7;//录音键控制口
- // ISD4004控制口定义:
- sbit SS =P1^0; //4004片选
- sbit MOSI=P1^1; //4004数据输入
- sbit MISO=P1^2; //4004数据输出
- sbit SCLK=P1^3; //ISD4004时钟
- sbit INT =P1^4; //4004中断
- sbit STOP=P3^4; //4004复位
- sbit LED1 =P1^5; //录音指示灯
- //===============================LCD1602接口定义=====================
- /* 注意,P2.2到P2.4需要接上拉电阻
- ---------------------------------------------------
- =============================================================*/
- #define LCM_Data P0 //LCD1602数据接口
- sbit LCM_RW = P2^3; //读写控制输入端,LCD1602的第五脚
- sbit LCM_RS = P2^4; //寄存器选择输入端,LCD1602的第四脚
- sbit LCM_E = P2^2; //使能信号输入端,LCD1602的第6脚
- //***************函数声明************************************************
- void WriteDataLCM(uchar WDLCM);//LCD模块写数据
- void WriteCommandLCM(uchar WCLCM,BuysC); //LCD模块写指令
- uchar ReadStatusLCM(void);//读LCD模块的忙标
- void DisplayOneChar(uchar X,uchar Y,uchar ASCII);//在第X+1行的第Y+1位置显示一个字符
- void LCMInit(void);
- void DelayUs(uint us); //微妙延时程序
- void DelayMs(uint Ms);//毫秒延时程序
- void init_t0();//定时器0初始化函数
- void setkey_treat(void);//录音键处理程序
- void display();//显示处理程序
- void isd_setrec(uchar adl,uchar adh);//发送setrec指令
- void isd_rec();//发送rec指令
- void isd_stop();//stop指令(停止当前操作)
- void isd_powerup();//发送上电指令
- void isd_stopwrdn();//发送掉电指令
- void isd_send(uchar isdx);//spi串行发送子程序,8位数据
- //程序中的一些常量定义
- uint time_total,st_add,end_add=0;
- uchar t0_crycle,count;
- uchar second_count=170,msecond_count=0;
- //second_count为芯片录音的起始地址,起始地址本来是A0,也就是160,
- //我们从170开始录音吧。
- #define Busy 0x80 //用于检测LCM状态字中的Busy标识
- /*===========================================================================
- 主程序
- =============================================================================*/
- void main(void)
- {
- LED1=0;//灭录音指示灯
- time_total=340;//录音地址从170开始,对应的单片机开始计时的时间就是340*0.1秒
- count=0;
- LCMInit(); //1602初始化
- init_t0();//定时器初始化
- DisplayOneChar( 0,5,'I'); //开机时显示000 ISD4004-X
- DisplayOneChar( 0,6,'S');
- DisplayOneChar( 0,7,'D');
- DisplayOneChar( 0,8,'4');
- DisplayOneChar( 0,9,'0');
- DisplayOneChar( 0,10,'0');
- DisplayOneChar( 0,11,'4');
- DisplayOneChar( 0,12,'-');
- DisplayOneChar( 0,13,'X');
- while(1)
- {
- display();//显示处理
- setkey_treat();//录音键处理
- }
- }
- //*******************************************
- //录音键处理程序
- //从指定地址开始录音的程序就是在这段里面
- void setkey_treat(void)
- {
- set_key=1;//置IO口为1,准备读入数据
- DelayUs(1);
- if(set_key==0)
- {
- if(count==0)//判断是否为上电或复位以来第一次按录音键
- {
- st_add=170;
- }
- else
- {
- st_add=end_add+3;
- }//每段语言间隔3个地址
- isd_powerup(); //AN键按下,ISD上电并延迟50ms
- isd_stopwrdn();
- isd_powerup();
- LED1=1;//录音指示灯亮,表示录音模式
- isd_setrec(st_add&0x00ff,st_add>>8); //从指定的地址
- if(INT==1)// 判定芯片有没有溢出
- {
- isd_rec(); //发送录音指令
- }
- time_total=st_add*2;//计时初始值计算
- TR0=1;//开计时器
- while(set_key==0);//等待本次录音结束
- TR0=0;//录音结束后停止计时
- isd_stop(); //发送4004停止命令
- end_add=time_total/2+2;//计算语音的结束地址
- LED1=0; //录音完毕,LED熄灭
- count++;//录音段数自加
- }
- }
- //************************************************?
- //发送rec指令
- void isd_rec()
- {
- isd_send(0xb0);
- SS=1;
- }
- //****************************************
- //发送setrec指令
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码 所有资料51hei提供下载:
ISD4004配套资料.rar
(373.19 KB, 下载次数: 212)
|