打印

搞定PS/2接口的底层驱动,找到原程序中的BUG

[复制链接]
2021|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
古道热肠|  楼主 | 2008-11-4 16:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
先贴上新的PS/2接口字符接收函数.

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


    ucOddValue = false;        

    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();
    bTemp = GetPS2DataStatus();
//    if(GetPS2DataStatus() && ucOddValue)         //BUG
    if(GetPS2DataStatus() == ucOddValue) //奇校验,数据累加为0 ,校验位为1,累加和为1时,校验位为0
    {    //防抖动,不理想.
//        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;
}

相关帖子

沙发
古道热肠|  楼主 | 2008-11-4 16:10 | 只看该作者

与硬件相关的函数不规范是造成BUG的元凶之一

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

    if(n&PS2_Data)
    {
        return  true;

    }
    else
    {
        return false;
    }

}

//最大的改变是,返回值用统一定义的布尔值来返回

使用特权

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

分析一下奇校验是如何实现的.欢迎大家拍砖.

1.先定义一个布尔变量.
 bool ucOddValue;
2.对布尔变量赋初值:
  ucOddValue = false;        
3.根据接收到串行数据位为0或1进行相应的处理,为1时要取反.
  ucOddValue = !ucOddValue;        //计算校验值    使用逻辑非操作
4.根据计算结果与读取到的校验位值进行判定
if(GetPS2DataStatus() == ucOddValue) //奇校验,数据累加为0 ,校验位为1,累加和为1时,校验位为0

//注意事项,只有逻辑值有二个状态,非真即假,
//         逻辑操作只有 && || 和!三种操作

使用特权

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

使用特权

评论回复
5
s46410864| | 2008-11-4 16:58 | 只看该作者

我拍...........^^

我可不敢拍LZ砖头......


所以只能灌水....我灌!!!

使用特权

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

本版积分规则

284

主题

6411

帖子

16

粉丝