打印

调试PS/2键盘时,遇到点小问题,高手帮忙看看

[复制链接]
4818|20
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
古道热肠|  楼主 | 2008-10-31 17:13 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
古道热肠|  楼主 | 2008-10-31 17:15 | 只看该作者

贴上源码,是Keil for ARM环境下编译的.

#include "Board.h"
#include "AT91SAM7S64a.H"                       /* AT91SAMT7S64 definitions  */
#include "lib_AT91SAM7S64a.h"
#include "DataTypeDef.h"
#include "DriverTimer.h"

#define DISABLE
#define ENABLE
//sbit PS2Kbd_Data = P1^0;
//sbit PS2Kbd_Clk = P1^1;

#define PS2ClkToLow() AT91F_PIO_OutputEnable( AT91C_BASE_PIOA, PS2_CLK ) 
#define PS2ClkToHigh() AT91F_PIO_OutputDisable( AT91C_BASE_PIOA, PS2_CLK ) 
#define PS2DataToLow() AT91F_PIO_OutputEnable( AT91C_BASE_PIOA, PS2_Data ) 
#define PS2DataToHigh() AT91F_PIO_OutputDisable( AT91C_BASE_PIOA, PS2_Data )

#define PS2DataTransEnable()  AT91F_PIO_OutputDisable( AT91C_BASE_PIOA, PS2_CLK )
#define PS2DataTransDisable()  AT91F_PIO_OutputEnable( AT91C_BASE_PIOA, PS2_CLK ) 

uchar ucPS2CommErrFlag = 0;

//#define PS2KBD_DataIn T0
//#define PS2KBD_CLKIn  INT1

//初始化硬件适应于PS/2接口进行通讯
void InitPS2HardWart(void)
{
    AT91F_PIO_CfgOpendrain(AT91C_BASE_PIOA,PS2_CLK|PS2_Data);
    AT91F_PIO_CfgPullup(AT91C_BASE_PIOA,PS2_CLK|PS2_Data);
    PS2DataToHigh();
      PS2ClkToLow();
//      AT91F_PIO_MultiDriverEnable(AT91C_BASE_PIOA,PS2_CLK);
//    AT91F_PIO_MultiDriverEnable(AT91C_BASE_PIOA,PS2_Data);
}

static bool GetPS2DataStatus(void)
{
    unsigned int  n;
    
    n = AT91F_PIO_GetInput( AT91C_BASE_PIOA);

    return(n&PS2_Data);

}

static bool GetPS2ClkStatus(void)
{
    unsigned int  n;
    
    n = AT91F_PIO_GetInput( AT91C_BASE_PIOA);

    return((n&PS2_CLK) );
}

/*
static void Delay10Us(uchar ucDelayCount)
{
    register uchar  uci;

    if(ucDelayCount == 0)
    {
        return;
    }
    for( ;ucDelayCount>0;ucDelayCount--)
    {
        for(uci=0; uci<30; uci++)
        {
//            _nop_();
        }
    }
}
*/

void Delay10Us(uchar ucDelayCount)
{
    Delay_10US(ucDelayCount);
}


static void CaptureClkLow(void)
{
    while(1)
    {
        if(GetPS2ClkStatus())
        {
            break;
           }
      }

    while(1)
    {
        if(!GetPS2ClkStatus())
        {
//            if(!GetPS2ClkStatus())
//            {
                break;
//              }
           }
      }
}

static void CaptureClkHigh(void)
{
    while(1)
    {
        if(!GetPS2ClkStatus())
        {
            break;
           }
      }

    while(1)
    {
        if(GetPS2ClkStatus())
        {
//            if(GetPS2ClkStatus())
//            {
                break;
//               }
           }
      }
}

/**************************************************
功能介绍:实现向PS2口发送1个字符的功能。
入口参数: 待发送的字符
返回:       发送是否成功。true 表示成功
备注:     
***************************************************/
bool PS2_SendChar(uchar ucSendChar)
{
    uchar ucCount;
    bool ucOddValue;
    uchar ucTempVal;

    ucOddValue = true;
    ucTempVal = ucSendChar;

//    ComShowString(COM_1,"start Test pS2");

//    printf("start Send char to Ps2 Kbd ");
//先计算发送数据的奇校验值备用
    for(ucCount=0; ucCount<8; ucCount++)
    {
        if(ucTempVal & 0x01)
        {
            ucOddValue = !ucOddValue;    
        }
        ucTempVal >>= 1;
    }
//抢占PS/2总线的控制权
    PS2ClkToLow();
    PS2DataToLow();
    Delay10Us(10);        //Delay100uS
        
    DISABLE;

    PS2ClkToHigh();        //通知PS/2设备,时机已成熟

//等待PS/2设备切换角色并发起数据接收的时序
    ucTempVal = ucSendChar;
    for(ucCount=0; ucCount<8; ucCount++)
    {
        //以下函数未设超时退出机制,如果设备不响应会死循环.
        CaptureClkLow();        
        //捕获到下降沿后改变数据线的值.
        if(ucTempVal & 0x01)
        {
            PS2DataToHigh();
        }
        else
        {
            PS2DataToLow();
        }
        ucTempVal >>= 1;
        //发送到P2/2的数据位会在时钟的上升沿锁入PS/2设备中的.
       }
//发送校验位
    CaptureClkLow();
    if(ucOddValue)
    {
        PS2DataToHigh();
    }
    else
    {
        PS2DataToLow();
    }
//发送停止位    
    CaptureClkLow();
    PS2DataToHigh();

//最后一个脉冲表示设备响应
//备注:根据PS/2协议,主机发往PS/2的数据在设备没有确认前,想取消还来得及
//     方法就是我先将数据线拉低,不让设备拉低应答,设备就会丢弃接收到的数据
//     至今想不明白IBM当年设计PS/2接口时为何要加这个规定.
    CaptureClkLow();
    if(GetPS2DataStatus() == 0)
    {
        CaptureClkHigh();
        ENABLE;
        return true;
    }
    else
    {
        CaptureClkHigh();
        ENABLE;
        return false;
    }
}

//从PS/2端口获取PS/2发送的字符
static bool  PS2_ReadChar(uchar *ucGetChar)
{
    uchar  ucCount;
    bool ucOddValue;
    uchar ucTempVal;
    uchar ucResult;
    uint  uiDelayCount;


    ucOddValue = true;        

    DISABLE;
    //Host释放总线控制权,让PS/2设备转换到数据发送状态,想发就快发,待会MCU要去干别的了.
    PS2DataTransEnable();
//    Delay_10US(1);
//    PS2Kbd_Data=1;
//    PS2Kbd_Clk=1;
    //
    uiDelayCount = 0x1fffff;    //关键时间
    //捕获时钟下降沿,有超时退出机制,这段时间就是让PS/2设备响应时间
    while(--uiDelayCount)
    {
        if(!GetPS2ClkStatus())
        {
        //    DISABLE;
            break;
        }
    }

    //已经查询过了,没有数据要发上来,俺MCU去返回干别的去了.
    if(GetPS2ClkStatus())    //Repeat check 
    {
        *ucGetChar = 0;

        PS2DataTransDisable();
        ENABLE;
        return false;
    }

    //每位在时钟的下降沿被主机读入
    //读取起始位必定为0
    if(GetPS2DataStatus())
    {
        if(GetPS2DataStatus())
        {
            *ucGetChar = 0;

            ucPS2CommErrFlag = 1;
//            ComShowString(COM_1,"START BIT ERR");
    
            ENABLE;
            return false;
        }
    }
    
    //读完起始位开始读取数据位
    ucTempVal = 0x01;
    ucResult = 0;
    for(ucCount=0; ucCount<8; ucCount++)
    {
        CaptureClkLow();
        if(GetPS2DataStatus())
        {
            ucResult |= ucTempVal;
            ucOddValue = !ucOddValue;        //计算校验值
        }
        ucTempVal <<= 1;
    }

    //读取奇校验位
    CaptureClkLow();
    if(GetPS2DataStatus() && ucOddValue)
    {    //防抖动,不理想.
//        if(GetPS2DataStatus() && ucOddValue)
//        {
            ucPS2CommErrFlag = 2;
//            ComShowString(COM_1,"Odd Check ERR");
        
            ENABLE;
            return false;
//           }
    }
    
    //获取停止位,必定为1
    CaptureClkLow();
    if(!GetPS2DataStatus())
    {
//        if(!GetPS2DataStatus())
//        {

            ucPS2CommErrFlag = 3;
//            ComShowString(COM_1,"STOP BIT ERR");

            ENABLE;
            return false;
//          }
    }
//数据读取完成,置标志和结果转运
    *ucGetChar = ucResult;
    ucPS2CommErrFlag = 0;
//等待发送事件完成
    CaptureClkHigh();
//禁止PS/2设备发送新数据,俺MCU有绝对控制权,要先去看看其它事件是否发生.有按键数据先自己缓存
    PS2DataTransDisable();
    
    ENABLE;
    return true;
}

/**************************************************
功能介绍:实现从PS2口接收1个字符的功能。
入口参数: 接收字符存放的缓冲区指针
返回:       接收是否成功。true 表示成功
备注:     有延时等待发生。
***************************************************/
bool  PS2_GetChar(uchar *ucGetChar)
{
/*
    if(ucPS2CommErrFlag)
    {
        PS2_SendChar(0xFE);
        BeepShort();
       }
*/
    return (PS2_ReadChar(ucGetChar));

}
                

使用特权

评论回复
板凳
古道热肠|  楼主 | 2008-10-31 17:16 | 只看该作者

经跟踪,发现奇校验易出错.

没找到根本原因.

使用特权

评论回复
地板
古道热肠|  楼主 | 2008-10-31 17:26 | 只看该作者

获取字符函数出口很多,晚上再改改看.

估计收尾工作做得不太好.

使用特权

评论回复
5
常来21ic| | 2008-11-1 11:00 | 只看该作者

我不是高手

帮你顶

使用特权

评论回复
6
冷漠| | 2008-11-1 19:58 | 只看该作者

没那么复杂。

  如果一件事过于复杂,大多数人不愿去做。  



          ORG    0H
    AJMP     L0
    ORG     23H
    AJMP     SINT
    ORG     50H
L0:    MOV    SCON,#0D0H;     串口模式3,变波特率工作
    MOV    TMOD,#20H  ;    计数器1 模式2 工作
    MOV     PCON,#80H   ;    SMOD = 1    
    MOV     TL1,#251       
    MOV     TH1,#251       ;    波特率 =12500 bps
    SETB     TR1
    CLR     A
    MOV     R0,#60H           ;    缓冲区首址
    MOV     IP,#10H
    MOV     IE,#90H
L2:    NOP
    SJMP     L2
SINT:    JNB     RI,L3
    CLR     RI
    MOV     A,SBUF
    MOV     @R0,A
    INC     R0
L3:    NOP
    RETI
    END

程序2运行后,在PS/2键盘上顺序敲下“1、2、3、4”,退出程序,可以在内部RAM 60H-6FH 间读到“16F0161EF01E26F02625F025”。
我们知道,标准键盘总是在按下键时发出一个接通码,释放键时发出一个断开码。例如:按下“1”键时,发接通码“16H”,释放“1”键时,发断开码 “F016H”。表1 列出了 PS/2 键盘常用键的接通 / 断开码。

使用特权

评论回复
7
古道热肠|  楼主 | 2008-11-2 10:25 | 只看该作者

谢谢大家关注,回楼上朋友冷漠

看你这代码,硬是没明白,PS/2接口是同步串口,同步脉冲是由PS2设备产生的CLK来实现的.咋简单到将其按异步方式来简单采样获取由PS/2设备发来的数据了呢? 异步采样应该是采样数据线吧,那时钟线根本就没去管它了.也不是在下降沿后采样数据线了,这种方式兼容性肯定难以保证.

使用特权

评论回复
8
冷漠| | 2008-11-2 12:19 | 只看该作者

精彩就在这。

抓住关键,舍弃无关问题。

PS/2接口协议显然是按字符/字节传输,每字符11位,起始位+8位数据位+1位奇校验+1位停止位。同步脉冲宽度80us。
作为异步通信还需要什么条件?下降沿采样数据线,OSI国际标准,异步通信时所有人都是这么做的,不必多虑兼容性保证。


既然有每字符帧有起始位、停止位封装,也就是说每字符帧传输将重新修正一次同步时钟偏移,即使最古老的RC振荡器都能保证15米不错位。时代发展到了晶体振荡器,5米之内每字符重新同步,还用考虑失步、兼容么。

AT键盘内部单片机以前是8048,它没有UART串口,所以用I/O口模拟UART,发展到后来CLK管脚输出在数据传输时是冗余的。

可以做个实验,把键盘接口的CLK脚拔掉,插到PC机上,没有了同步脉冲,照样使用!

使用特权

评论回复
9
冷漠| | 2008-11-2 14:59 | 只看该作者

改变一下惯性思维。

过去古老的25针RS-232接口是带有同步时钟CLK管脚的(14、17、24脚),那是因为PC机要求能够模拟CRT终端,它要求DCE给它提供发送、接收同步时钟。它自己没有内部时钟源。(那是DTE如果没有DCE提供的时钟就不能自主发送出数据)。
可这是什么年代的技术?从8251芯片上还能看到这种技术的影子。发送、接收可以不是同一个速率。

时代、技术早就发展了。8251的发送、接收时钟输出管脚早就是冗余的了。现在随便翻一本通信技术的书,就可以找到:“......键盘与计算机的连接就是典型的异步传输方式。”

通信双方已经规定了通信速率固定为12500bps,奇校验,每字符11位,又有起始位同步双方时钟,停止位重新位同步时钟。这么完善的规约还需要传输同步脉冲么。

我当时把能够得到的所有键盘类型都实验了一遍,——最新的和十几年前报废的;联想、爱国者、IBM-XT(原装8086),AT(286)、COMPAQ,读取数据都一样可靠,从无差错。而且用逻辑分析仪同时在看传输波形。没什么意思,大家结果一致。那是一种标准,兼容的。





使用特权

评论回复
10
古道热肠|  楼主 | 2008-11-2 16:42 | 只看该作者

PS/2接口数据传输是双向的

冷漠网友虽然理论和实践上证明了可以用串行接收方式接收键盘发送来的数据,但是无法实现将数据发送到键盘.
哈哈,俺习惯按照协议来实现功能,一般不去另想其它的方法,也许是思维和行为的方式各有不同,没有谁对谁错之分的.

使用特权

评论回复
11
冷漠| | 2008-11-2 23:22 | 只看该作者

谁说无法实现将数据发送到键盘?

多说一句,我们在键盘和单片机UART之间加了一个MC14053——2通道分离器双向开关,容易理解,单输入/输出一端接键盘数据端,双输入/输出端分别接单片机UART的发送TXD、接收端RXD。当单片机向键盘发送数据时,拉低CLK,转换方向,向键盘异步发送11位字符帧。


请参考下面这篇**

《PC机键盘接口深入分析与应用设计 》
来源:单片机与嵌入式系统应用   作者:北京军区空军航空中心修理厂 安学军 梁祥 张永军 

......
我们对AT、PS2扩展键盘进行了分析。确切地说,键盘与PC机的通信是串行异步与同步相结合的方式。键盘发送到PC机的数据采用标准的串行异步通信方式(对应于8051的串行通信方式2、3)[2],即1位起始位,8位数据位(低位在前),1位奇校验位,1位停止位。由于按键速度的不一致,并为了提高设备的兼容性,又在异步通信的基础上增加了同步时钟,在时钟的上升沿对数据进行采样。也就是说数据的时钟同步和恢复由发送端控制,不需要接收端再建立同步。这样增加了一根时钟线,却简化了控制和编程。反之,PC机发往键盘的命令和数据也如此。
......

参考文献 

1    《最新实用IBM PC 软硬件技术参考大全》    中国科学院希望高级电脑技术公司,   
2    张载鸿  《微型机(PC系列)接口控制教程》    清华大学出版社,

“由于按键速度的不一致,并为了提高设备的兼容性,又在异步通信的基础上增加了同步时钟,在时钟的上升沿对数据进行采样。也就是说数据的时钟同步和恢复由发送端控制,不需要接收端再建立同步。”

我想:这段话对于PC机来说是这样,制定PS/2标准的年代,谁知道PC机键盘端口将来会发展到何等速率?

   现在是在做单片机和PS/2标准键盘的接口。没有涉及到将来和PC机兼容的以上问题。

另外,PS/2是否规定了双方通信速率必须为固定值12500bps?我没看。如果有这一点规约就不用担心兼容问题了。现在来看所有PS/2键盘都是这个速率。


使用特权

评论回复
12
芯行天下| | 2008-11-3 12:57 | 只看该作者

楼主,我是芯行天下,也是该项目的义工

楼主好,我是芯行天下,也是该项目的义工,关于PS/2解码部分我好象也给你传过一个程序,那是用LPC2148做的,我用它对全部键盘进行解码操作,并且双向通讯都没有问题,虽然只是一个程序段,但功能应该还是正常的。不知是否可以参考一下。

使用特权

评论回复
13
呆板书生| | 2008-11-3 13:21 | 只看该作者

时钟信号是必须的

虽然PS/2使用了12500bps传送速度,但也不是固定不变的

最早我做的PS/2设备时,因为没有资料,自己用8300bps传送,测试通过没问题。产品就按一直这样用,超过10年了

如果设备没有时钟信号应答,PC机根本就不工作。

使用特权

评论回复
14
冷漠| | 2008-11-3 20:11 | 只看该作者

楼主说的是PS/2键盘与单片机接口问题?

如果涉及PC机,什么信号线都不能少。

而这里的主设备是单片机,程序是用户自己编的。所以可以简化。它没涉及也不需要时钟应答信号。

使用特权

评论回复
15
古道热肠|  楼主 | 2008-11-4 11:15 | 只看该作者

哈哈,冷漠网友还真有股较真劲,值得学习

冷漠网友提出的用模拟开关切换将UART二合一用于双向异步通信,电路上有些复杂,至少占用3根口线,其实用性不佳,况且单片机的串口数量有限,一般会优先考虑用于联网及其它必须串口通讯的接口处.
在此还是要感谢冷漠网友,用您的方法串口接收键盘发送来的数据用于前期测试硬件还是蛮合适的.打通硬件通路后,后面的都好办了.

使用特权

评论回复
16
hq_y| | 2008-11-4 11:53 | 只看该作者

能经得起冷漠网友的砖头的不多~~~~~~~~`哈哈~~~~~```

使用特权

评论回复
17
冷漠| | 2008-11-4 12:41 | 只看该作者

回15楼古道热肠版主

要是加一个双向开关要占用3根I/O口线,确实不是好的设计。

实际上只占用了一根口线(同时还可以作为CLK接口线实验,另一套程序。),高电平为接收状态,低电平为发送状态。

不明白版主是怎样设计4053模拟开关的。3根口线?8个状态选择,还有2根口线(4 或者6个状态)干什么用?

设计可以有各种这样,每个人都可以不一样,每个人都会欣赏自己的设计。我也会欣赏别人的不同设计。

欣赏基点就是选择最简单的。

使用特权

评论回复
18
古道热肠|  楼主 | 2008-11-4 14:54 | 只看该作者

三根口线是指,一根信号选择线,一根TXD,一根RXD

还没有时钟线计算在内,感觉不简单.

使用特权

评论回复
19
古道热肠|  楼主 | 2008-11-4 15:10 | 只看该作者

回12楼芯行天下网友

您的代码我看过的,哈哈,看来Magic Chip是习惯用中断来完成功能,有它的优点,但俺觉得中断加查询方式更加容易理解和维护.
贴上网友芯行天下的PS/2底层函数,是用LPC2148来实现的,给大家作参考吧.

/******************************************************/
/*                                                       */
/*                                                       */
/* 文件名称:.c                                          */
/* 文件标识:                                            */
/* 摘 要:                                               */
/*                                                       */
/* 当前版本:                                            */
/* 作 者:   magicchip                                   */
/* 完成日期:                                            */
/* 修改版本:                                            */
/*                                                       */
/*                                                       */
/*********************************************************/
#include "..srcconfig.h"

/**********************************************************************************
** PS2.c操作部分.定义了ps2.c文件中的变量和常量。
** 这些量同时适用于对时钟芯片的操作.
***********************************************************************************/
struct ps2struct
{
 uint16  buf[10];        //PS2命令代码缓冲区
 uint8   flag;           //PS2操作标志
 uint8   bits;           //每字节接收的位数
 uint8   bytes;          //接收的字节数
};

#define   PS2DATA     (1<<28)      //p0.28
#define   PS2CLK      (1<<30)      //p0.30


#define  ps2txdflag  0x01           //发送标志
#define  ps2rxdflag  0x02           //接收标志
#define  ps2txdok    0x04           //以送完为1
#define  ps2rxdok    0x08           //
#define  ps2parity   0x80           //奇偶校验位.

#define  startbit       0x0001      //起始位
#define  paritybit      0x0200      //校验位
#define  stopbit        0x0400      //停止位

struct ps2struct ps2;

/**********************************************************************************
** 函数名称:   void    EINT3_Init(void)
** 函数功能:   对外部中断3进行初始化,.
** 入口参数:   无
** 出口参数:   无
** 说明:     
** create by:   magicchip
** create data: 2007/12/05
*************************************************************************************/
void    EINT3_Init(void)
{
  PINSEL1 |= ((PINSEL1 & 0xccffffff) | (0x20000000));   //EINT3,p0.30,clk = p0.30,sda = p0.28
 
  EXTMODE |= 0x08;             //EINT3边沿中断
  EXTPOLAR |= 0x00;            //EINT3下降沿中断
  EXTINT |= 0x08;                            //清除EINT3中断标志

  install_irq(EINT3_INT,EINT3Prio,(void *)IRQ_EINT3);    
  ps2.flag = (0x00 | ps2parity);
  ps2.bits = 0x00;
  ps2.bytes = 0x00;
  
}

