打印
[51单片机]

关于51单片机模拟ps2键盘

[复制链接]
2640|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
yzcook|  楼主 | 2018-4-25 10:55 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
yzcook|  楼主 | 2018-4-25 10:56 | 只看该作者
这是我的主函数

#include <reg51.h>
#include "ps2.h"
#include "delay.h"
#include "usart.h"
#include "key.h"
#include<intrins.h>
sbit BEEP = P1^7;


void  main ( )
{        


        ConfigUART(9600);

        
        while(1)
        {

                        ps2_rec();
                        receive_process();//处理PC命令
//                delay_ms(5000);

        
               
               


               
        }  

}

使用特权

评论回复
板凳
yzcook|  楼主 | 2018-4-25 10:56 | 只看该作者
这是我的发送函数
发送应该是没有问题的
因为我发送0x58 能实现让灯亮



void  ps2_send(unsigned char value)
{
        unsigned char  i;
        unsigned char  char_temp,temp;
        unsigned char PARITY = 1 ;
        temp = value;
        last_s = value;
        for(i=0;i<8;i++)                                   
        {
                char_temp = temp&0x01;                          //奇效验,找出发送的数据中1的个数,如果为偶数,则置标志位为1,反之为0
                if(char_temp == 0x01)
                {
                         PARITY = !PARITY;
                }
                temp = temp>>1;
        }
        
        PS2_CLK = 1;
        PS2_DAT = 1;
        while(!PS2_CLK)  //等待clock为高
        {        
                PS2_CLK = 1;
                PS2_DAT = 1;
                Delay50us();        
        }        
                PS2_CLK = 1;
                PS2_DAT = 1;
                if(PS2_CLK)
                {
                        if(PS2_DAT)
                        {

                                PS2_DAT = 0; //PC在PS2_CLK的下降沿读取数据,起始位
                                Delay20us();
                                PS2_CLK = 0;
                                Delay40us();
        
                                for (i=0; i<8;i++) //发送数据位
                                {
                                        PS2_CLK = 1;
                                        Delay20us();
                                        char_temp = value&0x01;
                                        if(char_temp == 0x01)
                                                PS2_DAT = 1;
                                        else
                                                PS2_DAT = 0;
                                        char_temp = 0;
                                        Delay20us();                                
                                        PS2_CLK = 0;        
                                        Delay40us();
                                        value = value>>1;
                                }        
                                       
                                        PS2_CLK = 1;
                                        Delay20us();                                       
                                        PS2_DAT = PARITY; //发送奇校验
                                        Delay20us();
                                        PS2_CLK = 0;
                                        Delay40us();                                

                                        PS2_CLK = 1;
                                        Delay20us();                                       
                                        PS2_DAT = 1; // 发送停止位
                                        Delay20us();
                                        PS2_CLK = 0;
                                        Delay40us();
        
                                        PS2_CLK = 1;

                        }
                }

         Delay50us();
        
}

使用特权

评论回复
地板
yzcook|  楼主 | 2018-4-25 10:56 | 只看该作者
这是我的接收函数
感觉在这里出了问题



unsigned char ps2_rec( )//返回接收到的字节,接收错误则返回0
{
        unsigned char i,STOPBIT;
        unsigned char PARITY,temp ;

        PS2_CLK = 1;
        PS2_DAT = 1;
        Delay100us();
  PS2_DAT = 0;
        PS2_CLK = 1;        
        if (PS2_DAT)//PS2_DAT应该为低        如果此时PS2_DAT为高,则退出并发送错误状态字0xfe
        {
                ps2_send(0xfe);
                return 0;
        }

        else
        {        
                Delay40us();
                for(i=0;i<8;i++)
                {
                        Delay20us();
                        PS2_CLK = 0;
                        Delay40us();
                        PS2_CLK = 1;
                        Delay20us();
                        temp = temp>>1;
                        if(PS2_DAT)
                        {               
                                temp |=0x80;               
                        }

                }
//                SendByte(0X30+temp);
//                delay_ms(3000);
                        if(!PS2_CLK)        //每读完一个位都检测时钟线是否被拉低
                                {
                                                ps2_send(0xfe);      
                                                return 0;            
                                }
//======================================================                        
                        Delay20us();
                        PS2_CLK = 0;
                        Delay40us();
                        PS2_CLK = 1;        
                        Delay20us();
                        PARITY = PS2_DAT;
                        if(!PS2_CLK)        //每读完一个位都检测时钟线是否被拉低
                                {
                                                ps2_send(0xfe);      
                                                return 0;            
                                }        
//                        SendByte(0x30+PARITY);
        //        SendStr("4");
//======================================================        
                        Delay20us();
                        PS2_CLK = 0;
                        Delay40us();
                        PS2_CLK = 1;
                        Delay20us();
                        STOPBIT = PS2_DAT;
                        if(!PS2_CLK)//接收停止位,此时PS2_DAT应该为高,否则发送0xfe报错
                        {
                                ps2_send(0xfe);
                                return 0;
                        }
//======================================================
                                
                        Delay15us();
                        PS2_DAT = 0;
                        Delay5us();
                        PS2_CLK = 0;
                        Delay40us();
                        PS2_CLK = 1;
                        Delay5us();
                        PS2_DAT = 1;
                        ACC = temp;
                        SendByte(P);

                        if(P == PARITY)            //进行奇校验            
        {
//                                        ps2_send(0xfe);
          return 0;
        }
//                        SendStr("0x33");
                Delay40us();
                Delay5us();
        }
//        SendByte(0X30+temp);
        return temp;
        }

