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

📄 ps2.c

📁 通过8x16键盘扫描模拟Ps2键盘通过测试成功 硬件:P1P2接16跟列扫描线 P0接8跟行线 P3.6=PS2_data P3.7=CLK INT0接DATA 修改扫描码就可用 绝对好用~~~
💻 C
字号:
#include <reg51.h>
#include "PS2.H"
#include <stdio.h>

BYTE PS2RecChar=0xCC;
BOOL KeyBoardFlag=FALSE;  			//scan code  
                  	 //	DB	0C0H,0F9H,0A4H,0B0H	;0-3 
		 			//	DB	099H,092H,082H,0F8H	;4-7 
          			//	DB	080H,090H,088H,083H	;8-B 
					//	DB	0A7H,0A1H,086H,08EH	;C-F 
unsigned int code SCANCODE[16][8]={ 0xe06b,0xe074,0xe075,0x23,0x3c,0x33,0x42,0x43,	    //1	行
									0x15,0xe074,0xe075,0xe06b,0xe072,0x3c,0x33,0x43,	//2	
									0x15,0xe074,0xe075,0xe06b,0xe072,0x3c,0x33,0x43,		//3	  
									0x15,0xe074,0xe075,0xe06b,0xe072,0x3c,0x33,0x43,    //4
					    		    0x15,0xe074,0xe075,0xe06b,0xe072,0x3c,0x33,0x43,		    //5
									0x15,0xe074,0xe075,0xe06b,0xe072,0x3c,0x33,0x43,    //6
									0x15,0xe074,0xe075,0xe06b,0xe072,0x3c,0x33,0x43,	        //7
									0x15,0xe074,0xe075,0xe06b,0xe072,0x3c,0x33,0x43,	   //8
									0x15,0xe074,0xe075,0xe06b,0xe072,0x3c,0x33,0x43,		   //9
									0x15,0xe074,0xe075,0xe06b,0xe072,0x3c,0x33,0x43,  //10
							        0x15,0xe074,0xe075,0xe06b,0xe072,0x3c,0x33,0x43,	    //11
									0x15,0xe074,0xe075,0xe06b,0xe072,0x3c,0x33,0x43, 	//12																				   
						 			0x15,0xe074,0xe075,0xe06b,0xe072,0x3c,0x33,0x43,		  //13
									0x15,0xe074,0xe075,0xe06b,0xe072,0x3c,0x33,0x43,   //14
					    			0x15,0xe074,0xe075,0xe06b,0xe072,0x3c,0x33,0x43,    	//15
									0x15,0xe074,0xe075,0xe06b,0xe072,0x3c,0x33,0x43,    //16																					   
					 																						   
					 
					 };
sbit P00=P0^0;
sbit P01=P0^1;
sbit P02=P0^2;
sbit P03=P0^3;
sbit P04=P0^4;
sbit P05=P0^5;
sbit P06=P0^6;
sbit P07=P0^7;
bit fillDogFlag;

void OnKeyBoardOnline(BOOL i)
{
	KeyBoardFlag=i;
}	
//---------------------------------------------------------------------------
void OnPS2ReceiveChar(BYTE ReceChar,BOOL P)
{
	BOOL ParityBit=0;
	ACC=ReceChar;
	CY=P;
	ParityBit=(BOOL)(CY?0x00:0x80);//奇校验位
	if(P==ParityBit);
	PS2RecChar=ReceChar;
}
//---------------------------------------------------------------------------
int OnPS2SendChar(BYTE dat)
{	int temp;
	BOOL ParityBit;
	BYTE i;
	ACC=dat;
	CY=P;
   
	ParityBit=(BOOL)(CY?0x00:0x80); //奇校验位
	
	
	CLSSIGNAL();

	CT_KB=OFF;
	EA=0;	//Int0 disable

	H_DATA=0;Delay10us();//start bit
	H_CLK=1;
	if(H_CLK==1)
	{
	Delay10us();
	H_CLK=0;
	Delay30us();
	
	for(i=0;i<8;i++)
	{
		if(dat&0x01==0x01){H_DATA=1;Delay10us();}
		else {H_DATA=0;Delay10us();}
		dat>>=1;
		H_CLK=1;
		Delay10us();
		H_CLK=0;
		Delay30us();
	}

	H_DATA=ParityBit;Delay10us();//parity bit
	H_CLK=1;
	Delay10us();
	H_CLK=0;
	Delay30us();

	H_DATA=1;Delay10us();//stop bit
	H_CLK=1;
	Delay10us();
	H_CLK=0;
	Delay30us();
	temp=0x0000;
	}
	else  temp=0xffff;// Pc封锁发送 发送失败 errcode 0xfff
	
	IE0=0; //  cls INt0 ID

	H_CLK=1;
	H_DATA=1;
	
	CT_KB=ON;  //大键盘闭合 pc clk  Data  连接大键盘
	Delay30us();
	 	EA=1;	// eanble int0
	return temp;
}



//---------------------------------------------------------------------------
void ExternInterrupt0(void) interrupt 0	
{
	BOOL ParityBit=0,CLKFlag=1;
	BYTE i=0,j=8,dat=0x00;

	EA=0;

	while(CLKFlag)
	{
		i++;
		if(H_CLK==1)CLKFlag=0;
		if(i>0xEE)
		{	printf("Rcv err At Flag\n");  
			IE0=0;
			EX0=1;
			return ;
		}
	} 
	//while(j--)//延时等待大键盘的动作
	//{
	//	for(i=0;i<0x88;i++)//检查是否有数据处理	0x88
	//	{
	//		if(H_CLK==0)//有动作则是大键盘存在
	//		{
	//			OnKeyBoardOnline(TRUE);//大键盘存在,开机由大键盘应答
	//			IE0=0;
	//			EX0=1;
	////			return ;//存在的话置标志位,并返回
	//		}
	//	}
	//}

	OnKeyBoardOnline(FALSE);//大键盘不存在,由小键盘应答

	
	//转到接收
	for(i=0;i<8;i++)//read 8bit
	{
		Delay30us();
		H_CLK=0;            
		Delay30us();
		H_CLK=1;
		dat=dat>>1; 
		if(H_DATA)dat|=0x80;
		 
		if(H_CLK==0){ printf("Rcv Err\n");	return ;	}//如果时钟被拉低,则有错误发生
	}
										 
	Delay30us();
	H_CLK=0;            
	Delay30us();
	H_CLK=1;
	if(H_DATA)ParityBit=1;
	else ParityBit=0; 

	Delay30us();
	H_CLK=0;            
	Delay30us();
	H_CLK=1;//STOP BIT H_DATA 0 ERR
	
	Delay10us();																					  
	H_DATA=0;	//ACK bit
	Delay10us();
	H_CLK=0;
	Delay30us();Delay30us();
	H_CLK=1;
	Delay30us();
	H_DATA=1;
	
	OnPS2ReceiveChar(dat,ParityBit); // 记录到PS2Recchar 中
	printf("RcvDat %x\n",(unsigned int)PS2RecChar);
	IE0=0;   //Cls Biao ji
	EA=1;		//允许中断
	return ;
}
//---------------------------------------------------------------------------
void ProcessPS2(void)
{	EA=0;
	if(PS2RecChar!=0xCC )//大键盘不存在
	{
		if(PS2RecChar==0xF3)//1
		{
			OnPS2SendChar(0xFA);
			PS2RecChar=0xCC;
		}
		else if(PS2RecChar==0x00)//11
		{
			OnPS2SendChar(0xFA);
			PS2RecChar=0xCC;
		}
		else if(PS2RecChar==0x02)//111
		{
			OnPS2SendChar(0xFA);
			PS2RecChar=0xCC;
		}
		else if(PS2RecChar==0x20)//1111
		{
			OnPS2SendChar(0xFA);
			PS2RecChar=0xCC;
		}
		else if(PS2RecChar==0xED)//2  0xED (Set/Reset LEDs) 主机在本命令后跟随一个参数字节用于指示键盘上Num Lock, Caps Lock,
								//  	and Scroll Lock LED 的状态这个参数字节的定义如下
		{
			OnPS2SendChar(0xFA);
			PS2RecChar=0xCC;
		}
		else if(PS2RecChar==0xF0) //3
		{
			OnPS2SendChar(0xFA);
			PS2RecChar=0xCC;
		}
		else if(PS2RecChar==0xF2)//4  *0xF2 (Read ID) 键盘回应两个字节的设备ID 0xAB 0x83
		{
			OnPS2SendChar(0xFA);
			Delay30us();
			OnPS2SendChar(0xAB);
			Delay30us();
			OnPS2SendChar(0x83);
			PS2RecChar=0xCC;
		}
		else if(PS2RecChar==0xEF)//5
		{
			OnPS2SendChar(0xFA);
			Delay30us();
			OnPS2SendChar(0xBF);
			Delay30us();
			OnPS2SendChar(0xB0);
			PS2RecChar=0xCC;
		}
		else if(PS2RecChar==0xF3) //6	主机在这条命令后会发送一个字节的参数来定义机打速率和延
		{
			OnPS2SendChar(0xFA);
			PS2RecChar=0xCC;
		}
		else if(PS2RecChar==0xFE)//7 //resend
		{
			PS2RecChar=0xCC;
		}
		else if(PS2RecChar==0xEE)//8
		{
			OnPS2SendChar(0xEE);
			PS2RecChar=0xCC;
		}
		else if(PS2RecChar==0xEE)//9
		{
			OnPS2SendChar(0xEE);
			PS2RecChar=0xCC;
		}
		else if(PS2RecChar==0xF1)//10
		{
			OnPS2SendChar(0xFA);
			PS2RecChar=0xCC;
		}
		else if(PS2RecChar==0xF4)//11 在用上一条命令禁止键盘后重新使能键盘
		{
			OnPS2SendChar(0xFA);
			PS2RecChar=0xCC;
		}
		else if(PS2RecChar==0xAA)//12
		{
			OnPS2SendChar(0xAA);
			PS2RecChar=0xCC;
		}
		else if(PS2RecChar==0xFF)//13 0xFF (Reset) 引起键盘进入Reset 模式见复位部分
		{	
			OnPS2SendChar(0xFA);
			Delay30us();
			OnPS2SendChar(0xAA);
			Delay30us();
			PS2RecChar=0xCC;
			fillDogFlag=0; 
			printf("Reset HardWare\n");

		}
		else { 
		printf("NC=%x",PS2RecChar);
		OnPS2SendChar(0xFA); PS2RecChar=0xCC;}
	}																								   
EA=1;							
}
//---------------------------------------------------------------------------
void PS2Init(void)
{
	IT0=0;	//低电平触发中断
	PX0=1;	
	EX0=1;
	EA=1;	
}
//---------------------------------------------------------------------------
//用法-以下文件在main.c--------------------------------------------------------------------------
//把PS2.C Delay.asm加入工程
extern void ProcessPS2(void);
extern void PS2Init(void);
sbit nLed1 = P2^2;
sfr WDT_CONTR = 0xe1;
bit temp,temp1;
 
