⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sckeycode.asm

📁 PS2的按键解析驱动程序,已经在实际应用
💻 ASM
字号:
;模拟PC键盘

	?PR_ReadScKey SEGMENT  CODE
    
	?PR_SendScKey SEGMENT  CODE

	PUBLIC _ReadSCKey
	
	PUBLIC  _SendScKey

;======================发送一个字节=========================================
	RSEG  ?PR_SendScKey

_SendScKey:
	CLR EA
	//将CLK(Input) 和 DAT(iutput) 0
    ;设置数据线为输入方向
	 MOV DPTR,#7F07H
	 MOVX A,@DPTR
	 ANL A,#0F3H
	 MOVX @DPTR,A
	 
	;读取CLK线,检测CLK为高电平
	MOV DPTR,#7F01H
	MOVX A,@DPTR
	JNB ACC.3, SendSErr1	 ;如果CLK为低,退出发送
	JNB ACC.2,SendSErr1   ;如果Dat为低,退出发送,这时程序最好去读由主机传来数据
	LJMP  SendS
SendSErr1: LJMP  SendSErr

SendS:	
	;设置CLK 和 Dat为输出方向 1
	MOV DPTR,#7F07H
	MOVX A,@DPTR
	ORL A,#0CH
	MOVX @DPTR,A
	
	;输出起始位
	LCALL  Dat_LOW
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	;Clk变低
	LCALL Clk_LOW 
	LCALL YS10us
	LCALL YS10us
	LCALL YS10us
	LCALL YS10us
    
	MOV A,R7
	MOV R6,A

	MOV R1,#8


	;Clk变高
	LCALL Clk_HEI 
    LCALL YS10us
	LCALL YS10us
	LCALL YS10us
	LCALL YS10us
	;检测CLK
	LCALL Check_CLK
	JNC SendSErr
	
Send1:
	 MOV  A,R6     ;读入要送数据
	 RRC A
	 MOV  R6,A

	 MOV DPTR,#7F05H 
	 MOVX A,@DPTR   ;数据送到IO口 
	 MOV ACC.2,C
	 MOVX @DPTR,A

	 LCALL CLK_L_H;
	 
     ;检测CLK
	 LCALL Check_CLK
	 JNC SendSErr

	 DJNZ R1, Send1
	
	 ;发送校验位
	 MOV A,R7
	 JB P,Send2
	 SETB C
	 LJMP Send3
Send2:
     CLR C
Send3:
	 MOV DPTR,#7F05H
	 MOVX A,@DPTR   ;数据送到IO口 
	 MOV ACC.2,C
	 MOVX @DPTR,A
	 
	 LCALL CLK_L_H;
	 
     ;检测CLK
	 LCALL Check_CLK
	 JNC SendSErr

     ;发送停止位
	 SETB C
	 MOV DPTR,#7F05H
	 MOVX A,@DPTR   ;数据送到IO口 
	 MOV ACC.2,C
	 MOVX @DPTR,A
	 
	 LCALL CLK_L_H;
	 
     ;检测CLK
	 LCALL Check_CLK
	 JNC SendSErr

	  
SendSOK:
    ;将Clk和Dat都置为高
	MOV DPTR,#7F05H
	 MOVX A,@DPTR   ;数据送到IO口 
	 ORL A,#0CH
	 MOVX @DPTR,A

	MOV R7,#1
	SETB EA
	RET


SendSErr:
   ;将Clk和Dat都置为高
	MOV DPTR,#7F05H
	 MOVX A,@DPTR   ;数据送到IO口 
	 ORL A,#0CH
	 MOVX @DPTR,A
   MOV R7,#0
   SETB EA
   RET

;=======================接收一个字节=======================================	
	
	RSEG  ?PR_ReadScKey

_ReadSCKey:
    CLR EA
	//将CLK(Input) 和 DAT(iutput) 0
    ;设置数据线为输入方向
	 MOV DPTR,#7F07H
	 MOVX A,@DPTR
	 ANL A,#0F3H
	 MOVX @DPTR,A
	 
	;读取CLK线,检测CLK为高电平
	MOV DPTR,#7F01H
	MOVX A,@DPTR
;	JNB ACC.3, ReadSErr1	 ;如果CLK为低,退出
	JB ACC.2,ReadSErr1   ;如果Dat为高,退出接收HOST发来的数据,
	LJMP  ReadS
ReadSErr1: LJMP  ReadSErr

ReadS:	
	;设置CLK 为输出1,和 Dat为输入0
	MOV DPTR,#7F07H
	MOVX A,@DPTR
	ORL A,#08H
	MOVX @DPTR,A
    
	LCALL Clk_HEI

	MOV R0,#8
	MOV R6,#0

ReadS1:

    ;时钟从低
	LCALL Clk_LOW
	 LCALL YS10us
	 LCALL YS10us
	 LCALL YS10us
	 LCALL YS10us

	 ;Clk变高
	 LCALL Clk_HEI 
	 LCALL YS10us
	 LCALL YS10us
	 

;	 LCALL CLK_L_H            

	;读取数据
	 LCALL ReadDat
     
	 MOV A,R6
	 RRC A
	 MOV R6,A

	 LCALL YS10us
	 LCALL YS10us
     
	 DJNZ R0,ReadS1

	 ;读取校验位
	 ;时钟从低变高
	 LCALL Clk_LOW
	 LCALL YS10us
	 LCALL YS10us
	 LCALL YS10us
	 LCALL YS10us

	 ;Clk变高
	 LCALL Clk_HEI 
	 LCALL YS10us
	 LCALL YS10us
	 

;	 LCALL CLK_L_H            
	 MOV R0,#0
	;读取数据
	 LCALL ReadDat
	 MOV A,#0
	 RRC A
	 MOV R0,A
	 LCALL YS10us
	 LCALL YS10us

	 MOV R4,#0  ;存出错标志,1为出错
	 ;读取停止位
