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

📄 atkeyboard.c

📁 ps/2键盘处理程序
💻 C
字号:
//
//
//	键盘监控出来,每个位之间间隔约为315T,即高70us低70us
//	一个码发出总时间为3450T,约为1.5ms
//	键盘发出的码为:通码 + 断码
//	如数字1:16 (间145000T,约为62ms) F0 (间3250T,约为1.5ms) 16
//
//	即每发一个码了去后,即要等一个码的时间去检查主机是否有发送数据过来
//	通码与断码间
//	机打第一个间隔约为466303T,约为200ms;后每个隔约为59250T,约为26.6ms
//	最后断码同无机打模式一样

#include <REG52.H>
#include <string.h>
#include <INTRINS.H>
#include "ATKeyboard.H"

#define _DEBUG

#ifdef _DEBUG
#include "..\Debug\Debug.H"
#endif

//-------------------------IO Define---------------------------
sbit	Actual_Keyboard_CLK		=	P3^2;	//实际键盘时钟IO
sbit	Actual_Keyboard_Data	=	P3^4;	//实际键盘数据IO
sbit	Virtual_Keyboard_CLK	=	P1^1;	//虚拟键盘时钟IO
sbit	Virtual_Keyboard_Data	=	P1^2;	//虚拟键盘数据IO
sbit	Keyboard_Switch			=	P1^0;	//键盘切换控制IO
//-------------------------------------------------------------

typedef union BIT_CHAR_DATA
{
	struct _BIT_DATA
	{
		unsigned char Bit0:1;
		unsigned char Bit1:1;
		unsigned char Bit2:1;
		unsigned char Bit3:1;
		unsigned char Bit4:1;
		unsigned char Bit5:1;
		unsigned char Bit6:1;
		unsigned char Bit7:1;
	}Bits;
	unsigned char Value;
}BitCharData;

bit bKeyParityBit;						//奇偶校验位值
unsigned char data cKeyBufferBitCount;	//当前接收数据位计数
BitCharData bcRecKeyData;				//收到的键盘数据
sttKeyboardData stKeyboardData;			//键盘数据
extern void Delay50us(unsigned char _50us);
extern void Delay1ms(unsigned char _1ms);

//控制实际键盘通讯IO通断
//bit KeyboardType:键盘选择,ACTUAL_KEYBOARD-实际键盘,VIRTUAL_KEYBOARD-虚拟键盘
void SelectKeyboard(bit KeyboardType)
{
	Keyboard_Switch = KeyboardType;
}

//复位键盘监控
void ResetKeyboardMonitor()
{
	IT0 = 1;			// 设置外部中断0为边沿触发
	PX0 = 1;			// 设置外部中断0为高优先级
	cKeyBufferBitCount = 0;
	stKeyboardData.Length = 0;
	memset(stKeyboardData.cKeyBuffer,0,KEYBOARD_BUFFER_SIZE);
	bcRecKeyData.Value = 0;
}

void Keyboard_GetBit() interrupt 0   
{
	if(!Actual_Keyboard_CLK)
	{
		switch(cKeyBufferBitCount)
		{
		case 0:	//起始位
			if(Actual_Keyboard_Data) return;	//不是正确的起始数据
			cKeyBufferBitCount = 1;		//收到一位起始位
			bKeyParityBit = 1;			//初始为1
			break;
		case 1:
		case 2:
		case 3:
		case 4:
		case 5:
		case 6:
		case 7:
		case 8:	//数据位
			//保存当前位数据
			bcRecKeyData.Value >>= 1;	//准备接收下一位数据
			if(Actual_Keyboard_Data)
			{
				bcRecKeyData.Bits.Bit7 = 1; 
				bKeyParityBit ^= 1;	//计算校验值
			}
			break;
		case 9:		//奇偶校验位
			bKeyParityBit ^= Actual_Keyboard_Data;
			cKeyBufferBitCount ++;
			break;
		case 10:	//停止位
#ifdef _DEBUG
			DebugData(1,1,&bcRecKeyData.Value);
#endif
			cKeyBufferBitCount = 0;		//准备接收下一键码
			if(!Actual_Keyboard_Data) 	return;	//没收到正确的停止位
			if(bKeyParityBit) return;	//奇校验出错
			if(stKeyboardData.cKeyBuffer[stKeyboardData.Length] == bcRecKeyData.Value)
				return;			//收到的数据同上一次收到的值一样
			//若不一样,则保存当前键码
			//stKeyboardData.cKeyBuffer[stKeyboardData.Length++] = bcRecKeyData.Value;
		}
	}
}

void SendKeyCode(unsigned char KeyData)
{
	unsigned char rst;
	while(1)
	{
#ifdef _DEBUG
		DebugString("KeyData=");
		DebugData(1,1,&KeyData);
#endif
		rst = ATKeyboard_SendByte(KeyData);
#ifdef _DEBUG
		DebugString("rst=");
		DebugData(1,1,&rst);
#endif
		if(rst!=KEYBOARD_RESENT) return ;//除重响应0xFE外,其它均不理
	}
}

void SendKey(unsigned char KeyCode)
{
	StopMonitorKeyboard();		//关闭键盘监控
	SelectKeyboard(VIRTUAL_KEYBOARD);	//选取虚拟键盘
	SendKeyCode(KeyCode);		//发送通码
	Delay1ms(10);				//硬件越差的设备,这里的延时要越长
	SendKeyCode(KEYUP);			//发送断码
	SendKeyCode(KeyCode);		//这个码同前一个码只要间1.5ms即可,在接收ECHO里已经有这时长了
	SelectKeyboard(ACTUAL_KEYBOARD);	//选取实际键盘
	StartMonitorKeyboard();	//开键盘监控程序,接收数据
}

⌨️ 快捷键说明

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