51单片机控制ISD1420实现选段播放功能的实现(C程序 电路图)
发布: 2009-4-27 09:39 | 作者: hnrain | 查看: 418次
资料编写与整理:AVR猎手benladn911 出处:AVR猎手的地盘 http://benladn911.21ic.org/ www.avrzone.com转载请注明出处
在2006年时候记得我在做 ISD1420的播放控制,当时在 选段播放上遇到了问题,当时网络上也没有详细描述具体的控制方法,也在咱们坛子里问过。
折腾了很久,后来还是实现出来了。但资料后来没有实际应用到产品上,今天翻看资料的时候发现了,拿出来给同样碰到问题的朋友做为参考。
以前写的C程序比较菜,注释比较多。(现在写的程序注释也很多 :)
电路图简单画了下,大家都看得懂:
附上 KEIL完整工程:
1420_code.rar
程序原文:
/**********************************************************
功能: 使用STC2052单片机控制 ISD1420语音芯片的播放
1、顺序连续分段放音
2、选段播放(播放任意段)
3、所有的播放控制都是通过接收串口的命令来执行
编写: benladn911 AVR猎手
日期: 2006-6-28创建
2008-2-21添加注释和完善
**********************************************************/
#i nclude #i nclude #i nclude #i nclude //硬件端口的定义 #define POW P3_7 //此引脚为单片机控制一个三极管给 ISD1420供电 #define PL P3_5 //接 ISD1420 的 PLAYL #define PE P3_4 //接 ISD1420 的 PLAYE #define REC P3_3 //接 ISD1420 的 REC #define REC_LED P3_2 //ISD1420 的 REC LED //操作模式的定义 #define mode1 0xC8 //循环放音操作,按一下 PE 键可循环放音,按 PL 键停止;或按 PL 键放音,松开即停止 #define mode2 0xD0 //按顺序连续分段录放音,每段语音长度不限 #define mode3 0xC0 //地址指针复位,开始录放第一段 #define mode4 0xD1 //按 PE 键可快速选段放音 //0xC1 //也为地址指针复位 unsigned char RX_index=0; // bit FLAG_rev = 0; // unsigned char PC_COMMAND; unsigned char RX_BUFFER[10];//串行接收缓存 void io_init(void); void init_serialcomm(void); void serial_out(unsigned char d); void delay5ms(void); void delay(unsigned int x); void nop(unsigned char i); void paly(unsigned char i);//选择播放当前段操作 void main(void) { io_init(); init_serialcomm(); delay(1000); serial_out(0xaa); //发送到PC机,看看PC端是否收到正确数据 serial_out(0x55); serial_out(0x33); POW = 0;//开启电源 //P1 = mode4; //P1 = 0X00; while(1) { } } //----- 端口初始化 void io_init(void) { P1M0 = 0x00; //设置STC的 IO 为标准51 IO模式 P1M1 = 0x00; P3M0 = 0x00; P3M1 = 0x00; P1 = 0XFF; P3 = 0XFF; } //串行口初始化 void init_serialcomm(void) { SCON = 0x50; //SCON: serail mode 1, 8-bit UART, enable ucvr TMOD = 0x20; //TMOD: timer 1, mode 2, 8-bit reload TH1 = 0xf3;//12MHz, 2400 bps TL1 = 0xf3; //IE |= 0x90; //Enable Serial Interrupt TR1 = 1; // timer 1 run ES=1; EA=1; } //串行数据发送,查询模式 void serial_out(unsigned char d) { ES=0; SBUF=d;while(TI==0){;}TI=0; ES=1; } //串行中断接收 void receive() interrupt 4 { if(RI) { RI = 0; ES = 0; PC_COMMAND = SBUF; //RX_BUFFER[RX_index] = PC_COMMAND; //里面 保存数据到数组 //RX_index++; switch(PC_COMMAND) { case 0xa0: serial_out(0xa0); P1 = mode2; //按顺序连续分段录放音,每段语音长度不限 0xD0 连续寻址,A4 PE = 0; nop(10); PE = 1; P1 = 0XFF; break; case 0xb0: serial_out(0xb0); P1 = mode3; //地址指针复位 0xC0 nop(10); P1 = 0XFF; break; case 0xc0: //选段播放控制 serial_out(0xc0); P1 = 0xD1; // P1_0 = 0; nop(10); P1_0 = 1; nop(10); PE = 0; nop(10); PE = 1; 第二步:快速选段放音 break; case 0xd0: serial_out(0xd0); //播放任意段的组合 paly(3); paly(1); paly(5); paly(5); paly(6); paly(4); paly(3); paly(6); paly(1); break; case 0x30: serial_out(0x30); //此操作循环放音操作,按一下 PE 键可循环放音,按 PL 键停止;或按 PL 键放音,松开即停止 //此操作没什么用 P1 = mode1; PE = 0; nop(10); PE = 1; // break; default: break; } ES = 1; } } /************************************************************* 选段播放,i 的值就是要播放的当前段 i的取值:1 ~ ... **************************************************************/ void paly(unsigned char i) { i--; P1 = mode3; //第一步:地址指针复 位 0xC0 A7--A0: 1100 0000 (A2、A5在应用中可直接接地) nop(10); //P1 = 0XFF; delay(30);//必要的延时 if(i>0) { P1 = 0xD1; //第二步:快速选段放音 0xD1 A7--A0: 1101 0001 (A2、A5在应用中可直接接地) do { P1_0 = 0; //给 A0 低电平脉冲 nop(10); P1_0 = 1; nop(10); PE = 0; nop(10); PE = 1; delay(50);//这个延时是非常必要的! i--; } while(i!=0); delay(30);//必要的延时 } P1 = mode2; //第三步:播放当前段 0xD0 A7--A0: 1101 0000 A5在应用中可直接接地) PE = 0; nop(10); PE = 1; //P1 = 0XFF; while(REC_LED==1){;}//等待播放 A2、( while(REC_LED==0){;}//等待播放结束 } //----------------------------软件延时函数---------------------------- //50ms延时 void delay5ms(void) { unsigned char TempCyc = 250; while(TempCyc--); } void delay(unsigned int x) { do { delay5ms();delay5ms();delay5ms();x--; } while(x!=0); } void nop(unsigned char i) { do { _nop_(); i--; } while(i!=0); 因篇幅问题不能全部显示,请点此查看更多更全内容