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

📄 ps2键盘(at45db011).c

📁 键盘针对78键的键盘开发的针对PS2的程序
💻 C
📖 第 1 页 / 共 5 页
字号:
		}
		case 0x03:
		{
			while(Send_1Byte_To_PS2_Port(0xe0)==0) {}						//通码首字节
			while(Send_1Byte_To_PS2_Port(0xf0)==0) {}						//断码字节
			while(Send_1Byte_To_PS2_Port(0x7c)==0) {}
			while(Send_1Byte_To_PS2_Port(0xe0)==0) {}
			while(Send_1Byte_To_PS2_Port(0xf0)==0) {}
			while(Send_1Byte_To_PS2_Port(0x12)==0) {}						//通码下1个字节
			break;
		}
		default:
		{
			//while(Send_1Byte_To_PS2_Port(0x4a)==0) {}
			Key_Send_Buffer_PlacPoint=0;
			break;
		}
	}
}
//========================================放置键按下码================================================
void Find_OnKey_Position(unsigned char Key_SWitch)
{
	if(First_Key_Number[2]==Key_SWitch)
	{
		//Shift_Store_Data(&First_Key_Number[0],Key_SWitch);
		First_Key_Number[0]=First_Key_Number[1];			//如果当前按下键是上一次的继续,继续移位存放
		First_Key_Number[1]=First_Key_Number[2];
		First_Key_Number[2]=Key_SWitch;
		return;
	}
	else if(Second_Key_Number[2]==Key_SWitch)
	{
		//Shift_Store_Data(&Second_Key_Number[0],Key_SWitch);
		Second_Key_Number[0]=Second_Key_Number[1];
		Second_Key_Number[1]=Second_Key_Number[2];
		Second_Key_Number[2]=Key_SWitch;
		return;
	}
	else if(Third_Key_Number[2]==Key_SWitch)
	{
		//Shift_Store_Data(&Third_Key_Number[0],Key_SWitch);
		Third_Key_Number[0]=Third_Key_Number[1];
		Third_Key_Number[1]=Third_Key_Number[2];
		Third_Key_Number[2]=Key_SWitch;
		return;
	}
	
	else if((First_Key_Number[0]==0xff)&&(First_Key_Number[1]==0xff)&&(First_Key_Number[2]==0xff)			//如果该键未曾按下过,查找存放位置
		  &&(Second_Key_Number[0]==0xff)&&(Second_Key_Number[1]==0xff)&&(Second_Key_Number[2]==0xff)
		  &&(Third_Key_Number[0]==0xff)&&(Third_Key_Number[1]==0xff)&&(Third_Key_Number[2]==0xff))
	{
		//Shift_Store_Data(&First_Key_Number[0],Key_SWitch);
		First_Key_Number[0]=First_Key_Number[1];															//如果当前按下键是上一次的继续,继续移位存放
		First_Key_Number[1]=First_Key_Number[2];
		First_Key_Number[2]=Key_SWitch;
	}
	else if(((First_Key_Number[0]!=0xff)||(First_Key_Number[1]!=0xff)||(First_Key_Number[2]!=0xff))			//如果该键未曾按下过,查找存放位置
		  &&(Second_Key_Number[0]==0xff)&&(Second_Key_Number[1]==0xff)&&(Second_Key_Number[2]==0xff)
		  &&(Third_Key_Number[0]==0xff)&&(Third_Key_Number[1]==0xff)&&(Third_Key_Number[2]==0xff))
	{
		//Shift_Store_Data(&Second_Key_Number[0],Key_SWitch);
		Second_Key_Number[0]=Second_Key_Number[1];															//如果当前按下键是上一次的继续,继续移位存放
		Second_Key_Number[1]=Second_Key_Number[2];
		Second_Key_Number[2]=Key_SWitch;
	}
	else if((((First_Key_Number[0]!=0xff)||(First_Key_Number[1]!=0xff)||(First_Key_Number[2]!=0xff))		//如果该键未曾按下过,查找存放位置
		  &&((Second_Key_Number[0]!=0xff)||(Second_Key_Number[1]!=0xff)||(Second_Key_Number[2]!=0xff)))
		  &&(Third_Key_Number[0]==0xff)&&(Third_Key_Number[1]==0xff)&&(Third_Key_Number[2]==0xff))
	{
		//Shift_Store_Data(&Third_Key_Number[0],Key_SWitch);
		Third_Key_Number[0]=Third_Key_Number[1];							//如果当前按下键是上一次的继续,继续移位存放
		Third_Key_Number[1]=Third_Key_Number[2]; 
		Third_Key_Number[2]=Key_SWitch;
	}
}

