dqlspzl 发表于 2009-12-9 20:44:35

求助菜鸟的89S52仿真PS2键盘,无法通过开机自检。

我自己想用AT89S52仿真一个PS2键盘,我有详细的看过PS2协议,但是没办法通过开机自检。实在是找不到错的地方了,望高手指点,谢谢了。
这是全部的程序,扫描部分没有做,完整的处理,每次只能按下一个键。
#include<reg52.h>
#include<stdio.h>
#include<intrins.h>
#define row P1                  //键盘使用12M的晶振。
#define lineone P0   //P2和P0口的加上上拉电阻。
#define linetwo P2
sbit KBCLK=P3^0;                 //键盘时钟线
sbit KBDATA=P3^1;                 //键盘数据线
sbit LEDNUM=P3^3;                 //NUMLOCK指示灯
sbit LEDCAP=P3^4;                 //CAPLOCK指示灯
sbit LEDSCR=P3^5;                 //SCROLLLOCK指示灯
bit ledne=0;        //当他为1之后,在进行主机到键盘的通讯之后,立即将得到数据送给void set_led(unsigned char);
bit flag=0;                        //当他为1时,缓冲区头为通码,断开后需要进行断码处理。
bit keyne=1;                        //键盘扫描使能。为1时键盘允许扫描,为0时不让扫描。
bit sl=0;                //扫描码对于特殊扫描码的通断码标志位。
bit        spl=0;                //对于PRINTSCAN键的通断码标志位。为0时已经打了断码,为1时没有打断码
bit spe=0;                //特殊码处理标志。
void bat(void);                //键盘诊断自检。
void ssend_byte(void);
void set_led(unsigned char);        //点亮LED
void Timer1_init(void);         //定时器1初始化
void keycode1(void);                //将扫描到的在第一列上的扫描码,转换为ASCII码
void keycode2(void);                //将扫描到的在第二列上的扫描码,转换为ASCII码
void set_led(unsigned char);         //设置LED,在主机给键盘发送的命令里面调用
void receive_byte(void);                 //接收键盘命令并处理
void send_byte(void);                       //发送一字节数据/命令。
void key_manage(unsigned char);                //有效按键处理,还有对于按键的缓存。
void manage(unsigned char);                //有效命令处理
void send_command(unsigned char);        //对于命令的缓存
//void ssend_byte(void);
void delayms(unsigned int);                        //ms级别的延时程序
//void delay(unsigned char);                        //us级别的延时程序
void delayus(unsigned char);                //us级别的延时程序,在中断外使用。
void delays();
void clr_buf(void);                                 //清键盘缓冲区
void re_send(void);
void Skey_manage(unsigned char);                                //特殊按键的处理。
void SAkey_manage(unsigned char);                        //按键PRINTSCAN键的处理。
void SSkey_manage(void);                        //按键PAUSE的处理。
unsigned char change(unsigned char);        //将16进制转换成数字
unsigned char bdata redata;        //定义一个可位寻址区,bdata的无符号字符型变量。
sbit redata_bit0=redata^0;
sbit redata_bit1=redata^1;
sbit redata_bit2=redata^2;
sbit redata_bit3=redata^3;
sbit redata_bit4=redata^4;
sbit redata_bit5=redata^5;
sbit redata_bit6=redata^6;
sbit redata_bit7=redata^7;
//bit send_code(unsigned char _KeyNo,bit flag);
//发送按键扫描码,flag=0发送断开码,flag=1发送接通码。
//void set_default(); //设置缺省值
//void set_scan_v(unsigned char); //拍发速率、延迟时间.
//void set_flag(unsigned char); //设置缓冲区对应标记。
//unsigned char paifa_count=0;                        //拍发计数
unsigned char huancun=0x00;                                //缓存最后一位发送的数据或者命令。
unsigned char key_buf;                         //按键缓冲区
unsigned char command_buf;                        //命令缓冲区
//unsigned char keyrow,keylineone,keylinetwo;        //定义3个全局可查询变量。
unsigned char key_count=0;                        //按键计数器
unsigned char command_count=0;                        //命令计数器,计算命令缓冲区内的命令个数
unsigned char Rnum;                                //定义扫描到的行和列的大小
unsigned char Cnum1;
unsigned char Cnum2;
unsigned char idata tab1={{0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C},{0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C},{0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C},{0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C},{0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C},{0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C},{0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C},{0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C}};
unsigned char idata tab2={{0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C},{0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C},{0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C},{0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C},{0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C},{0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C},{0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C},{0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C}};
unsigned char idata tab3={0xE1,0x14,0x77,0xE1,0xF0,0x14,0xF0,0x17};
unsigned char idata tab4={0xE0,0xF0,0x7C,0xE0,0xF0,0x12};
unsigned char idata tab5={0xE0,0x12,0xE0,0x7C};

// 函数名称: 主程序
// 函数功能: 循环查询主机状态
//--------------------------------------------------------------------------------------------------
void main()
{
bat();                                //键盘诊断自检(基本保证测试)
while(1)
        {
        send_byte();
        }
}
//--------------------------------------------------------------------------------------------------
// 函数名称: Timer0_init()和Timer1_init()
// 函数功能: 初始化设置
//            设定INT0,INT1的工作方式
//--------------------------------------------------------------------------------------------------
void Timer1_init(void)
             {       
            ET1=1;   //定时器1中断允许,方式为1,中断时间为10MS,65536-15536=50000        每50MS扫描一次键盘
            TH0=0x3C;
            TL0=0xB0;
            TR1=1;   //定时器1开始计数
            }

//--------------------------------------------------------------------------------------------------
// 函数名称: TIMER1_intrupt
// 函数功能: 定时器1中断处理程序 按键定时查询
//--------------------------------------------------------------------------------------------------
void TIMER1_int(void) interrupt 3 using 3        //用定时器中断查询,而不用延时查询时为了节约CPU资源,P57页详细讲解。
    {                                                                        
        unsigned char R,L1,L2,keyrow,keylineone,keylinetwo;
        if(keyne==0)
        {
        return;                //中断扫描
        }
        row=0xFF;
        lineone=0x00;
        linetwo=0x00;
        R=row;
        if(~R)
                {
                delayms(16);                //延时16MS,延时消抖;
                row=0xFF;
                lineone=0x00;
                linetwo=0x00;
                R=row;
                if(~R)
                        {
                        keyrow=row;
                        Rnum=change(keyrow);
                        lineone=0xFF;
                        linetwo=0xFF;
                        row=0x00;
                        L1=lineone;
                        L2=linetwo;
                        if(~L1)
                                {
                                keylineone=lineone;
                                Cnum1=change(keylineone);
                                keycode1();                //调用扫描码转换成ASCII的函数
                                }                                        //在函数里面要完成把码压入缓冲区
                        if(~L2)
                                {
                                keylinetwo=linetwo;
                                Cnum2=change(keylinetwo);
                                keycode2();                //调用扫描码转换成ASCII的函数
                                }                                        //在函数里面要完成把码压入缓冲区
                        }
                }
if(flag)
        {
        key_manage(0x00);
        }             
}
//-----------------------函数声明,变量定义--------------------------------------------------------
//--------------------------------------------------------------------------------------------------
// 函数名称: delay
// 入口参数: N
// 函数功能:延时子程序,实现(16*N+24)us的延时
// 系统采用11.0592MHz的时钟时,延时满足要求,其它情况需要改动
//--------------------------------------------------------------------------------------------------
/*void delay(unsigned char a)
{
        while(--a);                //若12 M,下面有    i    delay time/us
                                //                           1    7                 调用函数3个机器周期 RET2个机器周期
                                //                           2    9
                                //                           3    11      延时20us,为delay 8        time19
}*/
//--------------------------------------------------------------------------------------------------
//函数名称:void keycode1(unsigned char a,unsigned char b)和void keycode2(unsigned char c,unsigned char d)
//函数功能:将P0口和P1口,P2口的扫描码转换成相应的ASCII码,并且用函数将它压入缓冲区中。
//--------------------------------------------------------------------------------------------------
void keycode1() using 3
        {
        key_manage(tab1);       
        }
void keycode2() using 3
        {
        key_manage(tab2);
        }
//------------------------------------------------------------------------------------------------
// 函数名称: key_manage
// 函数功能: 有效按键处理
//            按键计数器加1,缓存区数据后移1位
//--------------------------------------------------------------------------------------------------
void key_manage(unsigned char key_code) using 3
      {
        unsigned char i,j,l;
        if(key_buf!=key_code)
                {
                        if(sl==1)
                                {
                                Skey_manage(0x00);
                                }
                        if(spl==1)
                                {
                                SAkey_manage(0x00);
                                }
                        else
                                {
                                for(l=16;l>0;l--)
                                        {
                                        key_buf=key_buf;       //缓冲区内数据后移1位
                                        }
                                key_buf=0xF0;            //将断码符号送入缓冲区
                                for(j=16;j>0;j--)
                                        {
                                        key_buf=key_buf;       //缓冲区内数据后移1位
                                        }
                                key_buf=key_buf;            //将断码以前的送入缓冲区
                                flag=0;                                //缓冲区头为断码
                                key_count=key_count+2;
                                }       
                }                       
        else
                {          
                switch(key_code)
                          {
                          case        0xFF:        Skey_manage(0x1F);break;                //也可以goto语句跳转到句末
                          case        0xFE:        Skey_manage(0x14);break;
                          case        0xFD:        Skey_manage(0x27);break;
                          case        0xFC:        Skey_manage(0x11);break;
                          case        0xFB:        Skey_manage(0x2F);break;
                          case        0xFA:        SAkey_manage(0x7C);break;
                          case        0xF9:        SSkey_manage();break;
                          case        0xF8:        Skey_manage(0x70);break;
                          case        0xF7:        Skey_manage(0x6C);break;
                          case        0xF6:        Skey_manage(0x7D);break;
                          case        0xF5:        Skey_manage(0x71);break;
                          case        0xF4:        Skey_manage(0x69);break;
                          case        0xF3:        Skey_manage(0x7A);break;
                          case        0xF2:        Skey_manage(0x75);break;
                          case        0xF1:        Skey_manage(0x6B);break;
                          case        0xF0:        Skey_manage(0x72);break;
                          case        0xEF:        Skey_manage(0x74);break;
                          case        0xEE:        Skey_manage(0x4A);break;
                          case        0xED:        Skey_manage(0x5A);break;
                        default:        break;
                                  }          
                if(spe==0)
                        {       
                        for(i=16;i>0;i--)
                                {
                                key_buf=key_buf;       //缓冲区内数据后移1位
                                }
                        key_buf= key_code;            //将键值送入缓冲区
                        flag=1;
                        key_count++;
                        }
                        spe=0;
                }                                        //缓冲区头为通码。       
                if(key_count>16)
                        {
                        key_count=16;
                        }
           }
//--------------------------------------------------------------------------------------------------
// 函数名称: send_byte
// 函数功能: 发送一字节数据
//--------------------------------------------------------------------------------------------------
void send_byte(void)
{
        unsigned char i,temp,keycode;
        bit check;
                if(KBCLK==0)
                {
                        delayus(4);                //延时20us
                        _nop_();
                        if(KBCLK==0)
                                {
                                return;
                                }
                }
        delayus(17);
        if(KBCLK==0)
                {
                return;
                }       
       if(KBDATA==0)
               {
                receive_byte();
                return;
                }       
        if(command_count>0)
                {
                command_count=command_count-1;
                keycode=command_buf;
                }
        else if(key_count>0)
                {
                key_count=key_count-1;
                keycode=key_buf;
                }
                        else
                        {
                        return;
                        }               
        huancun=keycode;
        temp=keycode;                //16进制的位,赋值一个机器周期,寻找数据位置一个周期
        ACC=keycode;
        check=!P;                //给bit赋值时,赋值一个机器周期,寻找数据位置一个周期,寻找位地址一个机器周期
           KBDATA=0;
           delayus(4);        //延时19us
           KBCLK=0;         //发送起始位        2个机器周期,这两个机器周期一个算在前,一个算在后面。
        _nop_();
        _nop_();
        _nop_();
        _nop_();                //nop用了补充for语句第一次运行时少用的4个机器周期
           for(i=8;i>0;i--)        //for语句第一次调用,用两个机器周期,第二次调用用6个机器周期,执行完最后用6个机器周期
                {
                delayus(11);                //延时33us
              KBCLK=1;
                delayus(2);        //延时15us
                _nop_();          
                KBDATA=(temp&0x01);//发送数据&运算双目运算符,先运算“&”之后再对KNDATA赋值,所有的赋值应该算入前面的计算       
                temp=temp>>1;                // ">>"双目运算符 赋值占用两个机器周期
                   delayus(2);        //延时15us
                KBCLK=0;          //延时1US
                }
        delayus(11);                //延时33us,发送校验位
    KBCLK=1;
        delayus(3);        //延时17us                  
        KBDATA=check; //发送校验位        三个机器周期,因为check是可变量所以调用需要3个机器周期       
           delayus(4);        //延时19us
        KBCLK=0;
        delayus(14);                //延时37us,发送停止位。
    KBCLK=1;
        delayus(4);        //延时19us                  
        KBDATA=1;         //发送停止位               
           delayus(4);        //延时19us
        KBCLK=0;
        delayus(19);        //延时49us
        KBCLK=1;        //释放时钟线
        delayus(300);
        return;               
   }
//--------------------------------------------------------------------------------------------------
// 函数名称: receive_byte
// 函数功能: 接收一子节数据
//--------------------------------------------------------------------------------------------------
void receive_byte(void)
      {
        unsigned char i;
        bit check,jy;
        KBCLK=0;
        delayus(13);                        //延时37us                                 
   for(i=8;i>0;i--)               
      {
        KBCLK=1;                //接收起始位,丢弃
        delayus(3);                //延时17us
        redata_bit0=KBDATA;                //对位赋变量值 占3个字节
        redata=redata<<1;               //移动加赋值占3个字节
        delayus(2);                 //延时15us
        _nop_();
        KBCLK=0;
        delayus(11);                //延时33us       
        }
KBCLK=1;               
delayus(3);                //延时17us
jy=KBDATA;                //读取校验位,3个机器周期
delayus(4);                //延时19us
KBCLK=0;
delayus(14);                //延时39us       
KBCLK=1;
delayus(14);                //停止位的接收,直接忽略了检测,本来应该检验是0;
KBCLK=0;
delayus(14);
KBCLK=1;
delayus(2);                        //应答位的发送15us
KBDATA=0;
_nop_();                        //延时5us
_nop_();
_nop_();
_nop_();
_nop_();
KBCLK=0;
delayus(14);                        //延时39us
KBCLK=1;
_nop_();                        //延时5us
_nop_();
_nop_();
_nop_();
_nop_();
KBDATA=1;
ACC=redata;
check=P;
if(check==jy)
        {
        redata=0xAA;                  //校验错误,让电脑重发。
        }
if((ledne==1)&&(redata!=0xFE))
{
set_led(redata);
}
manage(redata);
}
//--------------------------------------------------------------------------------------------------
// 函数名称: manage
// 函数功能: 主机命令处理函数
//--------------------------------------------------------------------------------------------------
void manage(unsigned char rec_data)
    {
        switch(rec_data)
        {
        case        0xFF:        send_command(0xFA);bat();break;
        case        0xFE:        re_send();break;
        case        0xF6:        send_command(0xFA);break;        //载入缺省的机打速率/延时,按键类型(所有按键都使能机打/通码/断码),       
                                                                                                //以及第二套扫描码集
        case        0xF5:        send_command(0xFA);keyne=0;break;//禁止键盘扫描
        case        0xF4:        send_command(0xFA);keyne=1;break;//开放键盘扫描
        case        0xF2:        send_command(0xFA);send_command(0xAB);send_command(0x83);break;
        case        0xEE:        send_command(0xEE);break;
        case        0xED:        ledne=1;send_command(0xFA);break;
        case        0xAA:        send_command(0xFA);send_command(0xFE);break;
        default:        send_command(0xFA);break;
        }
}
//--------------------------------------------------------------------------------------------------
//将16位数据转换成10进制
//--------------------------------------------------------------------------------------------------
unsigned char change(unsigned char shiliu) using 3
{
unsigned char num;
switch(shiliu)
        {
        case        0xFE:        num=0;        break;
        case        0xFD:        num=1;        break;
        case        0xFB:        num=2;        break;
        case        0xF7:        num=3;        break;
        case        0xEF:        num=0;        break;
        case        0xDF:        num=1;        break;
        case        0xBF:        num=2;        break;
        case        0x7F:        num=3;        break;
        default:        break;
        }
return(num);
}
//--------------------------------------------------------------------------------------------------
//键盘诊断自检或者复位。完成键盘所有功能和时间上的初始化。
//--------------------------------------------------------------------------------------------------
void bat(void)
{
TMOD=0x11;                  //定时器0和1都工作在方式1
EA=1;
IP=0x02;                //中断优先级为定时器0为为高优先级。IP   ---PSPT1PX1PT0PX0
//Timer0_init();                        //将定时器0和1进行初始化。
Timer1_init();
//set_scan_v();                //设置初始缺省拍发速率,屏蔽设置拍发速率的函数值,而在接收PC命令的时候处理此状态
clr_buf();                                //*定义扫描码集,置所有按键为机打/通码/断码*
set_led(0x07);                        //将3个灯全部点亮。
ssend_byte();
//send_command(0xAA);                //向PC发送命令0xAA表示自检通过。
delays();                                //做一个秒级别的延时。
set_led(0x00);                        //将3个灯全部熄灭。
}
//--------------------------------------------------------------------------------------------------
//键盘灯灯显示函数
//--------------------------------------------------------------------------------------------------
void set_led(unsigned char a)
{
if(a&0x01)
        {
        LEDNUM=0;                 //NUMLOCK指示灯
        }
else
        {
        LEDNUM=1;
        }
if(a&0x02)
        {
        LEDCAP=0;                 //NUMCAP指示灯
        }
else
        {
        LEDCAP=1;
        }
if(a&0x04)
        {
        LEDSCR=0;                 //NUMSCR指示灯
        }
else
        {
        LEDSCR=1;
        }
ledne=0;
}
//--------------------------------------------------------------------------------------------------
//对于命令的缓存。
//--------------------------------------------------------------------------------------------------
void send_command(unsigned char command)
      {
      unsigned char i;
        for(i=7;i>0;i--)
                {
                command_buf=command_buf;       //缓冲区内数据后移1位
                }
        command_buf= command;         //将键值送入缓冲区
/*        if(command_count>8)
                {
                command_count=8;                        //缓存的按键计数多余8的时候将最高位放弃。
                }
        else
                {
                command_count++;                   //按键计数器加一
                }*/
        command_count++;
}
//--------------------------------------------------------------------------------------------------
//重发最后一个函数
//--------------------------------------------------------------------------------------------------
void re_send(void)
{       
        command_buf=huancun;
        command_count++;
}
//--------------------------------------------------------------------------------------------------
//ms级别的延时函数;
//--------------------------------------------------------------------------------------------------
void delayms(unsigned int ms)
{
unsigned char i;
        while(ms--)                   
        {
        for(i = 0; i < 120; i++);
        }
}                       
void delays(void)
{
   unsigned int i,j;
   for(i=0;i<200;i++)
                   {
                for(j=0;j<1240;j++){;}
                }
}
//--------------------------------------------------------------------------------------------------
//清所有缓冲区的函数;
//--------------------------------------------------------------------------------------------------
void clr_buf(void)
{
                unsigned char k,l;
        for(k=8;k>0;k--)
                {
                command_buf=0x00;       //缓冲区内数据后移1位
                }
               for(l=16;l>0;l--)
                       {
                                        key_buf=0x00;
                                }
}
//--------------------------------------------------------------------------------------------------
//特殊按键的处理;
//--------------------------------------------------------------------------------------------------
void Skey_manage(unsigned char ss) using 3
{

        unsigned char m,n;
        if(ss==0x00)                                               //进行断码处理
                {
                for(m=16;m>0;m--)
                        {
                        key_buf=key_buf;       //缓冲区内数据后移1位
                        }
                key_buf=0xE0;            //将断码符号送入缓冲区
                for(n=16;n>0;n--)
                        {
                        key_buf=key_buf;       //缓冲区内数据后移1位
                        }
                key_buf=0xF0;
                for(n=16;n>0;n--)
                        {
                        key_buf=key_buf;       //缓冲区内数据后移1位
                        }
                key_buf=key_buf;
                key_count=key_count+3;
                sl=0;
                }
        else
                {
                for(m=16;m>0;m--)
                        {
                        key_buf=key_buf;       //缓冲区内数据后移1位
                        }
                key_buf=0xE0;            //将断码符号送入缓冲区
                for(n=16;n>0;n--)
                        {
                        key_buf=key_buf;       //缓冲区内数据后移1位
                        }
                key_buf=ss;
                key_count=key_count+2;
                sl=1;
                spe=1;
                }       
}
//--------------------------------------------------------------------------------------------------
//特殊按键PRINTSCAN的处理;
//--------------------------------------------------------------------------------------------------
void SAkey_manage(unsigned char kk) using 3
{
unsigned char m,n;
        if(kk==0x00)                                               //进行断码处理
                {
               for(m=0;m<6;m++)
                       {
                        for(n=16;n>0;n--)
                                {
                                key_buf=key_buf;       //缓冲区内数据后移1位
                                }
                        key_buf=tab4;
                        }
                key_count=key_count+6;
                spl=0;
                }
        else
                {
                for(m=0;m<4;m++)
                       {
                        for(n=16;n>0;n--)
                                {
                                key_buf=key_buf;       //缓冲区内数据后移1位
                                }
                        key_buf=tab5;
                        }
                key_count=key_count+4;
                spl=1;
                spe=1;
                }
}
//--------------------------------------------------------------------------------------------------
//特殊按键PAUSE的处理;
//--------------------------------------------------------------------------------------------------
void SSkey_manage() using 3
{       
       unsigned char m,n;
       for(m=0;m<8;m++)
               {
                for(n=16;n>0;n--)
                        {
                        key_buf=key_buf;       //缓冲区内数据后移1位
                        }
                        key_buf=tab3;
                        key_count=key_count+8;
                }
                spe=1;
}
//US级别的延时
void delayus(unsigned char a)
{
        while(--a);                //若12 M,下面有    i    delay time/us
                                //                           1    7                 调用函数3个机器周期 RET2个机器周期
                                //                           2    9
                                //                           3    11      延时20us,为delay 8        time19
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
}
/*//开机自检发送0xAA
void ssend_byte(void)
{
        unsigned char i,check,temp;
        temp=0xAA;                //16进制的位,赋值一个机器周期,寻找数据位置一个周期
        ACC=0XAA;
        check=!P;                //给bit赋值时,赋值一个机器周期,寻找数据位置一个周期,寻找位地址一个机器周期
           KBDATA=0;
           delayus(4);        //延时19us
           KBCLK=0;         //发送起始位        2个机器周期,这两个机器周期一个算在前,一个算在后面。
        _nop_();
        _nop_();
        _nop_();
        _nop_();                //nop用了补充for语句第一次运行时少用的4个机器周期
           for(i=8;i>0;i--)        //for语句第一次调用,用两个机器周期,第二次调用用6个机器周期,执行完最后用6个机器周期
                {
                delayus(11);                //延时33us
              KBCLK=1;
                delayus(2);        //延时15us
                _nop_();          
                KBDATA=(temp&0x01);//发送数据&运算双目运算符,先运算“&”之后再对KNDATA赋值,所有的赋值应该算入前面的计算       
                temp=temp>>1;                // ">>"双目运算符 赋值占用两个机器周期
                   delayus(2);        //延时15us
                KBCLK=0;          //延时1US
                }
        delayus(11);                //延时33us,发送校验位
    KBCLK=1;
        delayus(3);        //延时17us                  
        KBDATA=check; //发送校验位        三个机器周期,因为check是可变量所以调用需要3个机器周期       
           delayus(4);        //延时19us
        KBCLK=0;
        delayus(14);                //延时37us,发送停止位。
    KBCLK=1;
        delayus(4);        //延时19us                  
        KBDATA=1;         //发送停止位               
           delayus(4);        //延时19us
        KBCLK=0;
        delayus(19);        //延时49us
        KBCLK=1;        //释放时钟线
        delayus(300);        //
        }*/

dqlspzl 发表于 2009-12-9 20:47:11

自己顶一下,我觉得是 发送和接受数据部分出问题了,但是找不到·····,原来是定义的10MS扫描检测数据线,后来看别人的帖子改成扫描的方式了,不知道对不对?

nicksean 发表于 2009-12-9 21:21:24

看着头大:)

chunk 发表于 2009-12-9 22:29:54

你没有观察一下,开机自检的过程中,主机给你发下来什么数据了?

dqlspzl 发表于 2009-12-10 12:22:11

我没有示波器·····应该是发送或者接受部分有问题···,但是我自己钻牛角尖了 ,找不出来···

xingqing 发表于 2011-5-30 11:27:24

想问下 哥们的问题解决了吗能否公布下程序

xi416547162 发表于 2012-12-8 14:15:03

期待楼主的问题能早日解决
我也是新入行做pc键盘软件驱动,有个键盘在其他pc主板上可以使用,但在主板A上使用时,连续软启动,每隔一次才能正常使用(在进bios中都能用,但选系统后进问题就出现了);用示波器捕捉波形,如果进xp时有通讯就可以正常使用,没有就不能使用,他们都说是时序问题,我做了些调整还是没解决(这键盘在其他pc机可以正常使用,热重启12次没有一次出差错),标准ps2键盘可以正常使用.
也请高手指点下
页: [1]
查看完整版本: 求助菜鸟的89S52仿真PS2键盘,无法通过开机自检。