ReadStop:     
	 ;时钟从低变高
	 LCALL Clk_LOW
	 LCALL YS10us
	 LCALL YS10us
	 LCALL YS10us
	 LCALL YS10us

	 ;Clk变高
	 LCALL Clk_HEI 
	 LCALL YS10us
	 LCALL YS10us    
	 ;读取数据
	 LCALL ReadDat
	 LCALL YS10us
	 LCALL YS10us

	 JC  ReadS2
	 MOV R4,#1
	 CJNE R4,#250,ReadStop
	 SJMP ReadSErr

ReadS2:
	 CJNE R4,#0, ReadSErr

	  ;	产生应答位
	  ;设置Dat为输出方向
	 MOV DPTR,#7F07H
	 MOVX A,@DPTR
	 ORL A,#04H
	 MOVX @DPTR,A

	  ;时钟从低变高
	 LCALL Clk_LOW
	 LCALL YS10us
	 LCALL YS10us
	 ;ACK
	 LCALL Dat_LOW

	 LCALL YS10us
	 LCALL YS10us

	 ;Clk变高
	 LCALL Clk_HEI 
	 LCALL YS10us
	 LCALL YS10us 
	 CALL YS10us
	 LCALL YS10us

	 LCALL Dat_HEI

	 ;判断数据是否正确
	 ;判断奇校验
	MOV A,R0
	RRC A
	MOV A,R6
									 
	JNB P,ReadS3    ;如果P为0,    
    JNC ReadSOK     ;P!=0 && CY = 0	
 	LJMP ReadSErr
ReadS3:
    JC  ReadSOK     ;如果CY为1,说明解码成功		  
	LJMP ReadSErr

ReadSOK:
    
	;设置CLK 和 Dat为输出方向 1
	MOV DPTR,#7F07H
	MOVX A,@DPTR
	ORL A,#0CH
	MOVX @DPTR,A
	
	;将Clk和Dat都置为高
	MOV DPTR,#7F05H
	MOVX A,@DPTR   ;数据送到IO口 
	ORL A,#0CH
	MOVX @DPTR,A

	MOV A,R6
	MOV @R1,A
	MOV R7,#1

	SETB EA
	RET


ReadSErr:

    ;设置CLK 和 Dat为输出方向 1
	MOV DPTR,#7F07H
	MOVX A,@DPTR
	ORL A,#0CH
	MOVX @DPTR,A


   ;将Clk和Dat都置为高
	MOV DPTR,#7F05H
	MOVX A,@DPTR   ;数据送到IO口 
	ORL A,#0CH
	MOVX @DPTR,A
    MOV R7,#0
   SETB EA

	RET
//延时10us
     YS10us: 
          MOV R5,#23 ;延时59 22.1184MHz  0.1818(0.2) 59*0.2 = 10  
		  DJNZ R5,$
		  RET


;===========================================================
 ;将DAT拉低,
Dat_LOW:
	 MOV  DPTR,#7F05H
	 MOVX A,@DPTR
	 ANL  A,#0FBH
	 MOVX @DPTR,A
     RET
Dat_HEI:
	 ;将DAT拉高
	 MOV  DPTR,#7F05H
	 MOVX A,@DPTR
	 ORL  A,#04H
	 MOVX @DPTR,A
	 RET
Clk_LOW:
	 ;将CLK拉低
	 MOV  DPTR,#7F05H
	 MOVX A,@DPTR
	 ANL  A,#0F7H
	 MOVX @DPTR,A
	 RET
Clk_HEI:
	 ;将CLK拉高
	 MOV  DPTR,#7F05H
	 MOVX A,@DPTR
	 ORL  A,#08H
	 MOVX @DPTR,A
	 RET

Check_CLK:  ;值放在C里
    ;设置 Clk为输入
	
	 MOV DPTR,#7F07H
	 MOVX A,@DPTR
	 ANL A,#0F7H
	 MOVX @DPTR,A
	 
	;读取CLK线,检测CLK为高电平
	MOV DPTR,#7F01H
	MOVX A,@DPTR

	JNB ACC.3,CHC

	;设置Clk为输出方向
	 MOV DPTR,#7F07H
	 MOVX A,@DPTR
	 ORL A,#08H
	 MOVX @DPTR,A

	SETB C
	RET
CHC: 

	 ;设置Clk为输出方向
	 MOV DPTR,#7F07H
	 MOVX A,@DPTR
	 ORL A,#08H
	 MOVX @DPTR,A

     CLR C
     RET
    

CLK_L_H:  ;Clk由高电平变成低电平,延时40us,再变成高电平,下降沿
    	 ;Clk变低
	 
	 ;设置Clk为输出方向
	 MOV DPTR,#7F07H
	 MOVX A,@DPTR
	 ORL A,#08H
	 MOVX @DPTR,A
	 
	 LCALL Clk_LOW
	 LCALL YS10us
	 LCALL YS10us
	 LCALL YS10us
	 LCALL YS10us

	 ;Clk变高
	 LCALL Clk_HEI 
	 LCALL YS10us
	 LCALL YS10us
	 LCALL YS10us
	 LCALL YS10us

	 RET


ReadDat:  ;值放在C里
    ;设置 Clk为输入
	
	 MOV DPTR,#7F07H
	 MOVX A,@DPTR
	 ANL A,#0FBH
	 MOVX @DPTR,A
	 
	;读取CLK线,检测CLK为高电平
	MOV DPTR,#7F01H
	MOVX A,@DPTR

	JNB ACC.2,CHC1

	SETB C
	RET
CHC1: 
     CLR C
     RET


END

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -