打印

谁做过C51单片机与PS/2键盘的通信

[复制链接]
3840|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wzywzy12|  楼主 | 2010-2-10 16:04 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
键盘初始化程序kb_init()流程为:
① 上电后,接收键盘上电自检通过信号0xAA,或者自检出错信号0xFC.单片机接收为0xAA则进入下一步,否则进行出错处理.
② 关LED指示,单片机发送0xED,然后接收键盘回应0xFA,接着发送0x00接收0xFA.
③ 设置机打延时和速率:单片机发送0xF3,接收0xFA,发送0x00(250 ms,2.0 cps),接收0xFA.
④ 检查LED,发送0xED,接收0xFA,发送0x07(开所有LED),接收0xFA.发送0xED,接收0xFA,发送0x00(关LED),接收0xFA.
⑤ 允许键盘,发送0xF4,接收0xFA.键盘LED改变ps2_ledchange()函数流程:发送0xED;接收0xFA;发送led_status;接收0xFA.

键盘上电后是否一定要对其初始化,但我接上键盘上电后并没有发出自检信号,并且发出指令后,键盘并没有动静。
我这个弄了很久了,弄得头都大了。那位能详细地指导我一下这个谁做过C51单片机与PS/2键盘的通信。。

相关帖子

沙发
wzywzy12|  楼主 | 2010-2-10 16:07 | 只看该作者
这是我对键盘初始化的代码:

#include <reg52.h>
#include <intrins.h>

sbit PS2_CLOCK = P3^2;
sbit PS2_DATA = P1^0;
sbit LED1=P0^7;
sbit LED2=P0^6;
sbit LED3=P0^5;
sbit LED4=P0^4;
sbit LED5=P0^3;
sbit LED6=P0^1;

unsigned char mcu_char;
unsigned char mcu_char_flag;
unsigned char char_bit;

/*延时函数*/
void delay10us(unsigned char t)
{  
  do
  {_nop_();_nop_();_nop_();_nop_();}while(--t);
}
/*单片机发送数据到PS2键盘*/
void MCU_to_PS2(unsigned char sendchar)
{
        unsigned char char_bit;
        unsigned char char_chk;
        //关闭中断
        EX0=0;
        //发送起始位
        PS2_CLOCK=0;
        delay10us(15);//精确延时100us
        PS2_DATA=0;
        delay10us(1);
        PS2_CLOCK=1;
        //发送数据位
        for(char_bit=0;char_bit<8;char_bit++)
        {
                while(PS2_CLOCK==1);
                PS2_DATA=sendchar&0x01;
                if(PS2_DATA==1)        char_chk++;
                sendchar>>=1;
                while(PS2_CLOCK==0);               
        }
        //发送校验位
        while(PS2_CLOCK==1);
        PS2_DATA=!(char_chk%2);
        while(PS2_CLOCK==0);
        //发送停止位
        while(PS2_CLOCK==1);
        PS2_CLOCK=1;
        while(PS2_CLOCK==0);
        //接收应答位
        while(PS2_CLOCK==1);
        //if(PS2_DATA==1) send_error(); 可添加应答位检测函数
        while(PS2_CLOCK==0);
        //开启中断       
        EX0=1;
}

