Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2152491
  • 博文数量: 361
  • 博客积分: 10828
  • 博客等级: 上将
  • 技术积分: 4161
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-20 14:34
文章分类

全部博文(361)

文章存档

2011年(132)

2010年(229)

分类:

2010-04-06 20:01:31

PS2协议:
 
设计目的:
1.熟悉PS/2协议的原理
2.学习单片机的使用
设计内容:
依照PS/2协议,在51芯片上开发汇编程序,使得按下开发板上的按键时,能够在PC机上输出a、b、c。
实验环境:
开发板、STC12C2052AD芯片、PS/2线、PC机、Keil软件、STC-ISP程序下载器
相关参数:
单片机振荡频率6MHz(具体情况请看此型号单片机用户手册)
指令周期0.5微秒(51型单片机的指令周期是其振荡频率的12分之一)
PS/2连接器引脚定义(见参考文献《PS/2技术参考》)
能够接受的键盘时钟信号频率10-20KHz(最大33KHz,推荐设为15KHz)
 
设计思想:
使用开发板上的按钮产生中断信号,使单片机进入相应的中断处理程序,从而向PC机发送相应的扫描码。PC机主板中有一个解码芯片,此芯片在收到扫描码之后,引发PC机操作系统的中断(I/O的中断),转到操作系统中的中断处理程序,从面在系统中输出相应字符。
原理:
实际的通用键盘上的每一个键都对应一个唯一个扫描码,这些键会在极短的时间内被扫描一遍,以确认它们有没有被按下,如果某个键被按下了,就发送其相应的扫描码。而在开发板上,51芯片有三个按键,对应芯片上的两个中断口和一个定时/计数器输入口。中断接口可以直接使用,当按下键时就触发中断,而定时/计数器需要设置为初始值为FFH,一旦按下键便会溢出而产生中断的计数器。
主机与键盘有四根线相连,时钟信号数、数据线、接地线、电源线。
时钟信号在任何时刻都是由键盘产生的,PC机在时种的下降沿接收数据线上的信号,要是PC机向键盘发送数据,则键盘在时钟的上升沿接收数据线上的数据。虽是由键盘产生时钟信号,但是PC机对总线有着绝对的控制权,只要其将时钟线拉低(高低电平信号有这样的特性:只有一端的信号为低电平,则整条线的信号都为低电平。这就是为什么要向单片机I/O口输出一个信号,要先将外部输入单片机这个I/O口的信号释放(拉高)。否则输出的永远都是低电平),就要以抵制键盘的输出。
总线上有这些几种状态:
1、PC等待键盘输出状态(键盘可以输出状态):CLK=1,DATA=1;
2、键盘等待PC输出状态(PC可以输出状态):CLK=1,DATA=0(这个状态之前还有一些状态要生产生的,详情请见参考文献《PS/2技术参考》)
3、正在输出状态:此时的时钟线与数据线上的信号没有定值,依据所要发送的数据不同而不同,CLK=X,DATA=X
  键盘从外部存储器中读取相应键位的扫描码,当要改变某个键所要发送的扫描码时,只需改变外部存储器中对应位置的扫描码,这样就可以方便地改变某键所要发送的扫描码。在存放扫描码时,只需将扫描码按顺序存放,如E0,70按存储地址从小到大顺序地排列。因为通码(make code)最多只有两个十六进制数,且如有两个则第一个必是E0H,而断码(break code)最多只有三个,且如果有三个,则第一个必是E0H,如果有二个,则第一个必是F0H。所以,当发送时,如果发现第一个是E0H或F0H的话,则再发送其后的一个扫描码。
注意事项:
1、  发送8个数据位时,是低位先发送(least significant bit first),如果是用高位先发送,主机自然是无法识别会发送的数据,会报警;
2、  如果想要精确计算时间,那么像子程序调用语句会占用两个指令周期也应该考虑到;
3、  连接线应该连在指示灯靠近51芯片的一端,否则无法接收到主机发来的信号;PS/2
4、  汇编程序前的org 语句必须按其指示的地址大小排列,小的在前,大的在后;
 
