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

📄 ps2.c

📁 PS2 读取键盘数具,非常好的一个软件PCB
💻 C
字号:
#include "..\include\ps2.h"

/************************************
名称:Ps2Delay()
功能:键盘总线操作延迟
入口:无
出口:无
说明:
************************************/
void Ps2Delay(void)
{
	 asm("nop"); asm("nop");
}

/************************************
名称:D20uS()
功能:延迟20uS
入口:无
出口:无
说明:
************************************/
void D20uS(void)
{
	 unsigned char cnt;
	 for(cnt=0x04; cnt>0; cnt--)
		{;}
	 asm("nop"); asm("nop");
}

/************************************
名称:D50mS()
功能:延迟50mS
入口:无
出口:无
说明:
************************************/
void D50mS(void)
{
	 unsigned int cnt;
	 for(cnt=0x1380; cnt>0; cnt--)
		{;}
}

/************************************
名称:WaitCLK0()
功能:等待KEY_CLK=0
入口:无
出口:0->等待超时
	  1->CLK=0
说明:
************************************/
unsigned char WaitCLK0(void)
{
	 unsigned int cnt;
	 for(cnt=5000; cnt>0; cnt--)
	{
		 if(!KEY_CLK)
			break;
	}
	if(cnt==0)
		return(0);
	else
		return(1);
}

/************************************
名称:WaitCLK1()
功能:等待KEY_CLK=1
入口:无
出口:0->等待超时
	  1->CLK=1
说明:
************************************/
unsigned char WaitCLK1(void)
{
	 unsigned int cnt;
	 for(cnt=5000; cnt>0; cnt--)
	{
		 if(KEY_CLK)
			break;
	}
	 if(cnt==0)
		return(0);
	else
		return(1);
}

/************************************
名称:WaitCLK1_INT()
功能:等待KEY_CLK=1,中断专用
入口:无
出口:0->等待超时
	  1->CLK=1
说明:
************************************/
unsigned char WaitCLK1_INT(void)
{
	 unsigned int cnt;
	 for(cnt=5000; cnt>0; cnt--)
	 {
		 if(KEY_CLK)
			break;
	 }
	 if(cnt==0)
		return(0);
	 else
		return(1);
}

/******************************************
键盘端口初始化函数Ps2PortInit()
作用:端口初始化
入口:无;
出口:无;
*******************************************/
void Ps2PortInit(void)
{
	 KEY_CLK_DIR = 1;
	 KEY_DAT_DIR = 1;
	 KEY_CLK = 1;
	 KEY_DAT = 1;	 
}

/******************************************
读取键盘数据函数ReadPs2()
作用:读取一帧PS2数据
入口:无;
出口:返回键值,返回0数据无效;
*******************************************/
unsigned char ReadPs2(void)
{
	 	unsigned char keyval,cnt,parity;
	 	unsigned int temp;
	
		//读取起始信号
		if(KEY_CLK||KEY_DAT)
			return(0);

		//变量初始化
	 	keyval = 0;
	 	temp = 0;
	 	parity = 0;

		//读取9位数据
	 	for(cnt=9; cnt>0; cnt--)
		{
		 	if(WaitCLK1()==0)	//等待时钟为1
				return(0);      //超时退出
		 	if(WaitCLK0()==0)	//等待时钟为0
				return(0);      //超时退出	
		 	Ps2Delay();		    //总线延迟
		 	temp>>= 1;
		 	if(KEY_DAT)
			{
			 	temp|= 0x0100; 
			 	parity++;
			}
		 	else
				{temp&= 0xfeff;}
		}

		//读取停止位
	 	if(WaitCLK1()==0)	//等待时钟为1
			return(0);      //超时退出
	 	if(WaitCLK0()==0)	//等待时钟为0
			return(0);      //超时退出
	 	Ps2Delay();		    //总线延迟
	 	if(!KEY_DAT)	
			return(0); 	    //非法停止信号	

		//奇校验
	 	if(parity&0x01)
		{
		 	keyval = (unsigned char)(temp&0xff);
		 	return(keyval);
		}
	 	else
			return(0);	   //奇校验失败
}

/******************************************
数据发送函数SendPs2()
作用:发送一帧PS2数据
入口:待发送的数据;
出口:返回1发送成功,返回0发送失败;
*******************************************/
unsigned char SendPs2(unsigned char data)
{
	 	unsigned char cnt;
	 	unsigned char parity,temp;

		//时钟线状态检测
	 	if(WaitCLK1_INT()==0)
			return(0);
	 	D20uS();D20uS();
	 	if(!KEY_CLK)
			return(0);

		//数据线检测
	 	if(!KEY_DAT)//主机准备发送数据
		{
		 	return(0);
		}

		//数据发送准备
	 	KEY_DAT_DIR = 0;
	 	KEY_CLK_DIR = 0;
	 	cnt = 8;
	 	parity = 0;
	 	temp = data;
	
		//发送起始位
	 	KEY_DAT = 0;
	 	D20uS();
	 	KEY_CLK = 0;
	 	D20uS();D20uS();
	 	KEY_CLK = 1;
	 	D20uS();

		//发送数据
	 	for(; cnt>0; cnt--)
		{
		 	if(temp&0x01)
			{
			 	KEY_DAT = 1; 
			 	parity++;
			}
		 	else
				{KEY_DAT = 0;}
			D20uS();
		 	KEY_CLK = 0;
		 	D20uS();D20uS();
		 	KEY_CLK = 1;
		 	D20uS();
		 	temp>>= 1;
		}
	 
		//发送校验位
	 	if((parity&0x01) == 0)	
			{ KEY_DAT = 1; }
	 	else
			{ KEY_DAT = 0; }
	 	D20uS();
	 	KEY_CLK = 0;
	 	D20uS();D20uS();
	 	KEY_CLK = 1;
	 	D20uS();
	
		//发送停止位
	 	KEY_DAT_DIR = 1;
	 	D20uS();
	 	KEY_CLK = 0;
	 	D20uS();D20uS();
	 	KEY_CLK = 1;
	 	D20uS();
	 	KEY_CLK_DIR = 1;
	 
		//发送成功
	 	D50mS();
	 	return(1);
}

⌨️ 快捷键说明

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