//========================================放置键释放码================================================
void Find_OffKey_Position(unsigned char Key_SWitch)
{
	if((First_Key_Number[0]==Key_SWitch)||(First_Key_Number[1]==Key_SWitch)||(First_Key_Number[2]==Key_SWitch))
	{
		//Shift_Store_Data(&First_Key_Number[0],0xff);
		First_Key_Number[0]=First_Key_Number[1];
		First_Key_Number[1]=First_Key_Number[2];
		First_Key_Number[2]=0xff;
	}
	else if((Second_Key_Number[0]==Key_SWitch)||(Second_Key_Number[1]==Key_SWitch)||(Second_Key_Number[2]==Key_SWitch))
	{
		//Shift_Store_Data(&Second_Key_Number[0],0xff);
		Second_Key_Number[0]=Second_Key_Number[1];
		Second_Key_Number[1]=Second_Key_Number[2];
		Second_Key_Number[2]=0xff;
	}
	else if((Third_Key_Number[0]==Key_SWitch)||(Third_Key_Number[1]==Key_SWitch)||(Third_Key_Number[2]==Key_SWitch))
	{
		//Shift_Store_Data(&Third_Key_Number[0],0xff);
		Third_Key_Number[0]=Third_Key_Number[1];					//这条指令占用3个字节
		Third_Key_Number[1]=Third_Key_Number[2];
		Third_Key_Number[2]=0xff;									//这条指令占用3个字节
	}
}

//=====================================移位存数函数===================================
//注意:创建这个函数需要40个字节,很不划算。
/*
void Shift_Store_Data(unsigned char *StoreAddr,unsigned char StoreData)
{
	StoreAddr[0]=StoreAddr[1];
	StoreAddr[1]=StoreAddr[2];
	StoreAddr[2]=StoreData;
}
*/
//========================装载键定义处理函数=======================================================
//返回值说明:
//	0x0  = 无键定义
//	0x1  = 有键定义且是单字节单键				须发断码
//	0x2  = 有键定义且是双字节单键				须发断码
//	0x3  = 有键定义且是四字节Prnt Scrn单键		须发断码
//  0x4  = 有键定义且是Pause单键或复合建		不发断码

unsigned char Load_TKey_Define(unsigned char Key_Num)
{
	unsigned char i;
	unsigned char k;
	
	ReadOnePageToBuffer(Key_Num);											//读该键的定义码到Buffer2,整页读
					
	k=ReadByteFromBuffer(0x00);

	if(k==0xe0)																//如果是0xe0打头
	{
		Nop_Key_Flag=1;														//有键
		
		for(i=1;;)
		{
			k=ReadNextFromBuffer();
			
			if((k==0)||(k==0xff))  break;
			i++;			
		}
		SPI45DB041_CS=1;
		
		if(i==1)
		{
			Nop_Key_Flag=0;
			return(0x00);													//错误键定义
		}
		else if(i==2)
		{
			 Key_Send_Buffer_PlacPoint=0;
			 return(0x02);													//如果是0xe0打头且只是2个字节,说明是			 
																			//双字节特殊功能键,释放时须发断码
		}
		else if(i==4)
		{
			k=ReadByteFromBuffer(0x01);
			SPI45DB041_CS=1;
			if(k!=0x12)
			{
				Key_Send_Buffer_PlacPoint=i;
				return(i);
			}
			k=ReadByteFromBuffer(0x02);
			SPI45DB041_CS=1;
			if(k!=0xe0)
			{
				Key_Send_Buffer_PlacPoint=i;
				return(i);
			}
			k=ReadByteFromBuffer(0x03);
			SPI45DB041_CS=1;
			if(k!=0x7c)
			{
				Key_Send_Buffer_PlacPoint=i;
				return(i);
			}
			return(0x03);
		}
		
		else
		{
			Key_Send_Buffer_PlacPoint=i;
			return(0x04);													//
		}
	}
	
	else if((k==0)||(k==0xff))
	{
		SPI45DB041_CS=1;
		Nop_Key_Flag=0;
		return(0x0);														//说明无键定义
	}
	
	Nop_Key_Flag=1;															//有键
		
	for(i=1;;)
	{
		k=ReadNextFromBuffer();
		if((k==0)||(k==0xff))  break;
		i++;			
	}
	SPI45DB041_CS=1;
	
	if(i==1)  return(0x01);
	else
	{		
		Key_Send_Buffer_PlacPoint=i;
		return(0x04);
	}
}