程序:
;=======================================
;program
;check clk and data before every 8 bit data sending
;a function is created for send all 11bit data
;a function is created for parity calculating
;CAPSLOCK :BIG LETTER P1.3=0,SMALL LETTER P1.3=1 
;=======================================

;=======================================
;VARS USED LOCALY
;R0 IS USED LOCALY AS A COUNTER
;20H.1 20H.2 20H.3 20H.4 IS USED IN FUNCTION AS TEMP VAR
;R3,R4,R5 USED LOCALLY IN DELAY()

;===================================
;Define Samples
;====================================
MCLK EQU P1.2    ;VALUE OF CLOCK LINE
MDATA EQU P1.1    ;VALUE OF DATA LINE
SCAN EQU R1        ;VALUE OF THE SCAN CODE
RECV EQU R2        ;VALUE RECEIVED BY KEYBOARD
RECV2 EQU R6    ;THE VALUE RECEIVED SECONDLY
NEXTBIT EQU CY   ;VALUE OF THE BIT WILL SENT NEXT
PARITY EQU 20H.1   ;VALUE OF PARITY
TEMP   EQU 20H.2   ;THIS BIT IS FOR TEMPORITARY USE
TEMP1  EQU 20H.3   ;THIS BIT IS FOR TEMP USE
TEMP8BIT EQU 21H
LOOPCOUNTER EQU 30H ;COUNTER SPECIAL FOR SENDALLBIT
SCROLLLOCK EQU P1.5
CAPSLOCK EQU P1.6
NUMLOCK EQU P1.7
ERROR_LIGHT EQU P1.4          ;PARITY ERROR
ERROR_LIGHT_STOPBIT EQU P1.3  ;STOP BIT RECEIVE ERROR
;===================================
 
;===================================
;ORG
;===================================
ORG 00H
JMP MAIN
ORG 0003H
LJMP K1DOWN
ORG    000BH
LJMP K3DOWN
ORG 0013H
LJMP K2DOWN
 
;============================================================
;MAIN
;============================================================
MAIN:
;==============================
;SET INTERRUPTER AND TIMER
    mov ie,#10000101B ;中断使能
    mov ip,#00H ;中断优先
    mov tcon,#00000101b ;中断为电平触发
    ;TIME0 AS A BUTTON
    MOV TMOD,#06H
    MOV TH0,#0FFH
    MOV TL0,#0FFH
    SETB ET0
    SETB TR0
;==============================
 
 

;==============================
;SET CLK AND DATA LINE TO NORMAL STATUS
    SETB MCLK
    SETB MDATA
;==============================
    SETB CAPSLOCK ;CAPSLOCK OFF(1)
    SETB NUMLOCK  ;NUMLOCK OFF(1)
    SETB SCROLLLOCK     ;SCROLLLOCK OFF(1)
CHKSTATUS:
    JNB MCLK,CHKSTATUS    ;IF MCLK==0 THEN GOTO CHKSTATUS
    JB  MDATA,CHKSTATUS      ;IF MDATA==1 THEN GOTO CHKSTAUS
    ;NOW MCLK=1 AND MDATA =0 ,READY TO RECEIVE DATA FROM PC
    LCALL RECV_CHK_SEND   ;RECEIVE DATA FROM PC    
LJMP CHKSTATUS     ;WAIT FOR BREAK
;============================================================
;///////MAIN
;============================================================
 
 
 

;===============================================================================================
;                            AREA FOR FUNCTION             
;===============================================================================================
LJMP ENDOFFILE

;====================================
;IN THIS FUNCTION:  RECEIVE ALL 10BIT DATA BY RECEIVEALLBIT() AND CHK WHETHER IT'S CORRECT THEN SEND CORRESPONDING SCANCODE TO PC
;====================================
RECV_CHK_SEND:
    CLR P1.0    ;INDICATE START RECEIVEING
    LCALL RECEIVEALLBIT ;RECV PARITY TEMP1
    MOV A,RECV
    CJNE A,#0EDH,RECV_CHK_SEND_END

    ;=====================
    ;RECV==EQ NOW SET LED
    ;CHKSTATUS_2:
    ;    JNB MCLK,CHKSTATUS_2    ;IF MCLK==0 THEN GOTO CHKSTATUS
    ;    JB  MDATA,CHKSTATUS_2      ;IF MDATA==1 THEN GOTO CHKSTAUS
        LCALL DELAY50
        LCALL DELAY50
        LCALL RECEIVEALLBIT ;RECV PARITY TEMP1
       
       
        ;========================
        ;THE CODE IS RIGHT AFTER THIS  ,TESTED BY MOV "RECV,#00000110"
        MOV A,RECV
        RRC A        ;NOW C=LEAST BIT OF A
        CPL C        ;PC: C=1 ON   ;C=0 OFF NOW IN KEYBOARD C=1 OFF(LIGHT OFF) C=0 ON(LIGHT ON)
        MOV SCROLLLOCK,C
        RRC A        ;NOW C=LEAST BIT OF A
        CPL C        ;PC: C=1 ON   ;C=0 OFF NOW IN KEYBOARD C=1 OFF(LIGHT OFF) C=0 ON(LIGHT ON)
        MOV NUMLOCK,C
        RRC A        ;NOW C=LEAST BIT OF A
        CPL C        ;PC: C=1 ON   ;C=0 OFF NOW IN KEYBOARD C=1 OFF(LIGHT OFF) C=0 ON(LIGHT ON)
        MOV CAPSLOCK,C
        SETB P1.0
    LJMP RECV_CHK_SEND_END
    ;/====================
RECV_CHK_SEND_END:
RET
;====================================
;////////IN THIS FUNCTION:  RECEIVE ALL 10BIT DATA BY RECEIVEALLBIT() AND CHK WHETHER IT'S CORRECT THEN SEND CORRESPONDING SCANCODE TO PC
;====================================
 
 
;====================================
;RECIEVE ALL THE 10BIT DATA FROM PC    AND CHECK WHETHER IT'S RIGHT
;SAVE THE 8BIT DATA TO RECV
;TEMP1: PARITY FIGURED OUT
;PARITY: PARITY RECEIVED
;====================================
RECEIVEALLBIT:
    MOV LOOPCOUNTER,#0008H
    RECV8BIT_LOOP:
        LCALL RECEIVEONE  ;GET ONE BIT AND SAVE IT TO CY
        RRC A              ;RIGHT MOVE THIS BIT TO A
        DJNZ LOOPCOUNTER,RECV8BIT_LOOP  ;LOOP FOR 8 TIMES
        MOV C,P                ;C=P(THIS DOUBLE PARITY JUST RECEIVED
        CPL C                ;CHANG TO ODD PARITY
        MOV TEMP1,C            ;STORE THE ODD PARITY TO TEMP1
       
        MOV RECV,A          ;RECV=A
        LCALL RECEIVEONE  ;GET PARITY BIT
        MOV PARITY,C      ;PARITY=C
        LCALL RECEIVEONE  ;PC PULL UP DATA LINE
        MOV TEMP,C          ;RECEIVE TERMINAL BIT(1)
        ;MOV P1,RECV ;JUST FOR TESTING
       
        JNB MDATA,STOPBIT_ERROR    ;  1==MDATA THEN  RECEIVEALLBIT_ERROR
        ;SEND ACK       
        LCALL SENDACK
        MOV C,TEMP1    ; C = PARITY FIGURED OUT
        MOV A,#00H     ;A=OOH
        RRC A            ;SAVE C TO A
        MOV TEMP8BIT,A  ;SAVE A TO TEMP8BIT
        MOV C,PARITY
        MOV A,#00H     
        RRC A
        CJNE A,TEMP8BIT,PARITY_ERROR
        ;DATA RECEIV SUCCESSFUL
        MOV SCAN,#00H
        LCALL SENDALLBIT
        ;IF THE PROGRAM CAN RUN HERE,INDICATE ALL IS IN GOOD CONDICION
        ;SCAN 00H TO TELL PC ALL IN IN GOOD
        ;MOV SCAN,#00H
        ;LCALL SENDALLBIT
        LJMP ENDOFSENDALLBIT
        ;===================
        ;THE PARITY IS WRONG ,SO KEYBOARD RECEIVED A WRONG DATA
        PARITY_ERROR:
            CLR ERROR_LIGHT
            ;MOV SCAN,#0FFH
            ;LCALL SENDALLBIT
        ;/==================
        LJMP ENDOFSENDALLBIT
 
        ;===================
        ;STOPBIT ERROR
        STOPBIT_ERROR:
            CLR ERROR_LIGHT_STOPBIT
            ;MOV SCAN,#0FFH
            ;LCALL SENDALLBIT
        LJMP ENDOFSENDALLBIT
                   
ENDOFSENDALLBIT:       
RET
;====================================
;/////////RECIEVE ALL THE 10BIT DATA FROM PC    AND CHECK WHETHER IT'S RIGHT
;/////////SAVE THE 8BIT DATA TO RECV
;====================================

;====================================
;SENDACK
;====================================
SENDACK:                            
    LCALL DELAY15
    CLR MDATA
    LCALL DELAY5
    CLR MCLK
    LCALL DELAY40
    SETB MCLK
    LCALL DELAY5
    SETB MDATA
RET
;//==================================
 
 
;====================================
;RECEIVE ONE BIT DATA FROM PC
;SAVE THIS BIT TO CY
;====================================
RECEIVEONE:
    LCALL DELAY20
    CLR MCLK
    LCALL DELAY40
    SETB MCLK
    LCALL DELAY20
    MOV C,MDATA       ;SAVE THIS BIT OF DATA TO CY,SAVE IT TO RECV LATER
RET
;====================================
;/////RECEIVE ONE BIT DATA FROM PC
;====================================
 
;====================================
;INVOKE THIS FUNCTION WHEN K1 IS DOWN
;====================================
K1DOWN:       
    MOV SCAN,#01CH
    LCALL SENDALLBIT
    MOV SCAN,#0F0H
    LCALL SENDALLBIT 
    MOV SCAN,#01CH
    LCALL SENDALLBIT
    ;LCALL DELAY   ;DON'T PRINT SO FAST
RETI
;====================================
;//////INVOKE THIS FUNCTION WHEN K1 IS DOWN
;====================================

;====================================
;INVOKE THIS FUNCTION WHEN K2 IS DOWN
;====================================
K2DOWN:       
    MOV SCAN,#032H
    LCALL SENDALLBIT
    MOV SCAN,#0F0H
    LCALL SENDALLBIT 
    MOV SCAN,#032H
    LCALL SENDALLBIT
    ;LCALL DELAY   ;DON'T PRINT SO FAST
RETI
;====================================
;//////INVOKE THIS FUNCTION WHEN K2 IS DOWN
;====================================
 
;====================================
;INVOKE THIS FUNCTION WHEN K3 IS DOWN
;====================================
K3DOWN:       
    MOV SCAN,#021H
    LCALL SENDALLBIT
    MOV SCAN,#0F0H
    LCALL SENDALLBIT 
    MOV SCAN,#021H
    LCALL SENDALLBIT
    ;LCALL DELAY   ;DON'T PRINT SO FAST
RETI
;====================================
;//////INVOKE THIS FUNCTION WHEN K3 IS DOWN
;====================================
 
 
;====================================
;SEND ALL 11 BIT DATA
;====================================
SENDALLBIT:
    ;THE VAR SCANCODE MUST BE SET BEFORE THE FUNCTION

    ;SET CLK AND DATA LINE TO 1
    INIT:
        SETB MCLK;
        SETB MDATA;
    ;CHECK WHETHER THE CLK AND DATA IS IN STATE THAT CAN TRANSFER DATA
    CHKCLKHIGH:
        JNB MCLK,CHKCLKHIGH ;IF CLK=0 THEN GOTO CHKCLKHIGH ELSE CONTINUE actually,this is the cache,wait for clk=1 to send the data
        LCALL DELAY50      ;DELAY 50us
        JNB MCLK,CHKCLKHIGH ;
        JNB MDATA,CHKCLKHIGH;IF DATA=0 THEN GOTO CHKCLKHIGH ELSE CONTINUE
        ;NOW CLK=1 FOR 50US AND DATA=1
        LCALL DELAY20;     ;DELAY 20US
    ;================================
    ;CLK AND DATA CHECK FINISHED ,START DATA TRANSFAN
    ;================================
    STARTSEND:
        CLR NEXTBIT ;SET START BIT                         ;1 PR
        LCALL SENDBIT;SENT THE START BIT                 ;170 PR
        ;SEND SCAN CODE   
        ;NOW SCAN IS SET BEFOR SENDALLBIT()                                
        ;MOV SCAN,#035H ;LET SCAN= THE SCAN CODE OF KEY A ;2 PR
        LCALL SENDSCAN ;SEND THE SCAN CODE                 ;1123 PR
    ;    SEND PARITY ; #### COULD BE BETTER IN SENDING PARITY  #########
        LCALL CALPARITY
        MOV C,PARITY
        LCALL SENDBIT                                     ;140 PR
        ;SEND TERMINAL SIGN
        SETB NEXTBIT   ;TERMINAL SIGN=1                     ;1 PR
        LCALL SENDBIT                                     ;140 PR
        LCALL DELAY50     ;DELAY 50us
        LCALL DELAY20     ;DELAY 50us
        ;FINISHED SENDING DATA    USED 1950 PERIODS

RET ;SENDALLBIT END
;=====================================

;=====================================
;long time delay
;=====================================
Delay:
 
    MOV   R3, #000H   
    MOV   R4, #000H   
    MOV   R5, #0DH
Delay_Loop:   
    DJNZ  R3, Delay_Loop   
    DJNZ  R4, Delay_Loop   
    DJNZ  R5, Delay_Loop   
RET
;=====================================
 
 
;=====================================================
;SEND THE SCAN CODE IN VAR SCAN
;PERIODS:1123 PR
;=====================================================
SENDSCAN:
    CLR C                         ;1 PR
    MOV A,SCAN                     ;2 PR
                                
    RRC A ;MOVE RIGHT             ;1 PR
    LCALL SENDBIT  ;SEND 7TH     ;140 PR
    RRC A ;MOVE RIGHT             ;1 PR
    LCALL SENDBIT  ;SEND 6TH     ;140 PR
    RRC A ;MOVE RIGHT             ;1 PR
    LCALL SENDBIT  ;SEND 5TH     ;170 PR
    RRC A ;MOVE RIGHT             ;1 PR
    LCALL SENDBIT  ;SEND 4TH     ;140 PR
    RRC A ;MOVE RIGHT             ;1 PR
    LCALL SENDBIT  ;SEND 3TH     ;140 PR
    RRC A ;MOVE RIGHT             ;1 PR
    LCALL SENDBIT  ;SEND 2TH     ;140 PR
    RRC A ;MOVE RIGHT             ;1 PR
    LCALL SENDBIT  ;SEND 1TH      ;140 PR
    RRC A ;MOVE RIGHT             ;1 PR
    LCALL SENDBIT  ;SEND 0TH      ;140 PR
RET
;=====================================================
 
 
 
;=====================================================
;SEND THE NEXTBIT
;PERIODS:138 PERIODS
;=====================================================
SENDBIT:
    MOV MDATA,C             ;1 period
    LCALL DELAY20        ;42 PERIODS
    CLR MCLK          ;PULL DOWN THE CLOCK LINE
    LCALL DELAY40        ;82 PERIODS
    SETB MCLK            ;1 PERIODS
    LCALL DELAY20        ;12 PERIODS
RET
;=====================================================
 
 

;======================================================
;SUB FOR DELAY 16US
;RAM USED:R0
;======================================================
DELAY16:
    MOV R0,#003H ;2
    DELAY16_IN:DJNZ R0,DELAY16_IN;THIS COMMAND WILL BE EXCUTE FOR 15 TIMES,    2period
RET
;======================================================

;======================================================
;SUB FOR DELAY 32US
;RAM USED:R0
;======================================================
DELAY32:
    MOV R0,#00EH ;
    DELAY32_IN:DJNZ R0,DELAY32_IN;THIS COMMAND WILL BE EXCUTE FOR 31 TIMES,    2period
RET
;======================================================
;======================================================
;SUB FOR DELAY 50US correct?
;RAM USED:R0
;======================================================
DELAY50US:
    MOV R0,#01aH ;
    DELAY50_LOOP:DJNZ R0,DELAY50_LOOP;THIS COMMAND WILL BE EXCUTE FOR 31 TIMES,    2period
RET
;======================================================
 
 
;======================================================
;SUB FOR DELAY 20US
;RAM USED:R0
;periods:TOTAL 40PERIODS
;======================================================
DELAY20:
    MOV R0,#013H ;RUN 19TIMES 2period
    DELAY20_IN:DJNZ R0,DELAY20_IN;THIS COMMAND WILL BE EXCUTE FOR 19 TIMES,    2period
RET
;======================================================
 
;======================================================
;SUB FOR DELAY 5US
;RAM USED:R0
;periods:
;======================================================
DELAY5:
    MOV R0,#004H ;RUN 10TIMES ;2period
    DELAY5_IN:DJNZ R0,DELAY5_IN;THIS COMMAND WILL BE EXCUTE FOR 4 TIMES,    2period
RET
;======================================================
;======================================================
;SUB FOR DELAY 20US      correct?
;RAM USED:R0
;periods:TOTAL 40PERIODS
;======================================================
DELAY20US:
    MOV R0,#00DH ;RUN 19TIMES 2period
    DELAY20US_LOOP:DJNZ R0,DELAY20US_LOOP;THIS COMMAND WILL BE EXCUTE FOR 19 TIMES,    2period
RET
;======================================================
 

;======================================================
;SUB FOR DELAY 50US
;RAM USED:R0
;PERIODS:100 PERIODS
;======================================================
DELAY50:
    MOV R0,#0B1H
    DELAY50_IN:DJNZ R0,DELAY50_IN;
RET
;======================================================
 
 
;======================================================
;SUB FOR DELAY 30US
;RAM USED:R0
;PERIODS:60 PERIODS
;======================================================
DELAY30:
    MOV R0,#01DH
    DELAY30_IN:DJNZ R0,DELAY30_IN;
RET
;======================================================
 

;======================================================
;SUB FOR DELAY 15US
;RAM USED:R0
;======================================================
DELAY15:
    MOV R0,#00EH
    DELAY15_IN:DJNZ R0,DELAY15_IN;
RET
;======================================================
 
 
;======================================================
;SUB FOR DELAY 40US
;RAM USED:R0
;PERIODS:80 PERIODS
;======================================================
DELAY40:
    MOV R0,#27H
    DELAY40_IN:DJNZ R0,DELAY40_IN;
RET
;======================================================
 
 
;======================================================
;CACULATE THE PARITY OF THE CODE
;RAM CHANGED:A,C,PARITY
;INPUT :SCAN
;RETURN VAR:PARITY
;======================================================
CALPARITY:
    MOV A,SCAN
    MOV C,P
    CPL C
    MOV PARITY,C
RET
;======================================================

;===================================================================================================================
ENDOFFILE:
END ;END OF THE PROGRAM

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/manio/archive/2007/02/03/1501654.aspx
阅读(2891) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

天行剑06162014-06-06 10:16:18

请问有没有用c语言写的版本呢?汇编太难懂了…