打印

单片机做PS/2键盘,初始化存在问题

[复制链接]
楼主: dosculler
手机看帖
扫描二维码
随时随地手机跟帖
21
刘前辈| | 2012-1-6 20:11 | 只看该作者 回帖奖励 |倒序浏览
本帖最后由 刘前辈 于 2012-1-6 20:25 编辑

呵呵,告诉你个秘密,可以参考。PS2接口通信实际是标准半双工UART通信(开集电级或门),11位一字节。——波特率精确125k;也就是80us一比特。——根本不需要同步时钟!用单片机串口通信模式3通信特简单,只要你知道初始化对话协议,通过之后,以后就是发送键值的问题啦!

想当初玩过之后,再看《嵌入式系统和单片机》杂志上登载的单片机I/O 口模拟键盘方法,觉得笨极了。——还作为新发现兴奋了一阵子。后来应用到项目中,从节点用一个键盘,和几百米外的控制室里的主机通信。没什么问题。

网上可以查到“单片机I/O口模拟PS2键盘接口”的**,模拟了半天,就是在模拟11位UART,太困难了。

、、

使用特权

评论回复
22
dengm| | 2012-1-7 00:57 | 只看该作者
re: 21楼 刘前辈
    你的方法是host PS2接口,  假定device一定能接收到,device发来的ack及clock都不管, 这样可靠性与兼容性都不好。LZ 是Device PS2接口.

使用特权

评论回复
23
xxdcq| | 2012-1-7 09:42 | 只看该作者
做ps2往往是高兴一时,郁闷一时
很多时候往往兴奋还没过,烦恼就接踵而至!
搞到最后就是不相信一切!

使用特权

评论回复
24
dosculler|  楼主 | 2012-1-7 10:11 | 只看该作者
做ps2往往是高兴一时,郁闷一时
很多时候往往兴奋还没过,烦恼就接踵而至!
搞到最后就是不相信一切!
xxdcq 发表于 2012-1-7 09:42

经验之谈啊,能说出这番话来的,
也可以说是被折腾过来的:D
有什么办法让我不被折腾啊,哈

使用特权

评论回复
25
dosculler|  楼主 | 2012-1-7 10:15 | 只看该作者
21# 刘前辈

正如22楼所说,我用的是device ps/2,如果不顾及host的时钟线,直接发射字节,很容易就导致开机初始化失败,
现在我已经很顾及host了,把它当爷爷来照顾了,不过发现host不给我面子,
现在恼火的正是开机初始化问题

使用特权

评论回复
26
刘前辈| | 2012-1-7 13:15 | 只看该作者
只好透露第二个秘密:  我做的也是device ps/2;而且当时只做一套设备,我觉得花那么大劲研究PS/2 实在不合算,既然别人标准键盘里的8048程序已经有了,利用一下就成了。

拆一个AT 旧键盘,(市场上还有卖16个键的PS/2接口51控制的小键盘。)老式的控制芯片是Intel-8048,硬件电路书上都有。——这是个51汇编兼容的芯片;把它的初始化程序抠出来分析一下就成了,(不需要分析全部程序)。

我当时没有耐心干这个(只卖一套的事,谁干?),就做了个三通:PC机开机时,让8048键盘控制器工作,启动时间过后,切换到我做的仅具有发送功能的PS2键盘(利用51_UART串口TDX)。
     成啦。没什么不可靠。初始化完成之后,主机即使再向键盘发什么我也不知道啦,——我根本没有接收通路(只发送不接收。)

三通芯片用的是4052.


//

使用特权

评论回复
27
dengm| | 2012-1-7 17:39 | 只看该作者
本帖最后由 dengm 于 2012-1-7 18:01 编辑

re:#25 dosculler: 当孙子不爽!!!
      爷爷可以任何时候发数据, 孙子还要给打拍子,还要ACK ..... 孙子不好当啊
    孙子要发出数据, 要等大于 50us  Idle state(Data = high, Clock = high), 才能发,
              最不爽的是, 在发数据过程中,爷爷捣乱,发来Communication Inhibited
                                      (Data =  high, Clock = low: 大于 100us) ,  要占公路,
                          孙子还要倒车1 or 2 公里 (重发1 or 2 bytes) 。

另:
   Host Request-to-Send(Data = low, Clock = high: ):那里是请求发送,
   其实是命令孙子给打拍子。

使用特权

评论回复
28
liulwn| | 2012-1-7 22:08 | 只看该作者
能做到一些名牌主机能识别的键盘一般都没问题

使用特权

评论回复
29
dengm| | 2012-1-8 13:45 | 只看该作者
名牌主机是好爷爷:
   1。在Idle state(Data = high, Clock = high) 50us后才, 发Communication Inhibited
     2。Host Request-to-Send, 等clock 远大于 2ms
     3.  没有 ASK,  耐心多发几次。

使用特权

评论回复
30
dosculler|  楼主 | 2012-1-10 16:06 | 只看该作者
本帖最后由 dosculler 于 2012-1-10 16:14 编辑

15# xxdcq
谢谢,今天才看到。
那个附件“Rabbit.GIF”(如下)是发错了还是习惯问题,一只灰兔子,很可爱,呵呵……

Rabbit.GIF (1.45 KB )

Rabbit.GIF

使用特权

评论回复
31
dosculler|  楼主 | 2012-1-10 16:08 | 只看该作者
20# dengm
这个确实很重要,send里我做了跟上面rev一样的处理,这样应该没问题了

使用特权

评论回复
32
xxdcq| | 2012-1-10 16:49 | 只看该作者
30# dosculler

使用特权

评论回复
33
xxdcq| | 2012-1-10 16:50 | 只看该作者
  呵呵!这个是公司统一邮箱,好像都有这个一个兔子!

使用特权

评论回复
34
dengm| | 2012-1-10 23:37 | 只看该作者
本帖最后由 dengm 于 2012-1-10 23:41 编辑

send() 要带参数返回: 成功发送/被Communication Inhibited。
不要在 send里 做了跟上面rev一样的处理。 重发在send/rev 外面处理。
要保证软件的结构化与层次。

使用特权

评论回复
35
dengm| | 2012-1-11 00:22 | 只看该作者
本帖最后由 dengm 于 2012-1-11 00:31 编辑

SUB_Send:
        ; input:           A   --- BYTE TO SEND
        ; OUTPUT:      C = 0 -- 成功  C=1-- Communication Inhibited
        ; USE: A, PSW,  R7, R6
        SETB P_PS2_DATA
        SETB P_PS2_CLK
        
        MOV R7, #25                    ;50us
DO_R7_1:    ; WAIT 50us idel
            JNB P_PS2_CLK,  SEND_EX_C1        
         DJNZ R7, DO_R7_1
;--------------------------------
         CLR P_PS2_CLK   ; START BIT
         MOV R7, #5
         DJNZ R7, $
         MOV R6, #10
         MOV C, P
         RRC A
DO_R6:     ; DATA 8  P 1 STOP 1
              MOV R7, #35                               ;35 us
              JNB P_PS2_CLK,  SEND_EX_C1
              CLR P_PS2_CLK
              DJNZ R7, $
              SETB  P_PS2_CLK
              MOV R7, #5                           ; 5us
              DJNZ R7, $
              JNB P_PS2_CLK,  SEND_EX_C1
              MOV P_PS2_DATA, C
              SETB C
              RRC A
              MOV R7, #15                       ;30us
DO_R7_2:
                 JNB P_PS2_CLK,  SEND_EX_C1
             DJNZ R7, DO_R7_2
         DJNZ R6, DO_R6
         JNB P_PS2_CLK,  SEND_EX_C1
         CLR P_PS2_CLK
         MOV R7, #35   ;35uS
         DJNZ R7, $
           CLR C
            SETB P_PS2_CLK
            RET

SEND_EX_C1: ;C=1-- Communication Inhibited
            SETB C
            SETB P_PS2_DATA
            RET

使用特权

评论回复
36
dosculler|  楼主 | 2012-1-11 16:27 | 只看该作者
27# dengm
这些孙子应该做的事情,相信在程序里都做完了,还有“孙子”注意的么:dizzy:

使用特权

评论回复
37
dosculler|  楼主 | 2012-1-11 16:29 | 只看该作者
26# 刘前辈
做一万套产品不是要拆1万个?

使用特权

评论回复
38
dosculler|  楼主 | 2012-1-12 19:54 | 只看该作者
35# dengm
汇编:dizzy: ,这是我Send函数,用C的,能帮我看下有没有可能错误
void PS2_Send(uchar send_ps2)   //PS 2(中控)发送出去(给PC机)
{
bit PARITY,a0,a1,a2,a3,a4,a5,a6,a7;
uchar i=0;     
PARITY= Parity(send_ps2);
    a0=(send_ps2>>0)&1;
    a1=(send_ps2>>1)&1;
    a2=(send_ps2>>2)&1;
    a3=(send_ps2>>3)&1;
    a4=(send_ps2>>4)&1;
    a5=(send_ps2>>5)&1;
    a6=(send_ps2>>6)&1;
    a7=(send_ps2>>7)&1;
    EA=0;
// send_last_ps2=send_ps2;
// CLOCK_PS2=1;   //置高检查
// DATA_PS2=1;   //置高检查
// Delay20Us();
/* //while(!CLOCK_PS2)  //(1)检测时钟线电平,如果时钟线为低,则延时50us
if(!CLOCK_PS2)
{
  Delay50Us();
  i++;
  if((i>=4) || !CLOCK_PS2)    //200us || 检测判断时钟信号是否为高,为高,则向下执行,为低,则转到(1)
  {
   EA=1;
   //主机拉低CLK100us,再下拉
   return;
  }
// break;  //主机下发数据拉低CLK100us,不过看门狗开着,不能让死循环
}
while(!CLOCK_PS2)  //(1)检测时钟线电平,如果时钟线为低,则延时50us
{
  Delay50Us();
}
if(!DATA_PS2)
{
  EA=1;
  return;
  //goto ps2_rev;
}  */
// if(!CLOCK_PS2||!DATA_PS2)//如果时钟线和数据线不都为高,则返回
// {       //注意:不加判断,以免少发码
//  EA=1;
// return;
// }
Delay20Us();//高电平设备改变数据线状态
DATA_PS2=0;//start bit
Delay40Us();
CLOCK_PS2=0;//拉低时钟线--下降沿
Delay40Us();
CLOCK_PS2=1;//释放时钟线
// if (!CLOCK_PS2)
// {
//  EA=1;
//  return ;
// }
// Delay20Us();
DATA_PS2=a0;//bit 0
Delay40Us();
CLOCK_PS2=0;//拉低时钟线--下降沿
Delay40Us();
CLOCK_PS2=1;//释放时钟线
// if (!CLOCK_PS2)
// {
//  EA=1;
//  return ;
// }
// Delay20Us();
DATA_PS2=a1;//bit 1
Delay40Us();
CLOCK_PS2=0;//拉低时钟线--下降沿
Delay40Us();
CLOCK_PS2=1;//释放时钟线
// if (!CLOCK_PS2)
// {
//  EA=1;
//  return ;
// }
// Delay20Us();
DATA_PS2=a2;//bit 2
Delay40Us();
CLOCK_PS2=0;//拉低时钟线--下降沿
Delay40Us();
CLOCK_PS2=1;//释放时钟线
// if (!CLOCK_PS2)
// {
//  EA=1;
//  return ;
// }
// Delay20Us();
DATA_PS2=a3;//bit 3
Delay40Us();
CLOCK_PS2=0;//拉低时钟线--下降沿
Delay40Us();
CLOCK_PS2=1;//释放时钟线
// if (!CLOCK_PS2)
// {
//  EA=1;
//  return ;
// }
// Delay20Us();
DATA_PS2=a4;//bit 4
Delay40Us();
CLOCK_PS2=0;//拉低时钟线--下降沿
Delay40Us();
CLOCK_PS2=1;//释放时钟线
// if (!CLOCK_PS2)
// {
//  EA=1;
//  return ;
// }
// Delay20Us();
DATA_PS2=a5;//bit 5
Delay40Us();
CLOCK_PS2=0;//拉低时钟线--下降沿
Delay40Us();
CLOCK_PS2=1;//释放时钟线
// if (!CLOCK_PS2)
// {
//  EA=1;
//  return ;
// }
// Delay20Us();
DATA_PS2=a6;//bit 6
Delay40Us();
CLOCK_PS2=0;//拉低时钟线--下降沿
Delay40Us();
CLOCK_PS2=1;//释放时钟线
// if (!CLOCK_PS2)
// {
//  EA=1;
//  return ;
// }
// Delay20Us();
DATA_PS2=a7;//bit 7
Delay40Us();
CLOCK_PS2=0;//拉低时钟线--下降沿
Delay40Us();
CLOCK_PS2=1;//释放时钟线
// if (!CLOCK_PS2)
// {
//  EA=1;
//  return ;
// }
// Delay20Us();
DATA_PS2=PARITY;//parity bit
Delay40Us();
CLOCK_PS2=0;//拉低时钟线--下降沿
Delay40Us();
CLOCK_PS2=1;//释放时钟线
// if (!CLOCK_PS2)
// {
//  EA=1;
//  return ;
// }
// Delay20Us();
DATA_PS2=1;//stop bit
Delay40Us();
CLOCK_PS2=0;//拉低时钟线--下降沿
Delay40Us();
CLOCK_PS2=1;//释放时钟线
Delay50Us();
// Delay50Us();

if(uninterrupt_flag == 0)         
  EA=1;   

}

使用特权

评论回复
39
dosculler|  楼主 | 2012-1-14 11:45 | 只看该作者
无明显问题么??
时序我看了示波器,40us整

使用特权

评论回复
40
刘前辈| | 2012-1-14 12:39 | 只看该作者
本帖最后由 刘前辈 于 2012-1-14 13:03 编辑
37#
做一万套产品不是要拆1万个?


唉!咱设计的产品最多卖出过5套。羡慕LZ能设计占领市场一万套的产品。

说一下我们老板,前年曾有一个前景不到50套的项目,他让我设计,一个月,2W报酬。实验室什么仪器都有:HP的逻辑分析仪,菊水的数字存储示波器,……我从来都没用过,让我倒交学费我都愿意干了。

所以,如果这个PS2产品让我做,市场前景多少万套我并不关心,我只关心自己的一次性的报酬。——2K有2K的干法,2W有2W的干法。

2W的干法:公司有8048仿真器,借助HP逻辑分析仪,一个月把标准PS2键盘不到1K 的汇编程序分析出来够了吧。——即使不能逐句明白,功能块总清楚了,自己的程序加在什么位置总知道了。

还有,PS/2接口标准程序有现成的,不用自己写。我就从网上下载过。
还有,《嵌入式系统和单片机》和《电子技术应用》上都刊登过PS2研究,研究所写的;找一个同系统的同学,去有偿索取一个就行了。(我老干这事。——这叫调研。)重复别人的研究?等于浪费才华和生命。LZ这么好的专注研究性格,……

、、

要不,我帮你去?

http://www.laogu.com/wz_17791.htm

、、

使用特权

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

本版积分规则