📄 sckeycode.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 + -