⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 can.c

📁 can模块
💻 C
字号:
/*****************************************************************/ 
/*名    称:        语音模块实验                                 */                                                                                                                                                                           
/*功    能:        能够录制,播放语音信息                       */                                                    
/*芯片类型:        AT89S51                                      */                                                                
/*晶振频率:        11.0592MHZ                                   */ 
/*难度等级:        高                                           */                                                                     
/*作    者:        救火车                                       */
/*版    权:        http://www.qm999.cn                          */
/*编写日期:        2008-12-5                                    */                                                                                                                                                                                                             
/*****************************************************************/
#include <reg51.h>
#include <delay.h>

sbit SCK = P0^0;   //语音模块控制管脚定义
sbit SS = P0^1;
sbit MOSI = P0^2;
sbit MISO = P0^3;
sbit INT = P0^4;
sbit RAC = P0^5;
sbit PLAY = P1^6;   //录音/放音 按键
sbit STOP = P1^5;	//复位按键
sbit P_R = P1^7;	//录音/放音跳线

sbit KEY=P3^2;       //定义按键使用的I/O口,P3.2  此处定义为KEY ,与学习板上标号保持一致。
sbit LED = P2^7;	 //学习板上指示灯	
sbit spk=P2^5;    //定义蜂鸣器使用的I/O口P2.5
#include "beep.c"
#include <intrins.h>
#include "sub4094.c"
#include "uart.c"
/*
ISD4003 SPI串行发送子程序 8位数据
*/
//向语音芯片发送数据函数
void spi_send(unsigned char isdx)
{
unsigned char i;
SS = 0;
SCK = 0;
for(i = 0;i < 8;i++)   //先发低位再发高位,依次发送
{
	if((isdx&0x01) == 1) MOSI = 1;
	else MOSI = 0;
	isdx>>=1;
	SCK = 1;
	delay_us(2);
	SCK = 0;
	delay_us(2);
}
}
void isd_stop(void)   //发送STOP指令
{
delay_us(10);
spi_send(0x30);
SS = 1;
delay_ms(50);
}
void isd_pu(void)    //发送上电指令,延时50ms
{
delay_us(10);
SS = 0;
spi_send(0x20);
SS = 1;
delay_ms(50);
}
void isd_pd(void)   //发送掉电指令
{
delay_us(10);
spi_send(0x10);
SS = 1;
delay_ms(50);
}
void isd_play(void)  //发送放音指令
{
LED=0;
spi_send(0xf0);
SS = 1;
}
void isd_rec(void)   //发送录音指令
{
LED=0;
spi_send(0xb0);
SS = 1;
}
void isd_setplay(unsigned char adl,unsigned char adh) //发送放音地址指令
{
spi_send(adl);     //发送放音起始低地址
adh = adh|0xe0;
spi_send(adh);     //发送放音起始高地址
SS = 1;
}
void isd_setrec(unsigned char adl,unsigned char adh)   //发送录音地址指令
{
spi_send(adl);     //发送录音起始低地址
adh = adh|0xa0;
spi_send(adh);     //发送录音起始高地址
SS = 1;
}
void isd_overflow(void)  //芯片溢出警告函数
{
while(0 == PLAY)           //指示灯闪烁
{
	LED = 0;
	delay_ms(300);
	LED = 1;
	delay_ms(300);
}
}
unsigned char chk_isdovf()  //检测芯片溢出函数
{
SS = 0;
delay_us(2);
SCK = 0;
delay_us(2);
SCK = 1;
SCK = 0;
delay_us(2);
if (1 == MISO)
{
	SCK = 0;    //
	SS = 1;     //关闭SPI通信端
	isd_stop();  //发送STOP指令
	return (1);  //OVF为1 返回 1  
	 
}
else 
{
	SCK = 0;
	SS = 1;        //关闭SPI通信	
	isd_stop();  //发送STOP指令
	return (0);	 //OVF为0 ,返回 0	
}
}

void sect_play(unsigned char adl,unsigned char adh)  //放音函数
{
	isd_setplay(adl,adh);
	isd_play();
	delay_us(20);
	while(1 == INT);
	LED = 1;
	isd_stop();
	if(chk_isdovf()) 
	{
		isd_stop();
		isd_pd();
	}	
}

