qq335702318 发表于 2011-1-3 18:24:17

改写的 PS/2 键盘解码程序

前段时间改写的PS2键盘解码程序
实测可以使用
但一直搞不懂如何写入键盘。
就是不知道如何通过单片机控制键盘的Caps Lock 、Num Lock 灯的亮灭,希望大虾指点指点。。。感谢!!



=====================================C文件========================================================
#include <reg52.h>
#include "scancodes.h"
#include "ps2kbd.h"
#include "delay.h"       
//#include "LCD1602.h"



/*-----------------------------------------------
名称:PS2键盘驱动程序
日期:2010.11
修改:无
内容:通过单片机读/写PS2键盘
备注:本程序需使用外部中断口
------------------------------------------------*/


//---------IO引脚宏定义---------//
sbit Key_Data = P3^0 ;   //定义Keyboard引脚
sbit Key_CLK = P3^2;      //使用中断




//-----结构体------//
//--标识特殊按键---//
static struct key_sign
{         
char Shift:1;      //上档键
char CapsLock:1;          //大小写
char NumLock:1;          //小键盘锁
}Button;                          

//-----标志----//
bit BF;                                       //解码完毕标志
bit Key_UP;            //定义通码断码标志
bit E0Key=0;                       //E0开头的键盘码
bit Paritycheck=1;               //奇偶校验标志


unsigned char KeyV;               //键值
unsigned char IntNum;       //中断次数


/******************************************************************/
/*                  函数声明                                    */
/******************************************************************/
void Decode(unsigned char ScanCode);//解码子程序
void keyVcache(unsigned char keyV);          //键值入口,keyV就是解码后返回的键码
void Keyboard_WRITE(unsigned char sentchar);//写一字节到PS2键盘






/*-----------------------------------------------
名称:主机读取PS2键盘一字节
日期:2010.11
修改:无
内容:读取PS2键盘返回值(未解码),外部中断法
备注:键值存KeyV
------------------------------------------------*/
void Keyboard_READ(void) interrupt 0
{
if((IntNum > 0) && (IntNum < 9))
   {
        KeyV >>= 1;                //因键盘数据是低>>高,结合上一句所以右移一位
        if (Key_Data)
        {
   KeyV |= 0x80;             //当键盘数据线为1时到最高位
       Paritycheck=~Paritycheck; //奇偶校验位,数据奇数1为0
        };
   };         
if(IntNum==9)
{
   if(Key_Data!=Paritycheck)
   {
      KeyV=0x00;                          //奇偶校验错误,清空数据
   };
};
IntNum++;
while (!Key_CLK);                           //等待PS/2CLK拉高
if(IntNum > 10)
{
   IntNum = 0;                  //当中断11次后表示一帧数据收完,清变量准备下一次接收
   BF = 1;                      //标识有字符输入完了
   EA = 0;                      //关中断等显示完后再开中断
   Paritycheck=1;                                 //一次接收接收,初始化奇偶校验位
};        
}



/*-----------------------------------------------
名称:PS2键盘解码
日期:2010.11
修改:无
内容:解码键盘返回值
传入:ScanCode 键盘返回值
传出:无
相关寄存器:BF,Shift,CapsLock,NumLock,Key_UP,E0_Key
------------------------------------------------*/
void Decode(unsigned char ScanCode) // 注意:如SHIFT+G为12H 34H F0H 34H F0H 12H,也就是说shift的通码+G的通码+shift的断码+G的断码
{
unsigned char TempCyc;

if (!Key_UP)                        // 当键盘按下时
        {
        switch (ScanCode)
                        {
                        case 0xF0 :             // 当收到0xF0,Key_UP置1表示断码开始
                                Key_UP = 1;
                                break;

                        case 0x12 :             // 左 SHIFT
                                Button.Shift = 1;
                                break;
                        case 0x58 :                                // CapsLock键
                          Button.CapsLock = ~Button.CapsLock;
                                break;
                        case 0x59 :             // 右 SHIFT
                                Button.Shift = 1;
                                break;

                        case 0x77 :                                // 小键盘锁
                          Button.NumLock = ~Button.NumLock;
                                break;

                        case 0xe0 :                                // 以E0开头的键码
                          E0Key = 1;
                                break;

                        case 0xFA :                          // 键盘应答信号
                          break;

                        default:
                           /*如果数据不是F0,E0或LOCK键,则进行:查表对比键盘码,输出键值*/
                          
                                if(Button.Shift)         // 如果SHIFT按下
                                        {
                                        for (TempCyc = 0;(kbdasciicode!=ScanCode)&&(TempCyc<49); TempCyc++); //查表显示
                                        if (kbdasciicode == ScanCode)
                                                {                                       
                                                keyVcache(kbdasciicode);//返回大写字母或第二功能键值
                                                break;
                                          };                                                 
                     }
                                else                // 没有按下SHIFT
                  {
                                        for(TempCyc = 0; (kbdasciicode!=ScanCode)&&(TempCyc<49); TempCyc++); //查表显示
                                        if (kbdasciicode == ScanCode)
                     {
                                          if(Button.CapsLock&(TempCyc<27))        // 如果CapsLock有效且按下字母键
                                                {
                                                keyVcache(kbdasciicode); // 返回大写字母键值
                                                }
                                                else
                                                {
                                                keyVcache(kbdasciicode); // 否则返回小写或第一功能键值
                                                };
                                                break;
                                           };
                  };
                                //带E0开头类按键 查表
                                if(E0Key)          //如果属于E0开头的键盘码
                                        {
                                        E0Key=0;
                                        for (TempCyc = 0;(E0startedcode!=ScanCode)&&(TempCyc<18); TempCyc++); //查表显示
                                        if (E0startedcode == ScanCode)
                                                {
                                                   keyVcache(E0startedcode);
                                                break;
                                          };
                                          
                     };
                                //控制类键以及小键盘按键 查表
                           for(TempCyc = 0; (kbdcontrolcode!=ScanCode)&&(TempCyc<37); TempCyc++); //查表显示
                                  {
                                        if (kbdcontrolcode == ScanCode)
                     {
                                          if(Button.NumLock&(TempCyc<14))
                                                {
                                                //NumLock上锁,小键盘不返回键码
                                                }
                                                else
                                                {
                                          keyVcache(kbdcontrolcode);
                                                };
                                           };
                                  };                               
                        };
        }
else
        {
        Key_UP = 0;
        switch (ScanCode) //当键松开时不处理判码,如G 34H F0H 34H 那么第二个34H不会被处理
                        {
                        case 0x12 : // 左 SHIFT
                                Button.Shift = 0;
                                break;

                        case 0x59 : // 右 SHIFT
                                Button.Shift = 0;
                          break;
                        };
        };
BF = 0; //标识字符处理完了
}




/*-----------------------------------------------
名称:主机写PS2键盘
日期:2010.11
修改:无
内容:写一个字节入PS2键盘
传入:sentchar 传入键盘的数据
------------------------------------------------*/
void Keyboard_WRITE(unsigned char sentchar)          //ps2主设备向从设备发送数据
{
unsigned char sentbit_cnt = 0x00;
unsigned char sentchar_chk = 0x00;
EX0=0; //关外部中断0

//发起一个传送,发起始位
Key_CLK = 0; //将时钟线拉低并保持100 us
delay_nus(100);
Key_Data= 0; //起始位
Key_CLK = 1;

//发送DATA0-7
for(sentbit_cnt=0;sentbit_cnt< 8;sentbit_cnt++)
{
while(Key_CLK)
_nop_(); //等待时钟线变为低
Key_Data = sentchar&0x01;//发送数据
if(Key_Data) sentchar_chk++; //计算校验
while(!Key_CLK) _nop_(); //等待时钟线变高
sentchar>>=1; //待发送数据右移一位
};

//发送校验位
while(Key_CLK) _nop_(); //等待时钟线变低
switch(sentchar_chk)
{
case 0:
case 2:
case 4:
case 6:Key_Data = 1;break;//奇校验
case 1:
case 3:
case 5:
case 7:Key_Data = 0;break;//奇校验
default:break;
};

while(!Key_CLK) _nop_(); //等待时钟线变高
while(Key_CLK) _nop_(); //等待时钟线变低
Key_Data =1;//发送停止位,停止位总为1
while(!Key_CLK) _nop_(); //等待时钟线变高
while(Key_CLK) _nop_(); //等待时钟线变低
//接收ACK
//if(PS2_SGN_DATA) error();
//ACK信号由键盘发出,总为低电平
while(!Key_CLK) _nop_(); //等待时钟线变高
EX0= 1; //开外部中断0
}



/*-----------------------------------------------
名称:键值传入
日期:2010.11
修改:无
内容:键值就传入到此函数,可通过对该函数编写按键处理
传入:解码后的按键键值
------------------------------------------------*/
void keyVcache(unsigned char keyV)
{
unsigned char i;

ShowChar(i++,keyV);
   if(i>32)
   {
   i=0;
   WriteCommand(0x01);
   };
}


//参考:http://www.picavr.com/news/2010-08/2296.htm


=====================================资料========================================================
程序ourdev_608918WOZS4Q.rar(文件大小:41K) (原文件名:ps2接口测试.rar)
PS2技术参考 本论坛已有ourdev_608919ZYXUGS.pdf(文件大小:667K) (原文件名:ps2技术参考.pdf)
不错的教程 网上收集ourdev_608920FR5THD.mht(文件大小:421K) (原文件名:转贴:PS2键盘的单片机编程 (重要!).mht)
http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_608921QLR5NG.jpg
=====================================测试图片=====================================================

以下1602显示的文字都是由PS2键盘输入的。

测试图片1 (原文件名:20110103431.jpg)

http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_608922DWZSGF.jpg
不知道键盘的Caps Lock灯怎么控制亮灭呢? (原文件名:20110103432.jpg)

http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_608923OBCP2T.jpg
不知道键盘的Caps Lock灯怎么控制亮灭呢? (原文件名:20110103434.jpg)

http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_608924LB8QZ0.jpg
不知道PS2键盘怎么初始化呢? (原文件名:20110103433.jpg)

http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_608925YWR1Q3.jpg
PS2硬件接口 (原文件名:连接图.jpg)

pxlpxlpxl 发表于 2011-1-3 22:39:50

沙发,强人一个

denglu 发表于 2011-1-4 12:20:30

mark

wgm_123 发表于 2011-1-4 14:21:16

顶啊,待会儿,我也去研究研究。

277135246 发表于 2011-1-6 09:17:05

写ps/2的话
两根线要上拉500欧电阻..
要不然的话主机释放总线后电平拉不高
我原来写过这玩意
命令你上传的资料里有
看看吧

qq335702318 发表于 2011-1-6 12:08:06

回复【4楼】277135246
-----------------------------------------------------------------------

谢谢!!请问PS2键盘需要像液晶屏一样上电初始化的吗?

277135246 发表于 2011-1-7 13:49:21

.. 不需要..

htlm2010 发表于 2011-1-11 12:54:45

不错

chess01 发表于 2011-1-11 19:05:19

mark

zxcao 发表于 2011-1-11 21:24:38

good

yaxi1984 发表于 2011-1-17 21:46:41

上传一个我大学时写的PS2程序和当初整理的PS2协议中文文档给你参考吧:

PS2键盘驱动程序ourdev_611716L1OEXI.rar(文件大小:30K) (原文件名:ps2-KEY_20060204_final.rar)
我整理的PS2协议中文文档ourdev_611717SPNBVV.pdf(文件大小:855K) (原文件名:PS2鼠标键盘协议-仅含PS2部分.pdf)

qq335702318 发表于 2011-1-18 13:15:47

回复【10楼】yaxi1984
-----------------------------------------------------------------------

谢谢yaxi1984

Ayumi123 发表于 2011-1-23 12:23:07

单片机里写命令就好了,我做成功过。

longren_gd 发表于 2011-1-24 16:42:27

哎,真复杂。。。

wochai 发表于 2011-4-2 14:23:41

xiami

jlhgold 发表于 2011-4-17 14:35:47

dofly?好熟悉的开发板啊

wenjin0386 发表于 2011-4-18 23:01:33

mark

ddcchh 发表于 2011-4-19 00:17:41

mark

wmm20031015 发表于 2011-4-19 08:54:09

感谢

gloryzkl 发表于 2011-4-19 18:12:24

mark

tomatowo 发表于 2011-5-10 16:46:30

PC机发送的命令字        16进制值        键盘发送的命令字        16进制值

置位/复位命令        ED        自检成功码        AA
允许              F4        自检错误码        FC
ECHO                 EE        ECHO                 EE
复位              FF        确认                 FA
重新发送                 FE        重新发送                 FE

fjourdev 发表于 2011-5-10 19:37:58

做个测试键盘工具,呵呵!!

cqwshll 发表于 2011-7-30 22:42:29

马克

1021477601 发表于 2011-8-1 17:34:41

mark

dhbighead 发表于 2011-8-1 19:11:30

支持一下~~

st870520 发表于 2011-8-11 15:40:01

支持一下~~

afei8856 发表于 2011-11-12 11:30:06

mark

shi_90 发表于 2011-11-12 13:56:58

mark

allan_qing 发表于 2011-11-19 17:29:23

謝謝樓主,學習

sglhz 发表于 2011-11-19 17:40:56

MARK!!!!!!

hhxb 发表于 2012-4-7 11:54:05

感谢LZ和11楼m{:smile:}

jjj2012 发表于 2012-4-7 18:50:04

呀,收藏了

xfdr 发表于 2013-5-18 20:37:45

你好楼主,附件里的程序我测试的各图片对不上啊,不能用好像

stm32f103f4 发表于 2013-8-9 16:49:02

最基本的ps2键盘解码程序并不难,我今天从论坛中找了2个不同的程序,综合一下,用stm32f103rb实现了,其实关于ps2协议,我一点都不懂,我一点都没有看,就是看看这两个程序,然后在stm上改写,成功了,但是没有向键盘发送命令,因为我不懂,但是也有相关的程序,我想一会看一下,这样就可以控制键盘的num指示灯了
页: [1]
查看完整版本: 改写的 PS/2 键盘解码程序