char andbit;
unsigned int andbit2;
#ifdef MONITOR51                         /* Debugging with Monitor-51 needs   */
char code reserve [3] _at_ 0x23;         /* space for serial interrupt if     */
#endif                                   /* Stop Exection with Serial Intr.   */
                                         /* is enabled                        */
void main(void)			 
{	  int i=0; 
	  int j=0;	
	 char pdata Data[16],hsData[16],Data3[16];
	 bit keep; 
	 int k; 
	 char ScanH; 
	//晶振为18.432 其他的频率需要修改延时程序
	//往PC上发按键使用OnPS2SendChar();
	
  #ifndef MONITOR51
    SCON  = 0x50;		        /* SCON: mode 1, 8-bit UART, enable rcvr      */
    TMOD |= 0x20;               /* TMOD: timer 1, mode 2, 8-bit reload        */
    TH1   = 0xfb;                /* TH1:  reload value for 9600 baud @ 18.43MHz   */
    TR1   = 1;                  /* TR1:  timer 1 run                          */
    TI    = 1;                  /* TI:   set TI to send first char of UART    */
#endif
	 
	   //printf("Init PS2");
	   	PS2Init();
		
		OnPS2SendChar(0xaa); //BAT sucess
		//for(j=0;j<10;j++)
		for (i=0;i<500;i++)	 
		 { 				  
						// OnPS2SendChar(0x15);//Q//发送通码	
		 				 OnPS2SendChar(0xf0);//
						OnPS2SendChar(0x15);//Q//发送断码}
		                 ProcessPS2();
						 	OnPS2SendChar(0xaa);
						}
	   WDT_CONTR=0x3f ;//初始化看门狗
	   fillDogFlag=1;  //允许喂狗
while(1)					 	            
		
							
	{  
	
		
	  	//开机应答,使电脑能识别到键盘	
		//other code 			
	  // OnPS2SendChar(0xaa);//Q//发送通码		
	   ProcessPS2();
       if	(fillDogFlag==1)WDT_CONTR=0x3f;//喂狗

	  // nLed1=P00;
	 
	 
	  
 /* if(~P00)
	 { Delay30us();
	          if(~P00)

	   				{	OnPS2SendChar(0x15);//Q//发送通码
	                   keep =~P00;
					   while(keep)	keep =~P00;
					    Delay30us();
						 OnPS2SendChar(0xF0);//
						 OnPS2SendChar(0x15);//Q//发送断码}
						 
		                               //这段为单键扫描				 
						
					 }
			          
						
	} */
	andbit2=0x01;
for( j=0;j<16;j++)
  {	       
		    //设置P1口 某根线为低扫描 j行
			
			P1=~andbit2 &0x00ff;
			P2= (~andbit2 & 0xff00)>>8;
//	Delay30us();
//	Delay30us();      
	hsData[j]=Data[j];
	for(k=0;k<2;k++)Delay30us(); //等P0口稳定

	Data[j]=P0;
//	for(k=0;k<10;k++) Delay30us();
//	Data3[j]=P0;

//if(Data[j]==Data3[j])	//去抖动 P0 稳定了
//	{
	if(Data[j]!=hsData[j])
	{   for(k=0;k<3;k++);Delay30us(); //100us
		Data[j]=P0;   
		andbit=0x01;
	  	for(i=0;i<8;i++)
		{ 		   
				  ScanH=(SCANCODE[j][i]&0xff00)>>8;//
				  if((Data[j]^hsData[j])&andbit&Data[j])
					{ 	//key i release 
											
					 printf("Key %d %d UP\n",j,i); 
				
				   if(ScanH) OnPS2SendChar(ScanH);     //先发送高八位扫描码通码
					OnPS2SendChar(0xF0);             //													 
					OnPS2SendChar(SCANCODE[j][i]);//发送i键低八位断码}
					 }
			andbit<<=1;
		}								
		andbit=0x01;
		for(i=0;i<8;i++)	   
		{	      // key i 	push down
				 ScanH=(SCANCODE[j][i]&0xff00)>>8;//
			  	if((Data[j]^hsData[j])&andbit&~Data[j])
				 {		
				  printf("Key %d %d down\n",j,i);											   
				 if( ScanH ) OnPS2SendChar( ScanH );//先发送高八位扫描码通码
				 OnPS2SendChar(SCANCODE[j][i]);////发送i键通码}	
				  }
		 andbit<<=1;	
	     }			        
		  
		
	//		if(P00) { nLed1=0;	
	//		         }
	//	         else 
	//			 { nLed1=1; 	
				           }
		   
	 //} //end if 
 
 	 andbit2<<=1;
 	} //end for j																									
} //end while
	Delay30us();

	
	

			
 
}

⌨️ 快捷键说明

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