使用特权

评论回复
5
yzcook|  楼主 | 2018-4-25 10:57 | 只看该作者

这是命令处理函数


unsigned char receive_process()
{
  unsigned char  command,led_rec;
//  if(!KB_START())  return;//如果当前的PS2_CLK和PS2_DAT不都为低,表明没有命令
        command = ps2_rec();
//        SendStr("pass");
        switch(command)
        {
                case 0xff:   //复位命令
                        ps2_send(0xfa);
                        delay_ms(50);
                  ps2_send(0xaa); //自检通过返回0xaa
                                                                //执行复位
                break;
                case 0xfe:
                        ps2_send(0xfa);
                        ps2_send(last_s);                                        //发送上一次的命令
                        break;
                case 0xf6:  //设置缺省值
                        ps2_send(0xfa);
                        
                break;
                case 0xf5:  //设置缺省值和停止键盘 ,等待进一步命令
                        ps2_send(0xfa);
               
               
                break;
                case 0xf4:  //重新使能键盘
                        ps2_send(0xfa);  
               
               
                break;
                case 0xf3:        //设置机打速率和延迟
                        ps2_send(0xfa);
                        
               
                break;
                case 0xee://回应命令
                        ps2_send(0xee);
               
                case 0xed: //指示灯参数
                        ps2_send(0xfa);                                
                        led_rec = ps2_rec();
                        SendByte(led_rec);
                        ps2_send(0xfa);               
                break;
                default:
                        ps2_send(0xfa); //对于其他命令发送完成标志
                break;
                        
               
        }
        return command;
}

使用特权

评论回复
6
ningling_21| | 2018-4-25 11:25 | 只看该作者
yzcook 发表于 2018-4-25 10:57
这是命令处理函数

发送如果有问题,PC不能正常识别,肯定不会返回

建议用示波器查看一下发送数据的波形,是否满足时序要求

使用特权

评论回复
7
yzcook|  楼主 | 2018-4-25 11:34 | 只看该作者
ningling_21 发表于 2018-4-25 11:25
发送如果有问题,PC不能正常识别,肯定不会返回

建议用示波器查看一下发送数据的波形,是否满足时序要求 ...

发送是没有问题的  我看过时序。 而且我发送0x58 即cap键的通码,CAP灯也能亮

使用特权

评论回复
8
ningling_21| | 2018-4-25 13:03 | 只看该作者
、先弄清楚通信协议

使用特权

评论回复
9
xyz549040622| | 2018-4-25 14:44 | 只看该作者
现在还有场合会用到PS2接口吗?应该被彻底淘汰了。

使用特权

评论回复
评论
xyz549040622 2018-4-25 19:15 回复TA
@yzcook :爱莫能助,当初学这个的时候,我就觉得PS2已经过期,就没学他,哈哈。 
yzcook 2018-4-25 14:48 回复TA
肯定多多少少都会有的 你懂这个吗 能不能帮我看看 
10
coody| | 2018-4-26 16:37 | 只看该作者
PS2协议比较简单,我十几年前做过不少,就是一个外中断(时钟)和一个普通IO(数据)就可以连接电脑的PS2接口了。关键是初始化。

使用特权

评论回复
评论
yzcook 2018-4-27 08:14 回复TA
。。。我就是在初始化这边调了好久。 
11
niuwp| | 2020-4-16 09:46 | 只看该作者
请问楼主接收和发送给主机数据的这个程序还在吗?小弟想参考一下,我QQ:1411542658
求联系

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

28

主题

84

帖子

0

粉丝