//函数名称:返回指令执行情况函数
//输入参数:命令码,帧序号,指令执行标志,
void ret_order(unsigned char order,unsigned char zhen_xh,unsigned char state)
{
unsigned char sum;
putchar(0xfa);     //起始字
putchar(0x05);     //字节个数
putchar(order);	   //命令码		
sum=0x05+order;
putchar(zhen_xh);	//帧序号 
sum+=zhen_xh;		
putchar(state);		//指令执行标志 0失败,1成功 
sum+=0x01;
putchar(sum);		//校验码
putchar(0xfb);		//结束字

}
unsigned char frame;
void main(void)
{
unsigned char i,kk;   //随即变量
unsigned char LAST_KEY,THIS_KEY; // 独立按键状态变量
unsigned char order,zjgs,zhen_xh,sum; //串行通讯 命令码,字节个数,帧序号,校验码
unsigned short tt;   //延时计数变量
unsigned char rx_data[10]; //串口接收 数据缓冲区
 
P4=0xff;       //将模拟I/O口P4所有管脚置为高电平  ,对于P4,P5的定义,在sub4094.C文件中。 
P5=0xff;	   //将模拟I/O口P5所有管脚置为高电平 
update4094();  //通过对4094的操作, 控制P4,P5的输出状态。经过此操作之后,数码管和流水灯就不会显示任何东西了。  
init_uart();   //初始化串行口
isd_pu();    //发送语音模块上电指令
isd_pd();    //掉电指令
isd_pu();	 //上电指令
delay_ms(500);
while(1)
{
	while(1 == PLAY)     //等待PLAY按键被按下

	{
		if(0 == PLAY) delay_ms(20);  //如果按键被按下,延时去抖动
		if(6 > rx_counter) goto end; //如果串行口缓冲区内数据不超过6个字节。跳出
		kk = getchar();
		if(0xfa != kk) goto end;	   //如果缓冲区内第一个字节不是0XFA,跳出		
		zjgs = getchar();              //读取整条指令字节个数
		tt=0;
		while(rx_counter < zjgs)       //如果缓冲区内字节数小于指令字节数
		{
			if(tt++ > 2000) goto end;     //延时一段时间, 如果超时,退出
		}
		sum = zjgs;          //计算校验码
		order = getchar();   //读取命令码
		sum+= order;        
		zhen_xh = getchar(); //读取帧序号
		sum+= zhen_xh;  
 	    for(i = 0;i < zjgs-4;i++)   //读取信息数据流
		{
   			rx_data[i] = getchar();
			sum+= rx_data[i];
		}
		kk = getchar();    //读取校验码
		if(kk != sum)   //如果校验不正确  
		{
			ret_order(order,zhen_xh,0);  //返回指令校验失败
			for(i=0;i<8;i++)  
			{
		    LED=~LED;     //取反指示灯
			spk=~spk;     //取反蜂鸣器
			delay_ms(200); 
			}
			goto end;   //退出
		}
		kk = getchar();    //校验正确 读取结束字
		if(0xfb != kk) {putchar (0);goto end;}   //如果结束字不正确,退出。
		switch(order)      //整条指令校验正确,根据命令码进行操作。
		{
			case 23: 
					 delay_ms(10);
					 isd_setrec(rx_data[0],rx_data[1]);     //发送录音开始地址给ISD4003 
					 isd_rec();  //发送录音指令给ISD4003
					 tt=rx_data[3];
					 tt<<=8;
					 tt=tt+rx_data[2];  
					 delay_ms(tt);   //延时等待录音完毕。
					 LED=1;
					 isd_stop();     //发送停止录音指令
					 ret_order(order,zhen_xh,1); //返回指令执行成功 
					 break;
			case 24: sect_play(rx_data[0],rx_data[1]); //放音函数 
					 tt=rx_data[3];
					 tt<<=8;
					 tt=tt+rx_data[2];
					 delay_ms(tt);   //延时等待放音完毕。
					 ret_order(order,zhen_xh,1); //返回指令执行成功
					 break;	
			case 25: isd_stop();
					 ret_order(order,zhen_xh,1); //返回指令执行成功
					 break;	
			default:break;
		}
		end:;
		
	}
	isd_pu();    //发送上电指令
	isd_pd();    //发送掉电指令
	isd_pu();	 //发送上电指令
	if(0 == P_R)      //如果跳线在录音一端,进入录音状态
	{
		//sound_1();
		delay_ms(500);
		isd_setrec(0x00,0x00);     //发送录音开始地址
		do
		{
			isd_rec();  //发送录音指令
			while (0 == PLAY)  //循环等待录音结束
			{	
				if (0 == INT) isd_overflow();   //如果溢出,则指示灯闪烁
			}
			if(0 == INT) break;   //跳出
			LED = 1;
			isd_stop();     //发送停止录音指令
			while(1 == PLAY)    //等待按键被按下
			{
				if(0 == STOP) break; //按一下STOP键,跳出录音操作过程
				if(0 == PLAY) {delay_ms(500);}  
			}
		}while(0 == PLAY);	
	}
	else  //如果跳线在放音一端 
	{
		//sound_1();
		//delay_ms(50);
		//sound_1();
		while(0 == PLAY);  //按一下PLAY按键,等待按键抬起,
		isd_setplay(0x00,0x00);  //发送放音地址,
		do
		{
			isd_play();			//发送放音指令。
			delay_us(20);
			while(1 == INT)		//放音,直到遇到一段语音结束标志
			{
				LAST_KEY=THIS_KEY;
				THIS_KEY=KEY;
				if((1 == LAST_KEY)&&(0 == THIS_KEY))  
				{
					sound_1();
					break;
				}   
			}
			LED = 1;    //放音结束,熄灭放音指示灯
			isd_stop();
			if(chk_isdovf()) break;
			while(1 == PLAY)
			{
				if(0 == STOP) break; //按一下STOP按键,结束放音过程
				if(0 == PLAY) delay_ms(20);
			}
		}while(0 == PLAY);
	}
isd_stop();
isd_pd();
}

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -