C51模拟PS2键盘(四)

*************************************************************************************

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。

否则将追究法律责任。http://blog.csdn.net/fulinus/article/details/15138735

*************************************************************************************

C51模拟PS2键盘程序,这是PS2协议程序头文件文件:

#ifndef __PS_2_H__
#define __PS_2_H__

#define PS2_DAT_H		1
#define PS2_DAT_L		0
#define PS2_CLK_H		1
#define PS2_CLK_L		0

sbit PS2_CLK = P0^0;
sbit PS2_DAT = P0^1;

void PS2_Send(unsigned char ch);

unsigned char PS2_Rece(void);

unsigned char PS2_Response(void);

void MCU_To_PC(unsigned char Key_num);

//void key_send(unsigned char key_value);

//unsigned int key_scan(void);

#endif


这是PS2协议程序C文件文件:

#include <C8051F310.h>                 // SFR declarations

#include "PS_2.h"
#include "delay.h"
#include "Initialize.h"


//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : 
//
// This function 
//
//
//
//-----------------------------------------------------------------------------

void PS2_Send(unsigned char ch)			                                            
{
	unsigned char i,temp,char_temp;
	unsigned char odd_flag=1;		//if odd_flag is 1,then odd is true ,else is flase
	
	temp=ch;
	for(i=0;i<8;i++)   				//find the number of 1 in this uchar x iS odd or not
	{
		char_temp=temp&0x01;  			//奇效验,找出发送的数据中1的个数,如果为偶数,则置标志位为1,反之为0
		if(char_temp==0x01)
		{ 
		 	odd_flag=!odd_flag;
		}
		temp=temp>>1;
	}
	temp=ch;
	char_temp=0;
	while(!PS2_CLK)
	{
		Delay_us(20);	
	}	 
	
	PS2_DAT = PS2_DAT_L;   //start bit 0	
    Delay_us(18); //从时钟脉冲的上升沿到一个数据转变的时间至少要有5微秒
	PS2_CLK = PS2_CLK_L;
	Delay_us(35);
	
	for(i=0;i<8;i++)   //send 8 bits LSB first
	{
		PS2_CLK = PS2_CLK_H;
		Delay_us(13); 	//从时钟脉冲的上升沿到一个数据转变的时间至少要有5微秒
		char_temp=temp&0x01;
		if(char_temp==0x01)
			PS2_DAT = PS2_DAT_H;
		else
			PS2_DAT = PS2_DAT_L;
		char_temp = 0;
		Delay_us(22);
		PS2_CLK = PS2_CLK_L;
		Delay_us(36);
		temp=temp>>1;
	}
	PS2_CLK = PS2_CLK_H;
	Delay_us(13); 	//从时钟脉冲的上升沿到一个数据转变的时间至少要有5微秒
	PS2_DAT = odd_flag;  //send odd bit   
	Delay_us(22);
	PS2_CLK = PS2_CLK_L;
	Delay_us(36);

	PS2_CLK = PS2_CLK_H;  //send stop bit									   
	Delay_us(13); 	//从时钟脉冲的上升沿到一个数据转变的时间至少要有5微秒
	PS2_DAT = PS2_DAT_H; 
	Delay_us(22);
	PS2_CLK = PS2_CLK_L;
	Delay_us(36);

	PS2_CLK = PS2_CLK_H;
}

//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
//
// Return Value : 
// Parameters   : 
//
// This function 
//
//
//
//-----------------------------------------------------------------------------

unsigned char PS2_Rece(void)
{
	unsigned char i,dat=0x00; 
	unsigned char ParityBit,oddSum=0; //数据校验计数器 
	if(!PS2_DAT)
	{
		Delay_us(10);
		if(PS2_DAT) return 0xCC;

		while(!PS2_CLK);
		Delay_us(40);
		PS2_CLK = PS2_CLK_L;
		for(i=0;i<8;i++)			//read 8bit
		{
			Delay_us(35);
			PS2_CLK = PS2_CLK_H;          
			Delay_us(36);
			PS2_CLK = PS2_CLK_L; 
			dat=dat>>1; 
			if(PS2_DAT)
			{
				dat|=0x80; 
				oddSum++;            //校验位计数器 
			} 
			Delay_us(15);    	
		}
		
		Delay_us(35);
		PS2_CLK = PS2_CLK_H;       
		Delay_us(36);
		PS2_CLK = PS2_CLK_L; 
		if(PS2_DAT)
			ParityBit=1;  //奇偶效验
		else 
			ParityBit=0;    
	
		Delay_us(35);
		PS2_CLK = PS2_CLK_H; 
		Delay_us(36);
		PS2_CLK = PS2_CLK_L; 
		if(!PS2_DAT)			//数据线仍旧为0吗
			return 0xCC;
		
		Delay_us(15);
		PS2_DAT = PS2_DAT_L;            
		Delay_us(20);
		PS2_CLK = PS2_CLK_L;	//STOP BIT H_DATA 0 ERR
		Delay_us(36);
		PS2_CLK = PS2_CLK_H;	//ACK bit
	
		
		Delay_us(15);
		PS2_DAT = PS2_DAT_H;
								
		oddSum += ParityBit; 	//数据位中1的个数加上校验为应为奇数
		if(oddSum%2==0) 
			return 0xCC;	
		else 
			return dat;	
	}
	else
		return 0xCC;		
}

//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
//
// Return Value : 
// Parameters   : 
//
// This function 
//
//
//
//-----------------------------------------------------------------------------
unsigned char PS2_Response(void)                        //开机应答,使电脑能识别到键盘                
{ 
	unsigned char PS2RecChar; 

	//while(PS2RecChar != 0xFF)
	PS2RecChar = PS2_Rece();

	if(PS2RecChar != 0xCC)
		switch(PS2RecChar)
		{
			Delay_ms(4);
			case 0xFF: 			//主机命令设备复位(0xff),设备必须应答0xfa后回复0xaa;
					PS2_Send(0xFA);
					Delay_ms(3);
					PS2_Send(0xAA);
					
					break;
			case 0xF2:	 // 主机请求获得设备ID命令(0xf2),设备必须应答0xfa后回复0xab,0x83; 
					PS2_Send(0xFA);
					Delay_ms(3);
					PS2_Send(0xAB);
					Delay_ms(3);
					PS2_Send(0x83);
//					LED = 1;
					break;
			case 0xEE:		//主机ECHO命令(0xee),设备直接回复0xee; 
					PS2_Send(0xEE);
					
					break;
			case 0xEF:
					PS2_Send(0xFA);
					Delay_ms(3);
					PS2_Send(0xBF);
					Delay_ms(3);
					PS2_Send(0xB0);
					break;
			//除以上命令之外的其它命令,设备只要回复0xfa即可,当然要视设备的功能作相应的动作。 
			/*case 0xF5:
					PS2_Send(0xFA);
					break;*/
			case 0xF3:
					PS2_Send(0xFA);
					break;
			case 0x00:
					PS2_Send(0xFA);
					break;
			case 0x02:
					PS2_Send(0xFA);
					break;
			case 0x20:
					PS2_Send(0xFA);
					break;
			case 0xED:
					PS2_Send(0xFA);
					break;
			case 0xF0:
					PS2_Send(0xFA);
					break;
			case 0xEC:
					PS2_Send(0xFE);
					break;	
			case 0xFE:
					PS2_Send(0xFA);
					break;
			case 0xF1:
					PS2_Send(0xFA);
					break;
			case 0xF4:
					PS2_Send(0xFA);
					break;
			case 0xAA:
					PS2_Send(0xAA);
					break;
			default  :break;
		}
	Delay_ms(4);
	return PS2RecChar;
	
}
//-----------------------------------------------------------------------------
// 
//-----------------------------------------------------------------------------
//
// Return Value : 
// Parameters   : 
//
// This function 
//
//
//
//-----------------------------------------------------------------------------
/*
void MCU_To_PC(unsigned char Key_num) 
{
	switch(Key_num)
	{
	     case 1:	 //'f'
			   PS2_Send(0x2B);
			   Delay_ms(60);
			   break;
		 case 2:	//L ARROW
			   PS2_Send(0xE0);
			   Delay_ms(4);
			   PS2_Send(0x6B);
			   Delay_ms(60);
			   break;
		case 3:	 //'Enter'
			   PS2_Send(0x5A);
			   Delay_ms(60);
			   break;
	     default: 
		 		break;
	}
}
*/

*************************************************************************************

C51模拟PS2键盘(三):原文链接

程序包的位置在这里

*************************************************************************************




你可能感兴趣的:(C51模拟PS2键盘,PS2协议,PS2键盘)