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

📄 hello.c

📁 运用protel设计简单ps2协议键盘,涉及单片机编程
💻 C
字号:
/*------------------------------------------------------------------------------
KB.C
说明:此程序为一简单键盘模拟程序.适用于8051系列单片机
     扫描码标准为国际第二通用扫描码,无任何粘连键及扩展键.
Copyright 2006 chuangxin
------------------------------------------------------------------------------*/


                                  /* for the intended 8051 derivative         */

#include <stdio.h>                /* prototype declarations for I/O functions */
#include <AT89X51.h> 
#define CLK P1_2
#define DATA P1_1



unsigned char Code = 0x00;
int enCode =0;			          //按键扫描成功标记
int realse =0;
unsigned char error = 0;
unsigned char RCode = 0x00;
unsigned char test = 0;
/*-----------------------------------------------
			  函数声明部分

------------------------------------------------*/
void ScanCode();
void Delay10ms();
void SendByte(unsigned char a );
void KBClk();
void DelayNus(unsigned char i);
unsigned char RecieveByte();
unsigned char C_Command();
/*------------------------------------------------
The main C function.  Program execution starts
here after stack initialization.
------------------------------------------------*/
void main () {
  		                              //扫描码
  
  int Command = 0;					  //命令输出标志
 
  //TMOD = 0x61;//0x20;  //定时器1定时方式2
  SCON = 0x50;
  //TCON = 0x40;  //定时器1开始计数
  //TH0 = 65490/256;//0xD7;	  //计数32us 此位保存TL1初始值
 // TL0 = 65490%256;//0xD      //起动定时器
        CLK =1;
        DATA =1;
        P1_4 =0;
 SendByte(0xAA); 		 //键盘自检完毕

  
while (1) { 	
              if(C_Command()){
			    RCode =RecieveByte();
			  	  
			  switch(RCode){

			    case 0xF2:
				  SendByte(0xFA);
				  SendByte(0xAB);
				  SendByte(0x83);
				  break;
				case 0xEE:
				  SendByte(0xEE);
				  break;
				case 0x00:
				  SendByte(0xFA);
				  P1_4 = 1;     //关掉指示灯
				  break;
				case 0x02:
				  SendByte(0xFA);
				  P1_4 =0;		//打开指示灯
				  break;
				case 0xFF:
				  SendByte(0xFA);
				  SendByte(0xAA); 
				  break;
				case 0xFE:
				  SendByte(0xFA);
				  SendByte(Code);
				  break;
			    default:
				  SendByte(0xFA);
				  break;		 
			  }	   
		  } 
             
			 enCode = 0;
		if(CLK & DATA){  
			   ScanCode();
			  		
			  
			  if(enCode)
			    
			    {  
				 SendByte(Code);
				}
			  if(realse){
			   
			    SendByte(0xF0);
				SendByte(Code);
			
				realse = 0;
			  }	 
			    
			} 	   
    }
  

}
/*-----------------------------------------------
        unsigned char ScanCode()  
		说明:按键扫描函数
		参数:无
		返回:unsigned char
		功能:返回按键编码
------------------------------------------------*/
void ScanCode(){
    unsigned char i =0;
	Code = 0x1C;                             //A键的扫描码因为只用一个K3按键
	P3_4 = 1;
	if(P3_4 == 0){                            //如果有键按下
	 Delay10ms();                            //延时10ms
	 if(P3_4 == 0)							 //确定有键按下
	  {
	   enCode = 1;							 //可以发送数据了
	   
	    Delay10ms();						 //等待10ms让释放按键
	    realse = 1;
	   
	   }								 
	 else
	  return ;
	 }
	 return ;    
}

/*-----------------------------------------------
        void DelayNms()  
		说明:延时程序
		参数:无
		返回:无
		功能:延时
------------------------------------------------*/
void Delay10ms(){
	unsigned char dly1 = 1;
	unsigned char dly2 = 215;
	while(dly1++){
   		while(dly2++);
  }
}

void Delay40us(){
 unsigned char i;
 for(i = 59;i >0; i--);
}

void Delay20us(){
 unsigned char i;
 for(i = 30;i >0; i--);
}

void Delay50us(){
 unsigned char i;
 for(i = 74;i >0; i--);
}

void Delay5us(){
 unsigned char i;
 for(i = 8;i >0; i--);
}

void Delay15us(){
 unsigned char i;
 for(i = 23;i >0; i--);
}
/*-----------------------------------------------
         void KBClk()
		 说明:键盘时钟脉冲生成函数
		 参数:无
		 返回:无
		 功能:生成键盘时钟脉冲,高40us,低40us
------------------------------------------------*/
void KBClk() interrupt 1 using 1 {
unsigned int edgeCg = 1;
unsigned char a =1;
   CLK = !CLK;
  TH0 = 65490/256;//0xD7;	  //计数32us 此位保存TL1初始值
  TL0 = 65490%256;
}
/*-----------------------------------------------
        void SendByte(unsigned char ScanCode)  
		说明:键盘发送一个字节
		参数:unsigned char
		返回:无
		功能:键盘发送数据
------------------------------------------------*/
void SendByte(unsigned char scanCode){
   
    int i;
	int ood;
	CLK =1;
	 
     wait: while(!CLK);
		  
			                   //等待时钟为高
	      Delay50us();
		   if(!CLK)
	       goto wait;

	     if(!DATA)	              //数据线不为高就退出				    
	       return;
		  
		  Delay20us(); //延时20us
		  
		 
		  DATA =0;
		  Delay20us();//延时20us
		   if(!CLK)
	       return ; 			 //主机阻止发送
		  CLK =0;                 //输出起始位
		  Delay40us();//延时40us
		  CLK =1;
		  Delay20us();//延时20us
		 
		   
		 for(i = 0; i < 8; i++){  //循环输出八位数据
		 while(CLK){
           if(scanCode&0x01)
		     { DATA =1; ood++;}
		   else
		     DATA =0;
		
			scanCode >>=1;
			Delay20us();//延时20us
			if(!CLK)
	         return ; 			 //主机阻止发送
			CLK =0;
			Delay40us();//延时40us
			

		 }
		 CLK =1;             //输出脉冲
		 Delay20us();//延时20us
		
		 }                       //八位输出完毕
		 
         
		   if(ood%2)			 //奇校验位如果有偶数个1则输出为1
		     DATA = 1;
		   else
		     DATA =0;            //输出脉冲
		  Delay20us();//延时40us
		   if(!CLK)
	       return ; 			 //主机阻止发送
		   CLK =0;
		  Delay40us();//延时40us
		   CLK = 1;
		  Delay20us();//延时20us
	
		   DATA =1;  		 	 //输出结束位
		   Delay20us();//延时20us
		   CLK = 0;
		   Delay40us();//延时40us
		   CLK =1;
		   Delay20us();//延时20us
		  
		  	
		 Delay15us();            //延时30us
		 Delay15us();
		 
		 return;
		 

}
/*-----------------------------------------------
        unsigned char ReceieveByte()  
		说明:键盘接收一个字节
		参数:无
		返回:unsigned char
		功能:键盘接收数据
------------------------------------------------*/
unsigned char RecieveByte(){

  unsigned char recieveData =0x00;
  unsigned char i;
  unsigned char ood;
  unsigned char oodRight;
  
  while(!CLK);        //等待时钟为高
  
  if(DATA)			  //等待数据为低
   {return 0xfe;}
   
  /*DelayNus(30);      //延时20us
  CLK = 0;			// 将时钟线拉低
  DelayNus(59);      //延时40us
  CLK =1;			 //释放时钟线
  DelayNus(30);      //延时20us
  					 
  					 //接收起始位 */
  for(i = 0;i <8;i++){
   	Delay20us();      //延时20us
	CLK = 0;			// 将时钟线拉低
	Delay40us();      //延时40us
	CLK =1;			 //释放时钟线
	Delay20us();      //延时20us
	recieveData>>=1;
	/*读八位数据*/
	if(DATA){
	 recieveData = recieveData | 0x80;
	 ood++;
	}
	else
	 recieveData = recieveData &0x7F;
	if(!CLK)
	 return 0xfe; 
  }

 
  Delay20us();      //延时20us
  CLK = 0;			// 将时钟线拉低
  Delay40us();      //延时40us
  CLK =1;			 //释放时钟线
  Delay20us();      //延时20us
  					 
   if(ood == DATA)	
  	oodRight =1;
  else
    oodRight =0;	 //接收校验位
  if(!CLK)
	 return 0xfe; 

  Delay20us();      //延时20us
  CLK = 0;			// 将时钟线拉低
  Delay40us();      //延时40us
  CLK =1;			 //释放时钟线
  Delay20us();      //延时20us
  					 
 					  //接收结束位
  if(!DATA)
	 return 0xfe; 
	
  // if(!DATA)	 //如果数据线还为0高,等待主机拉高
//	return 0;    //发生了错误
	
	             //发送应答位
  Delay15us(); //延时15us
  DATA =0;		//把数据线拉低
  Delay5us();	//延时5us
  CLK =0;
  Delay40us(); // 延时40us
  CLK =1;
  Delay5us();   //延时5us
  DATA =1;	   
  
  
  /*检验校验位是否正确,不正确就产生一个错误*/
   if(!oodRight)
	   error = 1;
   
   Delay40us();   //延时45us  	
   Delay5us();
 return recieveData;
}
/*-----------------------------------------------
              unsigned char C_Command()
			   说明:判断主机是否要发送命令
		       参数:无
	       	   返回:unsigned char
		       功能:判断主机是否要发送命令
--------------------------------------------------*/
unsigned char C_Command(){
 DATA =1;
 CLK =1;
 if(!DATA)
  return 1;
 else
  return 0;
}

⌨️ 快捷键说明

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