给你参考...
#include
#include
sbit PS2_DATA = P3^4; //PS2数据线
sbit PS2_CLK = P3^3; //PS2时钟线
sbit BEEP = P3^7; //蜂鸣器驱动线
bit flag;
bit break_code;
bit num_code;
bit esc_code;
#define NUMLOCK_CODE 0x77 //NumLock键码
#define ESC_CODE 0x76 //ESC键码
unsigned char TEMP,TEMP1,y;
unsigned char KeyCode; //键盘键值
unsigned char code TABLE_D[] = { //键值码
0x45,0x16,0x1e,0x26,0x25,0x2e,0x36,0x3d,0x3e,0x46, //0-9
0x1c,0x32,0x21,0x23,0x24,0x2b, //a-f
0x70,0x69,0x72,0x7a,0x6b,0x73,0x74,0x6c,0x75,0x7d,0xff }; //右边数字键0-9
unsigned char code TABLE_NUM[] = { //显示码
0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,
0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xff };
unsigned char IntNum = 0; /*中断次数计数*/
unsigned char BF = 0; /*标识是否有字符被收到*/
/*********************************************************
x*0.14ms延时函数
*********************************************************/
void delay(unsigned int x)
{
unsigned char i;
while(x--)
{
for (i=0; i<13; i++) ;
}
}
/**********************************************************
蜂鸣器驱动函数
**********************************************************/
void beep()
{
unsigned char i;
for (i=0;i<100;i++)
{
delay(5);
BEEP=!BEEP; //BEEP取反
}
BEEP=1; //关闭蜂鸣器
}
/*********************************************************
函数:SEND_DATA()
功能:向键盘发送命令
输入:命令
*********************************************************/
void SEND_DATA(unsigned char orderByte)
{
unsigned char k;
unsigned char check=0;
EA=0; //关闭总中断,发送命令到键盘
PS2_CLK = 0; //首先拉低时钟
PS2_DATA = 1; //置高数据
for(k=0xff; k!= 0; k--); //延时,抑制键盘发送
PS2_DATA = 0; //拉低数据,发送起始位
PS2_CLK = 1; //置高时钟,释放此线
for(k=8; k!= 0; k--) // 发送八位数据,循环八次
{
while(PS2_CLK); //等待PS2拉低时钟
if(orderByte & 0x01)
{
PS2_DATA = 1; // 根据低位设定输出数据
check ++; // 如果输出一个1,效验记录数据加一
}
else PS2_DATA = 0;
orderByte >>= 1; // 命令字调整
while(!PS2_CLK); // 输出脉冲
}
while(PS2_CLK); //等待PS2拉低时钟
if(check % 2)
{ // 如果输出过偶数个脉冲
PS2_DATA = 0; // 效验数据位置0
}
else
{
PS2_DATA = 1; // 否则数据位置1
}
while(!PS2_CLK); //发送效验位
while(PS2_CLK);
PS2_DATA = 1;
while(!PS2_CLK); // 发送终止位
PS2_DATA = 1;
PS2_CLK = 1;
while((PS2_CLK) | (PS2_DATA)); // 等待ACK握手信号
while(!PS2_CLK); //等待scl变高
EA=1; //开总中断
}
/*********************************************************
键码变换为显示码函数
*********************************************************/
void PS2KEY_NUM()
{
// unsigned char y;
switch (KeyCode)
{
case 0xF0 : // 当收到0xF0,表示断码开始
break_code=1;
break;
case 0x76 : // ESC键码
esc_code=1;
TEMP1= 0x86; //显示'E'
break;
case 0x77 : // NUM键码
num_code=1;
TEMP1=0xc8; //显示'n'
break;
default:
for(y=0 ;y<27 ;y++) //键值变换为顺序码
{
if(KeyCode==TABLE_D[y])
{
if((y>15) & flag)
{
break_code=0;
KeyCode=0x00;
return;
}
else
{
break_code=0;
TEMP1=TABLE_NUM[y];
beep() ; //查找有效,蜂鸣器响一声
delay(800);
KeyCode=0x00;
return;
}
}else //没有定义的键
{
break_code=0;
TEMP1=0xbf; //显示'-'
}
}
break;
} // end of switch (KeyCode)
if(break_code & num_code)
{
break_code=0;
num_code=0;
}
if(break_code & esc_code)
{
break_code=0;
esc_code=0;
}
}
/*********************************************************
主函数
*********************************************************/
void main()
{
P0 = 0xff;
P2 = 0xff;
TEMP1 = 0xbf; //显示'-'
flag = 1;
IT1 =0; //外部中断1为低电平触发
EA =1; //开总中断
EX1 =1; //开外部中断1
SEND_DATA(0xff); //键盘复位
while(1)
{
if(BF==1)
{
PS2KEY_NUM();
BF=0;
EA=1; //数据处理完毕开中断
}
P0 = TEMP1; //显示数据
P2 = 0X7f;
if((KeyCode==ESC_CODE) & esc_code) //Esc键码
{
beep();
esc_code=0;
}
if((KeyCode==NUMLOCK_CODE)& flag & num_code)
{
flag=0;
num_code=0;
SEND_DATA(0xED); //点亮NumLock
SEND_DATA(0x02);
beep();
}
else
{
if((KeyCode==NUMLOCK_CODE)&(!flag) & num_code)
{
flag=1;
num_code=0;
SEND_DATA(0xED); //熄灭NumLock
SEND_DATA(0x00);
beep();
}
}
} //end of while(1)
} // end of main()
/*********************************************************
外部中断函数
*********************************************************/
void ReadPS2() interrupt 2
{
while (PS2_CLK);
if ((IntNum >0) && (IntNum < 9)) //跳过起始位
{
KeyCode = KeyCode >> 1; //因键盘数据是低>>高
if (PS2_DATA)
KeyCode = KeyCode | 0x80; //当键盘数据线为1时为1到最高位
}
PS2_CLK=1;
IntNum++;
while (!PS2_CLK); //*等待PS/2CLK拉高
if (IntNum==11) //当中断11次后表示一帧数据收完
{
IntNum = 0; //清变量准备下一次接收
EA=0;
BF=1;
}
}
/*********************************************************/
取消
评论