搜索
bottom↓
回复: 33

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

[复制链接]

出0入0汤圆

发表于 2011-1-3 18:24:17 | 显示全部楼层 |阅读模式
前段时间改写的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[TempCyc][0]!=ScanCode)&&(TempCyc<49); TempCyc++); //查表显示
                                        if (kbdasciicode[TempCyc][0] == ScanCode)
                                                {                                         
                                                keyVcache(kbdasciicode[TempCyc][2]);  //返回大写字母或第二功能键值
                                                break;
                                            };                                                 
                     }
                                else                // 没有按下SHIFT
                    {
                                        for(TempCyc = 0; (kbdasciicode[TempCyc][0]!=ScanCode)&&(TempCyc<49); TempCyc++); //查表显示
                                        if (kbdasciicode[TempCyc][0] == ScanCode)
                       {
                                            if(Button.CapsLock&(TempCyc<27))        // 如果CapsLock有效且按下字母键
                                                {
                                                  keyVcache(kbdasciicode[TempCyc][2]); // 返回大写字母键值
                                                }
                                                else
                                                {
                                                keyVcache(kbdasciicode[TempCyc][1]); // 否则返回小写或第一功能键值
                                                };
                                                break;
                                             };
                    };
                                //带E0开头类按键 查表
                                if(E0Key)          //如果属于E0开头的键盘码
                                        {
                                        E0Key=0;
                                        for (TempCyc = 0;(E0startedcode[TempCyc][0]!=ScanCode)&&(TempCyc<18); TempCyc++); //查表显示
                                        if (E0startedcode[TempCyc][0] == ScanCode)
                                                {
                                                   keyVcache(E0startedcode[TempCyc][1]);
                                                break;
                                            };
                                          
                     };
                                //控制类键以及小键盘按键 查表
                           for(TempCyc = 0; (kbdcontrolcode[TempCyc][0]!=ScanCode)&&(TempCyc<37); TempCyc++); //查表显示
                                  {
                                        if (kbdcontrolcode[TempCyc][0] == ScanCode)
                       {
                                            if(Button.NumLock&(TempCyc<14))
                                                {
                                                //NumLock上锁,小键盘不返回键码
                                                }
                                                else
                                                {
                                              keyVcache(kbdcontrolcode[TempCyc][1]);
                                                };
                                             };
                                  };                               
                        };
        }
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)

=====================================测试图片=====================================================

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

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


不知道键盘的Caps Lock灯怎么控制亮灭呢? (原文件名:20110103432.jpg)


不知道键盘的Caps Lock灯怎么控制亮灭呢? (原文件名:20110103434.jpg)


不知道PS2键盘怎么初始化呢? (原文件名:20110103433.jpg)


PS2硬件接口 (原文件名:连接图.jpg)

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2011-1-3 22:39:50 | 显示全部楼层
沙发,强人一个

出0入0汤圆

发表于 2011-1-4 12:20:30 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-1-4 14:21:16 | 显示全部楼层
顶啊,待会儿,我也去研究研究。

出0入0汤圆

发表于 2011-1-6 09:17:05 | 显示全部楼层
写ps/2的话
两根线要上拉500欧电阻..
要不然的话主机释放总线后电平拉不高
我原来写过这玩意
命令你上传的资料里有
看看吧

出0入0汤圆

 楼主| 发表于 2011-1-6 12:08:06 | 显示全部楼层
回复【4楼】277135246
-----------------------------------------------------------------------

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

出0入0汤圆

发表于 2011-1-7 13:49:21 | 显示全部楼层
.. 不需要..

出0入0汤圆

发表于 2011-1-11 12:54:45 | 显示全部楼层
不错

出0入0汤圆

发表于 2011-1-11 19:05:19 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-1-11 21:24:38 | 显示全部楼层
good

出0入0汤圆

发表于 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)

出0入0汤圆

 楼主| 发表于 2011-1-18 13:15:47 | 显示全部楼层
回复【10楼】yaxi1984
-----------------------------------------------------------------------

谢谢yaxi1984

出0入0汤圆

发表于 2011-1-23 12:23:07 | 显示全部楼层
单片机里写命令就好了,我做成功过。

出0入0汤圆

发表于 2011-1-24 16:42:27 | 显示全部楼层
哎,真复杂。。。

出100入0汤圆

发表于 2011-4-2 14:23:41 | 显示全部楼层
xiami

出0入0汤圆

发表于 2011-4-17 14:35:47 | 显示全部楼层
dofly?好熟悉的开发板啊

出0入0汤圆

发表于 2011-4-18 23:01:33 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-4-19 00:17:41 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-4-19 08:54:09 | 显示全部楼层
感谢

出0入0汤圆

发表于 2011-4-19 18:12:24 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-5-10 16:46:30 | 显示全部楼层
PC机发送的命令字        16进制值        键盘发送的命令字        16进制值

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

出0入0汤圆

发表于 2011-5-10 19:37:58 | 显示全部楼层
做个测试键盘工具,呵呵!!

出0入0汤圆

发表于 2011-7-30 22:42:29 | 显示全部楼层
马克

出0入0汤圆

发表于 2011-8-1 17:34:41 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-8-1 19:11:30 | 显示全部楼层
支持一下~~

出0入0汤圆

发表于 2011-8-11 15:40:01 | 显示全部楼层
支持一下~~

出0入0汤圆

发表于 2011-11-12 11:30:06 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-11-12 13:56:58 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-11-19 17:29:23 | 显示全部楼层
謝謝樓主,學習

出0入0汤圆

发表于 2011-11-19 17:40:56 | 显示全部楼层
MARK!!!!!!

出0入17汤圆

发表于 2012-4-7 11:54:05 | 显示全部楼层
感谢LZ和11楼m

出0入0汤圆

发表于 2012-4-7 18:50:04 来自手机 | 显示全部楼层
呀,收藏了

出0入0汤圆

发表于 2013-5-18 20:37:45 | 显示全部楼层
你好楼主,附件里的程序我测试的各图片对不上啊,不能用好像

出0入0汤圆

发表于 2013-8-9 16:49:02 | 显示全部楼层
最基本的ps2键盘解码程序并不难,我今天从论坛中找了2个不同的程序,综合一下,用stm32f103rb实现了,其实关于ps2协议,我一点都不懂,我一点都没有看,就是看看这两个程序,然后在stm上改写,成功了,但是没有向键盘发送命令,因为我不懂,但是也有相关的程序,我想一会看一下,这样就可以控制键盘的num指示灯了
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 16:12

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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