//========================蜂鸣器鸣响启动函数=======================================================
void Drived_Buzz(unsigned int HLen)
{
	Buzz_Rs232_Flag=1;					//设为Buzz模式
	Buzz_Timer=0;						//这个定时就取T1中断的次数,因为T0已经关闭
	
	TR0=0;
	TR1=1;
	
	while(Buzz_Timer<HLen) {}			//经过测定,所用蜂鸣器在f=3.125KHz时比较合适,这个值已反复调试,勿改
										//示波器测得f=3.125KHz
	
	TR1=0;
	TR0=1;	
	
	BUZZ=1;
	Buzz_Rs232_Flag=0;
	Buzz_Timer=0;
}
//========================上电/复位初始化键盘======================================================
void Ini_KeyBoard(void)
{
	unsigned char k;
	
	ReadOnePageToBuffer(SYSTEM_PARA_PAGE_FLASH);
	k=ReadByteFromBuffer(KEYCODED_TABLE);
	SPI45DB041_CS=1;
		
	if(k==0x0)	Keycoded_Table=0;
	else Keycoded_Table=1;
	
	System_Status_Reg=(~ReadByteFromBuffer(SYSYTEM_STATUS_BYTE));
	SPI45DB041_CS=1;	
}

//============================限时读PS2口=========================================================
//规定时间内读到返回1,没读到返回0
bit TRead_PS2_Port(unsigned char RDPS2Time)
{	
	Code_Reci_Data_Timing=0;	
	while(1)
	{
		if(PS2_RXD==0)  break;
		if(Code_Reci_Data_Timing > RDPS2Time)  return(0);		
	}
	
	if(Read_PS2_Port()==0)   return(0);	
	
	return(1);													//		
}
//========================从PS2口读一个字节========================================================
//正确读到数据时返回1,数据在Key_Reciver_Buffer中
//
bit Read_PS2_Port(void)
{
	bit cp;
	
	unsigned char i;
		
	cp=0;
	i=0;
	
	//while(PS2_RXD==1)													//等待主机拉低数据线提出发送请求
	
	while(PS2_TXD==0) {}												//等待主机释放时钟线
	
	//开始读
	TR0=0;
			
	Delay_uS_Time(15);													//维持高40微妙
	
	for(i=0;i<8;i++)
	{
		Key_Reciver_Buffer=Key_Reciver_Buffer>>1;
		
		PS2_TXD=0;														//拉低时钟,主机发送第1个数据位
		Delay_uS_Time(15);												//维持低电平40微妙	
		PS2_TXD=1;														//拉高通告主机,设备已读取数据
		if(PS2_RXD==1) Key_Reciver_Buffer=(Key_Reciver_Buffer|0x80);	//读数据位
		if(Check_PC_Cancle_Send()==0)
		{
			TR0=1;
			return(0);
		}
	}
		
	PS2_TXD=0;												//拉低时钟,主机发送校验位
	Delay_uS_Time(15);										//延迟20微妙	
	PS2_TXD=1;
	if(PS2_RXD==1) cp=1;									//读校验位
	ACC=Key_Reciver_Buffer;
	if(P!=(!cp))							
	{
		TR0=1;
		return(0);
	}	
	if(Check_PC_Cancle_Send()==0)
	{
		TR0=1;
		return(0);
	}
		
	PS2_TXD=0;
	Delay_uS_Time(15);									//延迟20微妙	
	PS2_TXD=1;		
	if(PS2_RXD==0)							//等待主机拉高数据线,实际上是读停止位
	{
		TR0=1;
		return(0);
	}		
			
	Delay_uS_Time(7);
			
	PS2_RXD=0;								//送应答ACK位
			
	Delay_uS_Time(7);						//延迟40微妙
						
	PS2_TXD=0;
	Delay_uS_Time(15);						//延迟40微妙
	PS2_TXD=1;								//释放时钟线
	PS2_RXD=1;								//释放数据线
	
	while(PS2_RXD==0)
	{
		//PS2_TXD=0;
		//Delay_uS_Time(15);
		//PS2_TXD=1;									//继续发脉冲等待主机释放时钟线
		//Delay_uS_Time(15);
	}
	
	TR0=1;
	Delay_uS_Time(30);
	
	return(1);
}

