📄 ps2.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 + -