📄 ps2_key.c
字号:
/****************************************Copyright (c)***************************************
**
/*-----------------------------------------文件信息------------------------------------------
**文 件 名:PS2_Key.C
**创 建 人:王胜
**日 期:2007年3月26日
**描 述:
** 本库函数实现了20键PS2键盘键值的解码和读取,将PS2CLOCK与P3.6连接,通过将外部中断6
** 设置为下降沿中断模式来捕抓PS2DATA中数据,从而实现PS2键值的解码,将解码得到的键值
** 通过全局变量PS2KeyVal带出以供外部使用,同时设定按键标志,将按键标志通过全局位变量
** PS2Key_sign供外部使用(PS2Key_sign=0无键按下,PS2Key_sign=1有键按下,键值存放在键
** 值变量PS2KeyVal中),同时将键值读取时的按键状态通过全局变量PS2KeyMessage带出供外部
** 使用;
** 将这两个文件复制到您的工程目录下,在主函数中使用头文件包含语句#include "PS2_Key.h"
** 同时在初始化话函数CPU_Init.C中使用头文件包含语句#include "PS2_Key.h"将中断6初始化
** 函数加入到系统初始化中即可;本C文件包括两个函数:
**
** INT6初始化函数:
** void INT6_Init(void);
**
** PS2键盘中断处理函数:
** void PS2_ISR (void) interrupt 18;
**
** 供外部使用的全局变量:
** bit PS2Key_sign=0; //按键标志
** unsigned char PS2KeyVal=0; //按键键值寄存变量
** unsigned char PS2KeyMessage=0; //按键键值状态变量,数值定义如下:
** 0x80--键值读取时按键已释放
** 0x40--按键为机打按键,机打模式下通码被不断发送
** 0x20--按键为多键按下模式,取最后一个按下键键值
**
** 外部硬件资源信息:
** sbit PS2DATA = P3^1;
** sbit PS2CLOCK = P3^6;
** 外部中断6 INT6-> P3^6;
********************************************************************************************/
#include <C8051f020.h>
#include "PS2_Key.h"
#define DEFPS2PUSHCOUNT 0x0A //长按时间
bit PS2Key_sign=0; //按键标志
struct Keyboard_Information
{
unsigned char PS2KeyCount; //脉冲计数
unsigned char PS2KeyExtFlage; //扩展键标志
unsigned char PS2KeyTemp; //键码移位记录器
unsigned char PS2KeyPopError; //出错类别
unsigned char PS2KeyPushCount;//长压键计数器
}PS2Buffers={0,0,0,0,0};
unsigned char PS2KeyVal=0; //按键键值寄存变量
unsigned char PS2KeyMessage=0;/*按键键值状态变量,数值定义如下:
0x80--键值读取时按键已释放
0x40--按键为机打按键,机打模式下通码被不断发送
0x20--按键为多键按下模式,取最后一个按下键键值*/
//20键PS2小键盘键码表(实际按键数为18个)
unsigned char code PS2TAB[18][2] =
{
0x70,'0', //0
0x69,'1', //1
0x72,'2', //2
0x7A,'3', //3
0x6B,'4', //4
0x73,'5', //5
0x74,'6', //6
0x6C,'7', //7
0x75,'8', //8
0x7D,'9', //9
0x79,'+', //加
0x7B,'-', //减
0x7C,'*', //乘
0x4A,'/', //除
0x77,'N', //NumberLock
0x66,'B', //Bksp
0x71,'.', //Del.
0x5A,'E', //Enter
};
/*****************************************************************************************************
**函数名称:INT6_Init()
**函数功能:外部中断6初始化,将外部中断设置为下降沿中断;
**入口参数:无
**出口参数:无
*****************************************************************************************************/
void INT6_Init(void)//中断6初始化
{
P3IF &= ~0x40;//清除INT6标志,中断6为下降沿中断方式
EIE2 |= 0x10; //使能外部中断6
}
/******************************************************************************************************
**函数名称:PS2_ISR()
**函数功能:PS2键盘中断处理,将处理得到的键值存放在外部变量PS2KeyVal中,按键状态存入变量PS2KeyMessage中;
**入口参数:无
**出口参数:无
******************************************************************************************************/
void PS2_ISR (void) interrupt 18 //PS2键盘中断处理函数
{
unsigned char i=0;
unsigned char key=0;//键值暂存变量
P3IF &= ~0x40;//清除中断6标志位
if (PS2Buffers.PS2KeyCount ==0)
{ //PS2起始位测试
if (!PS2CLOCK && !PS2DATA)
{ //低电平是起始位
if (PS2Buffers.PS2KeyExtFlage !=0xF0)
{
PS2Buffers.PS2KeyTemp =0;
PS2Buffers.PS2KeyExtFlage =0;
PS2Buffers.PS2KeyPopError =0;
}
PS2Buffers.PS2KeyCount++; //脉冲计数
}
else PS2Buffers.PS2KeyPopError =0xEB; //置键起始位错误号0xeb
}
else if (PS2Buffers.PS2KeyCount <9)
{ //PS2数据位
key =PS2Buffers.PS2KeyTemp; //取键盘缓冲区移位数据
key >>=1;
if (PS2DATA) key |=0x80;
PS2Buffers.PS2KeyTemp =key;
PS2Buffers.PS2KeyCount++; //脉冲计数
}
else if (PS2Buffers.PS2KeyCount ==9)
{ //PS2数据奇校验
ACC = PS2Buffers.PS2KeyTemp; //取键盘缓冲区移位数据(C51取偶校验位)
if (P != PS2DATA) PS2Buffers.PS2KeyCount++; //奇校验正确,脉冲计数
else
{//PSW.0为奇偶标志位,当ACC中个位和为奇数时该位为1
PS2Buffers.PS2KeyPopError =0xEC; //置键奇校验位错误号0xec
PS2Buffers.PS2KeyCount =0; //脉冲计数归零
}
}
else if (PS2Buffers.PS2KeyCount ==10)
{ //停止位
key = PS2Buffers.PS2KeyTemp; //取键盘缓冲区移位数据
PS2Buffers.PS2KeyCount =0; //脉冲计数归零
if (PS2DATA)
{ //高电平是停止位
if (key ==0xE0) //本次是扩展键
{PS2Buffers.PS2KeyExtFlage =0xE0;}//置扩展键标志(小键盘只有回车键)
else if (key ==0xF0)//本次是键断码,键释放
{PS2Buffers.PS2KeyExtFlage =0xF0;}//置键释放标志
else
{ //本次必为键值
if ((key ==0xAA) || (key ==0xFA)) PS2Buffers.PS2KeyPushCount = 0;//长压键计数器清零
else
{
PS2CLOCK =0;//阻止PS2键盘立即回送数据
PS2Buffers.PS2KeyPopError =0xAA;//出错码
for (i =0; i <18; i++)
{
if (key ==(PS2TAB[i][0])) //搜索匹配按键
{
key =PS2TAB[i][1];
if (PS2Buffers.PS2KeyExtFlage ==0xF0)//键释放
{
PS2Buffers.PS2KeyPushCount =0;//长压键计数器清零
PS2KeyMessage =0x80;//当前键值由释放按键得到
}
else
{
if (key !=PS2KeyVal)
{ //换了一个键
PS2Buffers.PS2KeyPushCount =0;//长压键计数器清零
PS2KeyMessage =0x20;//当前键值由多键按下,最后一个按键得到
}
else
{ //未换键,机打模式
PS2Buffers.PS2KeyPushCount++; //长压键计数器计数
if (PS2Buffers.PS2KeyPushCount >DEFPS2PUSHCOUNT)
{ //长压时间到
PS2KeyMessage =0x40; //存入当前键值并执行命令
PS2Buffers.PS2KeyPushCount =0; //长压键计数器清零
}
}
}
PS2KeyVal =key; //存入当前键值
PS2Key_sign =1;
PS2Buffers.PS2KeyTemp =0; //键码移位记录器
PS2Buffers.PS2KeyExtFlage =0; //扩展键标志
PS2Buffers.PS2KeyPopError =0; //键释放标志或出错码
break;
}
}//for循环出口
if (PS2Buffers.PS2KeyPopError)
PS2Buffers.PS2KeyPushCount =0; //长压键计数器清零
PS2CLOCK =1; //释放PS2时钟总线
}
}
}//得到停止位,完成键值处理
else PS2Buffers.PS2KeyPopError =0xed;//置停止位错误号0xed
}
else PS2Buffers.PS2KeyCount =0;//PS2键盘出错
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -