吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 5748|回复: 5
收起左侧

[其他转载] 原创——20140812PS2键盘程序

[复制链接]
lizhirui 发表于 2014-12-10 13:03
这个程序是我当时写的,现在发出来
本程序基于STC12C5608AD,该程序实现了判定特殊按键,并且最终返回一系列数值,支持锁定键以及键盘灯主机发送数据到键盘:
1) 把时钟线拉低至少100微秒
2) 把数据线拉低
3) 释放时钟线
4) 等待设备把时钟线拉低
5) 设置/复位数据线发送第一个数据位
6) 等待设备把时钟拉高
7) 等待设备把时钟拉低
8) 重复 5-7步发送剩下的7 个数据位和校验位
9) 释放数据线
10) 等待设备把数据线拉低
11) 等待设备把时钟线拉低
12) 等待设备释放数据线和时钟线
PS2向主机:
1) 检测时钟线电平,如果时钟线为低,则延时50μs;
2) 检测判断时钟信号是否为高,为高,则向下执行,为低,则转到(1);
3) 检测数据线是否为高,如果为高则继续执行,如果为低,则放弃发送(此时PC机在向PS2设备发送数据,所以PS2设备要转移到接收程序处接收数据);
4) 延时20μs(如果此时正在发送起始位,则应延时40μs);
5) 输出起始位(0)到数据线上。这里要注意的是:在送出每一位后都要检测时钟线,以确保PC机没有抑制PS2设备,如果有则中止发送;
6) 输出8个数据位到数据线上;
7) 输出校验位;
8) 输出停止位(1);
9) 延时30μs(如果在发送停止位时释放时钟信号则应延时50μs);
按如下的过程发送单个位
1) 设置/复位数据
2) 延迟20 微秒
3) 把时钟拉低
4) 延迟40 微秒
5) 释放时钟
6) 延迟20 微秒

PS2通信数据帧格式:
1个起始位
总是逻辑0
8个数据位
(LSB)低位在前
1个奇偶校验位
奇校验
1个停止位
总是逻辑1
1个应答位
仅用在主机对设备的通讯中

主机向键盘的命令集:
0xFF (Reset)——引起键盘进入Reset 模式(见复位部分)。
0xFE (Resend)——用于只是在接收中出现的错误。键盘的响应就是重发送最后的扫描码或者命令回应给主机。但是0xFE绝不会作为Resend命令的回应而被发送。
● *0xFD (Set Key Type Make)——允许主机指定一个按键只发送通码。这个按键不发送断码或进行机打重复。指定的按键采用它的第三套扫描码。
● *0xFC (Set Key Type Make/Break)——类似于Set Key Type Make,只有通码和断码是使能的(机打被禁止了)。
● *0xFB (Set Key Type Typematic)——类似于前两条命令通码和机打是使能的,而断码被禁止。
● *0xFA (Set All Keys Typematic/Make/Break)——缺省设置所有键的通码、断码和机打重复都使能(除了Print Screen 键,它在第一套和第二套中没有断码)。
● *0xF9 (Set All Keys Make)——所有键都只发送通码;断码和机打重复被禁止。
● *0xF8 (Set All Keys Make/Break)——类似于前两条命令,除了机打重复被禁止外。
● *0xF7 (Set All Keys Typematic)——类似于前三条命令仅断码被禁止,通码和机打重复是使能的。
0xF6 (Set Default)——载入缺省的机打速率/延时(10.9cps/500ms),按键类型(所有按键都使能机打/通码/断码),以及第二套扫描码集。
0xF5 (Disable)——键盘停止扫描,载入缺省值键Set Default 命令,等待进一步指令。
0xF4 (Enable)——在用上一条命令禁止键盘后,重新使能键盘。
0xF3 (Set Typematic Rate/Delay)——主机在这条命令后会发送一个字节的参数来定义机打速率和延时,具体含义如表2.1、2.2所示。
表2.1  Repeat Rate
Bits0-4
Rate(cps)
Bits0-4
Rate(cps)
Bits0-4
Rate(cps)
Bits0-4
Rate(cps)
00h
2.0
08h
4.0
10h
8.0
18h
16.0
01h
2.1
09h
4.3
11h
8.6
19h
17.1
02h
2.3
0Ah
4.6
12h
9.2
1Ah
18.5
03h
2.5
0Bh
5.0
13h
10.0
1Bh
20.0
04h
2.7
0Ch
5.5
14h
10.9
1Ch
21.8
05h
3.0
0Dh
6.0
15h
12.0
1Dh
24.0
06h
3.3
0Eh
6.7
16h
13.3
1Eh
26.7
07h
3.7
0Fh
7.5
17h
15.0
1Fh
30.0
表2.2  Delay
Bits5-6
Delay(seconds)
00b
0.25
01b
0.50
10b
0.75
11b
1.00
● *0xF2 (Read ID)——键盘回应两个字节的设备ID,0xAB、0x83。
● *0xF0 (Set Scan Code Set)——主机在这个命令后发送一个字节的参数,是定键盘使用哪套扫描码集。参数字节可以是0x01、0x02或0x03分别选择扫描码集第一套、第二套或第三套。如果要获得当前正在使用的扫描码集,只要发送带0x00参数的本命令即可。
0xEE (Echo)——键盘用“Echo”0xEE 回应。
0xED (Set/Reset LEDs)——主机在本命令后跟随一个参数字节,用于指示键盘上Num Lock, Caps Lock,and Scroll Lock LED的状态这个参数字节的定义如下:
MSB                                                                          LSB
Always0
Always0
Always0
Always0
Always0
Caps Lock
Num Lock
Scroll Lock
○"Scroll Lock" - Scroll Lock LED off(0)/on(1)
○"Num Lock" - Num Lock LED off(0)/on(1)
○"Caps Lock" - Caps Lock LED off(0)/on(1)
*只是最初可用于PS/2 键盘。

程序如下:
#include "common.h"
#include "uart.h"
#define WAITTIME 10000
bit ext=0;
bit up=0;
bit shift=0,ctrl=0,alt=0,gui=0,lshift=0,lctrl=0,lalt=0,lgui=0,numlock=1,capslock=0,scrolllock=0;
sbit CLK=P1^6;
sbit DAT=P1^7;
unsigned char code UnShifted[61][2] = {
0x1C, 'a',
0x32, 'b',
0x21, 'c',
0x23, 'd',
0x24, 'e',
0x2B, 'f',
0x34, 'g',
0x33, 'h',
0x43, 'i',
0x3B, 'j',
0x42, 'k',
0x4B, 'l',
0x3A, 'm',
0x31, 'n',
0x44, 'o',
0x4D, 'p',
0x15, 'q',
0x2D, 'r',
0x1B, 's',
0x2C, 't',
0x3C, 'u',
0x2A, 'v',
0x1D, 'w',
0x22, 'x',
0x35, 'y',
0x1A, 'z',
0x45, '0',
0x16, '1',
0x1E, '2',
0x26, '3',
0x25, '4',
0x2E, '5',
0x36, '6',
0x3D, '7',
0x3E, '8',
0x46, '9',
0x0E, '`',
0x4E, '-',
0x55, '=',
0x5D, '\\',
0x29, ' ',
0x54, '[',
0x5B, ']',
0x4C, ';',
0x52, '\'',
0x41, ',',
0x49, '.',
0x4A, '/',
0x71, '.',
0x70, '0',
0x69, '1',
0x72, '2',
0x7A, '3',
0x6B, '4',
0x73, '5',
0x74, '6',
0x6C, '7',
0x75, '8',
0x7D, '9',
0x66, ' ',
0x5A, ' ',
};
unsigned char code Shifted[61][2] = {
0x1C, 'A',
0x32, 'B',
0x21, 'C',
0x23, 'D',
0x24, 'E',
0x2B, 'F',
0x34, 'G',
0x33, 'H',
0x43, 'I',
0x3B, 'J',
0x42, 'K',
0x4B, 'L',
0x3A, 'M',
0x31, 'N',
0x44, 'O',
0x4D, 'P',
0x15, 'Q',
0x2D, 'R',
0x1B, 'S',
0x2C, 'T',
0x3C, 'U',
0x2A, 'V',
0x1D, 'W',
0x22, 'X',
0x35, 'Y',
0x1A, 'Z',
0x45, '0',
0x16, '1',
0x1E, '2',
0x26, '3',
0x25, '4',
0x2E, '5',
0x36, '6',
0x3D, '7',
0x3E, '8',
0x46, '9',
0x0E, '~',
0x4E, '_',
0x55, '+',
0x5D, '|',
0x29, ' ',
0x54, '{',
0x5B, '}',
0x4C, ':',
0x52, '"',
0x41, '<',
0x49, '>',
0x4A, '?',
0x71, '.',
0x70, '0',
0x69, '1',
0x72, '2',
0x7A, '3',
0x6B, '4',
0x73, '5',
0x74, '6',
0x6C, '7',
0x75, '8',
0x7D, '9',
0x66, ' ',
0x5A, ' ',
};
void SendPS2(uchar dat)
{
uchar i=0;
bit chk=1;
CLK=0;
Delay(1);
DAT=0;
CLK=1;
while(CLK);
for(i=0;i<8;i++)
{
DAT=(dat>>i)&0x01;
if(((dat>>i)&0x01)==1)
{
chk=~chk;
}
while(!CLK);
while(CLK);
}
DAT=chk;
while(!CLK);
while(CLK);
DAT=1;
while(DAT);
while(CLK);
while((!DAT)||(!CLK));
}
uchar ReadPS2() reentrant
{
uchar result=0,i=0;
if(!CLK)
{
while(!CLK);//等待起始位发送完毕
for(i=0;i<8;i++)//LSB
{
while(CLK);//等待时钟线
result|=((uchar)(DAT)<<i);
while(!CLK);//等待释放时钟线
}
while(CLK);
while(!CLK);//校验位
while(CLK);
while(!CLK);//停止位
if(result==0xE0||result==0xE1)
{
ext=1;
while(CLK);
return ReadPS2();
}
else if(result==0xF0)
{
up=1;
while(CLK);
return ReadPS2();
}
return result;
}
return 0x00;
}
bit IsKey(bit e,bit u,uchar key,uchar key2)
{
return (e==ext)&&(u==up)&&(key==key2);
}
void SetKeyLed(uchar num,uchar caps,uchar scroll)
{
    SendPS2(0xED);
SendPS2(scroll|(num<<1)|(caps<<2));
Delay(10000);
}
void ClearControlKey()
{
ctrl=0;
alt=0;
shift=0;
gui=0;
lctrl=0;
lalt=0;
lshift=0;
lgui=0;
}
bit SetControlKey(uchar key)
{
if(IsKey(0,0,0x12,key))//L Shift
{
shift=1;
lshift=1;
}
else if(IsKey(0,1,0x12,key))//L Shift Up
{
shift=0;
lshift=0;
}
else if(IsKey(0,0,0x14,key))//L Ctrl
{
ctrl=1;
lctrl=1;
}
else if(IsKey(0,1,0x14,key))//L Ctrl Up
{
ctrl=0;
lctrl=0;
}
else if(IsKey(0,0,0x11,key))//L Alt
{
alt=1;
lalt=1;
}
else if(IsKey(0,1,0x11,key))//L Alt Up
{
alt=0;
lalt=0;
}
else if(IsKey(1,0,0x1F,key))//L GUI
{
gui=1;
lgui=1;
}
else if(IsKey(1,1,0x1F,key))//L GUI Up
{
gui=0;
lgui=0;
}
else if(IsKey(0,0,0x59,key))//R Shift
{
shift=1;
lshift=0;
}
else if(IsKey(0,1,0x59,key))//R Shift Up
{
shift=0;
lshift=0;
}
else if(IsKey(1,0,0x14,key))//R Ctrl
{
ctrl=1;
lctrl=0;
}
else if(IsKey(1,1,0x14,key))//R Ctrl Up
{
ctrl=0;
lctrl=0;
}
else if(IsKey(1,0,0x11,key))//R Alt
{
alt=1;
lalt=0;
}
else if(IsKey(1,1,0x11,key))//R Alt Up
{
alt=0;
lalt=0;
}
else if(IsKey(1,0,0x27,key))//R GUI
{
gui=1;
lgui=0;
}
else if(IsKey(1,1,0x27,key))//R GUI Up
{
gui=0;
lgui=0;
}
else if(IsKey(0,0,0x77,key))//NumLock
{
numlock=~numlock;
SetKeyLed(numlock,capslock,scrolllock);
ClearControlKey();
}
else if(IsKey(0,1,0x77,key))//NumLock Up
{
ClearControlKey();
}
else if(IsKey(0,0,0x58,key))//CapsLock
{
capslock=~capslock;
SetKeyLed(numlock,capslock,scrolllock);
ClearControlKey();
}
else if(IsKey(0,1,0x58,key))//CapsLock Up
{
ClearControlKey();
}
else if(IsKey(0,0,0x7E,key))//ScrollLock
{
scrolllock=~scrolllock;
SetKeyLed(numlock,capslock,scrolllock);
ClearControlKey();
}
else if(IsKey(0,1,0x7E,key))//ScrollLock Up
{
ClearControlKey();
}
else
{
return 0;
}
return 1;
}
void ResetKey()
{
SendPS2(0xFF);
Delay(20000);
}
uchar GetChar(uchar key,bit s)
{
uchar i=0;
if(s)
{
for(i=0;i<61;i++)
{
if(Shifted[0]==key)
{
return Shifted[1];
}
}
}
else
{
for(i=0;i<61;i++)
{
if(UnShifted[0]==key)
{
return UnShifted[1];
}
}
}
return 0x00;
}
void main()
{
uchar key=0,tmp=0;
Uart_Init();
CLK=1;
DAT=1;
Delay(10000);
ResetKey();
SetKeyLed(numlock,capslock,scrolllock);
while(1)
{
ext=0;
up=0;
key=ReadPS2();
if((key!=0x00)&&!SetControlKey(key))
{
SendData((uchar)lgui<<7|(uchar)lalt<<6|(uchar)lshift<<5|(uchar)lctrl<<4|(uchar)gui<<3|(uchar)alt<<2|(uchar)shift<<1|(uchar)ctrl);
SendData((uchar)ext|(uchar)up<<1|(uchar)numlock<<2|(uchar)capslock<<3|(uchar)scrolllock<<4);
SendData(key);  
}
}
}



免费评分

参与人数 1热心值 +1 收起 理由
284912933 + 1 热心回复!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

f378694339 发表于 2014-12-10 13:10
感谢分享 支持了 楼主
GA゛木子 发表于 2014-12-10 16:59 来自手机
pppszxc 发表于 2014-12-12 11:21
 楼主| lizhirui 发表于 2014-12-12 17:27 来自手机
就是单片机程序
284912933 发表于 2014-12-12 18:29
完全看不懂啊,只知道是和键盘有关的东西....
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 11:12

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表