/*单片机接收PS2键盘数据*/
void PS2_to_MCU() interrupt 0
{       
        EX0=0; //关外部中断0
        switch(char_bit)
        {
                case 1:
                case 2:
                case 3:
                case 4:
                case 5:
                case 6:
                case 7:
                case 8:{mcu_char>>=1;
                                if(PS2_DATA) mcu_char|=0x80;
                                char_bit++;

                                break;
                                }
                case 0:char_bit++;break; //开始位,
                case 9:char_bit++;break; //校验位,可添加校验程序
                case 10:{//停止位
                                char_bit=0;
                                mcu_char_flag=1;//置接收到数据标识位
                                //if(mcu_revchar==0xF0) F0_FLAG=1;
                                //else F0_FLAG=0;
                                break;}
                default:break;
        }

        EX0=1;//开外部中断0
}
/*① 上电后,接收键盘上电自检通过信号0xAA,或者自检出错信号0xFC.单片机接收为0xAA则进入下一步,否则进行出错处理.
② 关LED指示,单片机发送0xED,然后接收键盘回应0xFA,接着发送0x00接收0xFA.
③ 设置机打延时和速率:单片机发送0xF3,接收0xFA,发送0x00(250 ms,2.0 cps),接收0xFA.
④ 检查LED,发送0xED,接收0xFA,发送0x07(开所有LED),接收0xFA.发送0xED,接收0xFA,发送0x00(关LED),接收0xFA.
⑤ 允许键盘,发送0xF4,接收0xFA.键盘LED改变ps2_ledchange()函数流程:发送0xED;接收0xFA;发送led_status;接收0xFA.*/
/*键盘初始化函数*/
void key_init()
{       
        while(mcu_char_flag==0);
            
        if(mcu_char==0xFF)
//                {LED6=0;//key_init_error();//键盘初始化失败
//        mcu_char_flag=0;}
//        else if(mcu_char==0xAA) {
                mcu_char_flag=0;
                LED3=0;
                MCU_to_PS2(0xED);
                while(mcu_char_flag==0);
                while(mcu_char!=0xFA);
                mcu_char_flag=0;
               
                MCU_to_PS2(0x00);
                while(mcu_char_flag==0);
                while(mcu_char!=0xFA);
                mcu_char_flag=0;
                MCU_to_PS2(0xF3);
                while(mcu_char_flag==0);
                while(mcu_char!=0xFF);
                mcu_char_flag=0;
                MCU_to_PS2(0xFA);
                while(mcu_char_flag==0);
                while(mcu_char!=0xFA);
                mcu_char_flag=0;
                MCU_to_PS2(0x00);
                while(mcu_char_flag==0);
                while(mcu_char!=0xFA);
                mcu_char_flag=0;
                MCU_to_PS2(0xED);
                while(mcu_char_flag==0);
                while(mcu_char!=0xFA);
                mcu_char_flag=0;
                MCU_to_PS2(0x07);
                while(mcu_char_flag==0);
                while(mcu_char!=0xFA);
                mcu_char_flag=0;
                MCU_to_PS2(0xED);
                while(mcu_char_flag==0);
                while(mcu_char!=0xFA);
                mcu_char_flag=0;
                MCU_to_PS2(0x00);
                while(mcu_char_flag==0);
                while(mcu_char!=0xFA);
                mcu_char_flag=0;
                MCU_to_PS2(0xF4);
                while(mcu_char_flag==0);
                while(mcu_char!=0xFA);
                mcu_char_flag=0;                               
                //}
               
}

void key_ledchange(unsigned char led_status)
{
        MCU_to_PS2(0xED);
        while(mcu_char_flag==0);
        while(mcu_char!=0xFA);
        mcu_char_flag=0;
        MCU_to_PS2(led_status);
        while(mcu_char_flag==0);
        while(mcu_char!=0xFA);
        mcu_char_flag=0;
}

void main()
{       
        IE=0x81;
        TCON=0x01;
        key_init();


        key_ledchange(0x04);//启用小键盘
        //读取小键盘程序

}

使用特权

评论回复
板凳
清风致影| | 2010-2-10 16:55 | 只看该作者
我以前做的时候没有什么要对键盘初始化的,直接上电就行了,在键盘上按下按键会发出通码和断码,根据这2个码进行解码,可得到对应的按键名。你检查下ps/2通讯是否正确

使用特权

评论回复
地板
冷漠| | 2010-2-10 20:19 | 只看该作者

没那么复杂,标准的异步字符通信格式。

本帖最后由 冷漠 于 2010-2-10 21:04 编辑

当时发现这一点的时候,兴奋地不得了。 就是个单片机之间的2线通信问题。比特率12500bps,根本不需要时钟线。测了3个不同牌子的AT键盘都是一样,很精准。哈哈。
       单片机向键盘发送也很简单,加一个2选1芯片就行了:键盘不按键时,就是处于接收状态。


单片机与标准键盘接口方法1.rar (26.97 KB)

使用特权

评论回复
5
wzywzy12|  楼主 | 2010-2-11 14:22 | 只看该作者
那如果我想启用小键盘呢,点亮小键盘的灯呢?

使用特权

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

本版积分规则

5

主题

16

帖子

1

粉丝