/**********************************************************************************
** 函数名称:   void  ps2txd(uint8 txdbuf)
** 函数功能:   
** 入口参数:   无
** 出口参数:   无
** create by:   magicchip
** create data: 2007/12/06
*************************************************************************************/
void  ps2txd(uint8 txdbuf)
{
   uint16 a;
   if (ps2.bits<10)                     //接收位数小于10
   {
      ps2.flag &= ~ps2txdok;
      ps2.flag |= ps2txdflag ;
      PINSEL1 = (PINSEL1 & 0xcfffffff);   //GPIO P0.30.
      IO0DIR |= (PS2CLK|PS2DATA);         //out 
      IO0CLR = PS2CLK;                    //clk = 0  
      DelayNS(10);
      ps2.bits = 0x00;
      ps2.bytes = 0x00;
      ps2.buf[0] = (((uint16)txdbuf) | (stopbit>>1) | (paritybit>>1));
      IO0CLR = PS2DATA;                   //data = 0
      IO0DIR &= ~PS2CLK;                  //clk in
      PINSEL1 |= ((PINSEL1 & 0xccffffff) | (0x20000000));   //EINT3,p0.30,clk = p0.30,sda = p0.28

   }   


/**********************************************************************************
** 函数名称:   void  __irq  IRQ_EINT3(void)
** 函数功能:   
** 入口参数:   无
** 出口参数:   无
** create by:   magicchip
** create data: 2007/12/06
*************************************************************************************/
void  __irq  IRQ_EINT3(void)
{
  uint16 *string;
  if ((ps2.flag & ps2txdflag) == ps2txdflag)   //发送数据.
  {
    DelayNS(1);
    if (ps2.bits < 10)
    {
       if ((ps2.buf[0] & (1<<ps2.bits)) == (1<<ps2.bits))   //send 1
       {  
          IO0SET = PS2DATA;
          ps2.buf[0] ^= (paritybit>>1);
          ps2.bits++;
       }
       else                                                 //send 0
       {
          IO0CLR = PS2DATA;
          ps2.bits++;
       }
    }
    /*
    else if (ps2.bits == 9)                                //send stop
    {
       IO0SET = PS2DATA;
       ps2.bits++;
    }
    */
    else                                                  //ack
    {
       IO0DIR &= ~PS2DATA;                  //DATA in
       ps2.flag &=~ps2txdflag;
       ps2.bits = 0x00;
    }
  }
  else                                         //接收数据
  {
    if ((IO0PIN & PS2DATA) == PS2DATA)
    {
      ps2.buf[ps2.bytes] |= (1<<ps2.bits);
      if (ps2.bits < 9)
        ps2.flag ^= ps2parity;  
    }
    else
    { 
      ps2.buf[ps2.bytes] &= ~(1<<ps2.bits);
    }    
    ps2.bits++;
    if (ps2.bits == 11)
    { 
      ps2.bits = 0x00;      
      ps2.flag |= ps2rxdflag;               //接收数据标志.  
      ps2.buf[ps2.bytes] = ((ps2.buf[ps2.bytes]>>1) & 0x00ff);
      string =ps2.buf;  
      ps2.bytes=0x00;
      //                                起始位,停止位,奇偶校验位检查。
      /*
      if ((((ps2buf[ps2bytes] & paritybit) >> 2) == (ps2flag & ps2parity)) 
          && ((ps2buf[ps2bytes] & stopbit) == stopbit)
         && ((ps2buf[ps2bytes] & startbit) != startbit))
      {
        ps2.flag |= ps2parity;        
      } 
      */   
    }
  }

  EXTINT |= 0x08;                            //清除EINT3中断标志
  VICVectAddr = 0;            // 通知中断控制器中断结束   
}
 

使用特权

评论回复
20
芯行天下| | 2008-11-4 16:10 | 只看该作者

回楼主

呵呵,感觉用中断处理效率高些。当然加上查询会更好,以后要往这方面转一下了。

使用特权

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

本版积分规则

284

主题

6411

帖子

16

粉丝