打印

请您来找茬--->>>羸超级小奖<<<---

[复制链接]
5606|29
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
古道热肠|  楼主 | 2008-10-29 11:13 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
为了调试DIY优盘的需要,今早温故了一下早期从网下下载的PS/2接口技术的文档,哈哈,这篇文档很经典,翻译得很详尽和贴切,但在翻译时,有一个操作是错误的,您能找到吧,找到有奖.

相关帖子

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

文档可以在我的博客下载和查看

论坛300K限制,传不上来,有600多K,上传到博客去了.
相关链接:http://blog.21ic.com/user1/4538/archives/2008/52814.html

使用特权

评论回复
板凳
sz_kd| | 2008-10-29 11:17 | 只看该作者

下不了

使用特权

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

谁先找到谁得奖,依据发贴先后顺序排定

奖品就是网站DIY项目-DIY优盘与PC遥控接收器第一版的空白PCB板一块.
哈哈,第一版数量非常有限,值得收藏的哟!

使用特权

评论回复
5
古道热肠|  楼主 | 2008-10-29 11:23 | 只看该作者

备注

1、第一位快手如果放弃对PCB板的拥有权由第二名获得,依此类推
2、快递费由项目组支出,获奖者不需任何花费即可轻松得到,但要花费脑力的。

使用特权

评论回复
6
古道热肠|  楼主 | 2008-10-29 11:33 | 只看该作者

贴上俺以前用的PS/2接口的底层驱动来助兴—Q版注释

/*------------------------------------------------------------------

//作者:古道热肠
//Email:xg_2004_sy@126.com
//Blog: gdrc.bolg.21ic.com
//版本:1.0
//完成日期:2008-10-14
//硬件平台,51单片机IO口模拟PS/2协议与PS/2设备通讯
--------------------------------------------------------------------*/

//#include<conio.h>
#include "....incincludes.h"

sbit PS2Kbd_Data = P1^1;
sbit PS2Kbd_Clk = P1^2;

#define PS2ClkToLow() PS2Kbd_Clk=0 
#define PS2ClkToHigh() PS2Kbd_Clk=1 
#define PS2DataToLow() PS2Kbd_Data=0 
#define PS2DataToHigh() PS2Kbd_Data=1 

#define PS2DataTransEnable() PS2Kbd_Clk = 1
#define PS2DataTransDisable() PS2Kbd_Clk = 0

uchar ucPS2CommErrFlag = 0;

static bool GetPS2DataStatus(void)
{
//    PS2Kbd_Data=1;
    return(PS2Kbd_Data);
}

static bool GetPS2ClkStatus(void)
{
//    PS2Kbd_Clk=1;
    return(PS2Kbd_Clk);
}

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

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

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

    while(1)
    {
        if(GetPS2ClkStatus() == 0)
        {
            if(GetPS2ClkStatus() == 0)
            {
                break;
              }
           }
      }
}

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

    while(1)
    {
        if(GetPS2ClkStatus() == 1)
        {
            if(GetPS2ClkStatus() == 1)
            {
                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 data ucCount;
    bool ucOddValue;
    uchar ucTempVal;
    uchar ucResult;
    uint data uiDelayCount;


    ucOddValue = true;        

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

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

        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 = 1;
            ComShowString(COM_1,"Odd Check ERR");
        
            ENABLE;
            return false;
           }
    }
    
    //获取停止位,必定为1
    CaptureClkLow();
    if(GetPS2DataStatus() == 0)
    {
        if(GetPS2DataStatus() == 0)
        {

            ucPS2CommErrFlag = 1;
            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));

}
                

使用特权

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

PS/2驱动打个包传上来,用起来更方便

使用特权

评论回复
8
yewuyi| | 2008-10-29 12:01 | 只看该作者

和IIC太象了。。。

使用特权

评论回复
9
xusnwise| | 2008-10-29 12:27 | 只看该作者

应该是这里吧,

step 3:  release the clock line
被错误的翻译为: 释放数据线

使用特权

评论回复
10
古道热肠|  楼主 | 2008-10-29 12:30 | 只看该作者

回楼上,看走眼了吧,大不一样的.

通讯时的脉冲只能由PS/2设备生成,主机是不能生成脉冲的.相同的地方是两种协议都是同步串行通讯方式,由脉冲来同步数据位.当然硬件结构是极为相似的.

使用特权

评论回复
11
xusnwise| | 2008-10-29 12:43 | 只看该作者

说实在的翻译的太别扭了,俺宁愿看E文

说实在的翻译的太别扭了,俺宁愿看E文
没用过PS2, 刚才大致看了下全文
不认同翻译"经典" 之说.

使用特权

评论回复
12
tage| | 2008-10-29 12:59 | 只看该作者

是不是这个

在你的主程序中,至少每10ms检测时钟线是否为低。

使用特权

评论回复
13
mymystery| | 2008-10-29 13:06 | 只看该作者

第3条

这也太明显了吧 有点怀疑。。。

使用特权

评论回复
14
古道热肠|  楼主 | 2008-10-29 13:14 | 只看该作者

哈哈,这么小奖快就被抢走了.

回9楼xusnwise,您找的地方完全正确.
恭喜您,答对了!

使用特权

评论回复
15
古道热肠|  楼主 | 2008-10-29 13:18 | 只看该作者

请xusnwise与俺邮箱联系领奖事宜.

如果不需要这块PCB板,或感觉用不着,愿意发扬雷锋精神,请主动发贴申明放弃领取奖品.由后续答对者获得.

使用特权

评论回复
16
古道热肠|  楼主 | 2008-10-29 13:23 | 只看该作者

大家可以在看过文档后可以发表一下对文档的看法

实际上,关于介绍PS/2接口的文档,能找到的就这一篇比较详细,而且热心网友进行了翻译工作,找不到更好的,这个当然就是经典啦,只是让大家找个这个错误,我想应该是作者翻译时的笔误,但暇不掩瑜,能做到这种程度还是值得表扬的.

使用特权

评论回复
17
mymystery| | 2008-10-29 13:31 | 只看该作者

问个很菜的问题

额 刚刚学习PS/2协议 
主机处理接收的键值是放在中断中来处理 还是设置标志放外边处理呢,如果放外面处理会不会在处理过程中又有中断产生怎么办。。。可能问的太白痴了不过还是请帮忙解解惑

使用特权

评论回复
18
zook0k| | 2008-10-29 17:29 | 只看该作者

正确的翻译是什么?

step 3:  release the clock line
被错误的翻译为: 释放数据线

正确的翻译是什么?
没弄过ps

使用特权

评论回复
19
古道热肠|  楼主 | 2008-10-29 17:35 | 只看该作者

正确的翻译大家应该能看得懂吧-"释放时种线"

PS/2只要将时钟线拉低时,就不允许PS/2设备发送数据.
见源码
#define PS2DataTransEnable() PS2Kbd_Clk = 1
#define PS2DataTransDisable() PS2Kbd_Clk = 0
用中断方式接收较为合理,由CLK触发中断,接收完数据后,禁止PS/2设备发送就行了,但不可关太长时间,太长了就会出现键盘响应不灵的感觉.

使用特权

评论回复
20
mymystery| | 2008-10-29 17:44 | 只看该作者

顺便问一下

那是不是如果处理所需时间比较短的话就可以关外部中断来进行处理。。但是如果处理数据时间要求比较长怎么办。。比如将接收的通码转换为ascII 然后再通过串口传出去...

使用特权

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

本版积分规则

284

主题

6411

帖子

16

粉丝