//高点平期间检查主机是否放弃传送,放弃返回0
bit Check_PC_Cancle_Send(void)
{
	unsigned char i;
	for(i=0;i<19;i++)
	{
		if(PS2_TXD==0) return(0);
	}
	return(1);
}

//========================发送一个字节到PS2口======================================================
//A发送成功返回1,失败返回0
//=================================================================================================
bit Send_1Byte_To_PS2_Port(unsigned char SendData)
{
	bit cp=0;
	unsigned char i;
	unsigned char h;
	
	WDT_CONTR=0x37;
	
	h=SendData;
	Last_Send_To_Ps2_Word=h;											//保存发送的字节以便重发
	
	if((PS2_TXD==1)&&(PS2_RXD==1))
	{
		TR0=0;															//关闭定时器,以免影响时序
		
		PS2_RXD=0;
		Delay_uS_Time(7);												//
		
		ACC=h;
				
		if(P==0) cp=1;													//如果数据位中包含偶数个1 校验位就会置1 如果数据位中
																		//包含奇数个1 校验位就会置0 数据位中1 的个数加上校验
																		//位总为奇数这就是奇校验这是用来错误检测
		else cp=0;
		/*
		Code_Reci_Data_Timing=0;	
		while(1)
		{		
			if((PS2_TXD==1)&&(PS2_RXD==1))  break;
			if((Code_Reci_Data_Timing>20)||(PS2_RXD==0)||(PS2_TXD==0))
			{
				return(0);												//20毫秒内主机无反应返回失败
			}
		}
		*/
		//PS2_RXD=0;
		
	
		Send_1Bit_To_PS2_Port(0x00);									//发送起始位
		
		for(i=0;i<8;i++)
		{
			Send_1Bit_To_PS2_Port(h);									//发送8位数据		
			h=h>>1;		
		}
					
		if(cp==0) Send_1Bit_To_PS2_Port(0x0);							//发校验位
		else Send_1Bit_To_PS2_Port(0x01);						
		
		Send_1Bit_To_PS2_Port(0x01);									//发停止位
		
		TR0=1;
		
		Delay_uS_Time(50);												//
		return(1);
	}
	return(0);
}

//========================发送一个bit到PS2口======================================================
void Send_1Bit_To_PS2_Port(unsigned char Send_Bit)
{	
	if((Send_Bit&0x01)!=0) PS2_RXD=1;
	else PS2_RXD=0;
	_nop_();
	PS2_TXD=0;
	Delay_uS_Time(14);									//延迟40微妙
	PS2_TXD=1;
	Delay_uS_Time(12);
}

/********************************************************\
*	函数名:SPI45D041_ReadByte
	作用域:本文件调用
*	功能:  SPI_SCK下降沿数据有效,读一个字节数据
*	参数:  无
\********************************************************/
unsigned char SPI45D041_ReadByte(void)
{
	unsigned char count,byte;
	for(count=0;count<8;count++)
	{
		SPI45DB041_SCK=1;
		byte<<=1;
		SPI45DB041_SCK=0;
		if(SPI45DB041_SO) byte++;
	}
	return(byte);	
}

/********************************************************\
*	函数名:SPI45D041_WriteBits
	作用域:本文件调用
*	功能:  对一个int型的数据(16位)依次右移,并放在FLASH的输入脚上
*	参数:  byte 		一个int的数
			num_of_bits	针对上面的int型的数据,依次向右移出的bit数
*	返回值:无
	SPI_SCK上升沿数据有效
	针对bit的数据操作:通过SI口,写入一个字节的多少bit
\********************************************************/

void SPI45D041_WriteBits(unsigned int byte,unsigned char num_of_bits)
{

⌨️ 快捷键说明

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