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

📄 success_wjx3.asm

📁 在研究PC机键盘通信协议的基础上
💻 ASM
📖 第 1 页 / 共 2 页
字号:
        MOV   R4,A            ;以上3条调整待扫描行
        MOV   P1,A            ;逐行扫描,被扫描行送0
        MOV   A,P1            ;读回各列线电平
        MOV   R3,#04H         ;R3作计数器,存被扫描行的待查列数
        ANL   A,#0F0H         ;高4位为有效的列线电平
        SWAP  A               ;移到低4位
NEXT:   RRC   A               ;调整待查列
        JNC   FIND            ;被查列为低电平,按键找到,转出
        INC   R7              ;未找到,键号加1
        DJNZ  R3,NEXT         ;被扫描行的待查列未完,转回NEXT
        DJNZ  R1,SCAN         ;待扫描行数未完,转回SCAN
        SJMP  NOKEY           ;未找到按键
FIND:   MOV   P1,#0F0H
LOOSEN: MOV   A,P1
        ORL   A,#0FH
        CPL   A
        JNZ   LOOSEN          ;以上5条全扫描,等待松按
        SETB  WKLED
        LCALL DELAY100
        CLR   WKLED            ;以上3条熄灭LED再点亮,表示获得按键
        ACALL DISP            ;显示键值
        SJMP L1
        RETURN:RET
L1:     ACALL SEND            ;发送键码
NOKEY:  SETB  EX0             ;开INT0中断,以便响应以后的其它按键
        MOV   P1,#0F0H        ;置键盘行线P1.0-P1.3为0,作好响应按键的准备
        RETI

;子程序---键号转换并向PC机发送按键,入口参数:R7=键号
SEND:   MOV   A,R7
        MOV   DPTR,#TAB_KBD
        MOVC  A,@A+DPTR       ;发送键号对应的接通键码
        ACALL SEND_B
        MOV   A,#0F0H         ;发送断开键码F0
        ACALL SEND_B
        MOV   A,R7
        MOV   DPTR,#TAB_KBD
        MOVC  A,@A+DPTR       ;加发键号对应的接通键码
        ACALL SEND_B
        RET

TAB_KBD:DB    3DH             ;'7'的接通键码
        DB    3EH             ;'8'的接通键码
        DB    46H             ;'9'的接通键码
        DB    05H             ;'F1'的接通键码
        DB    25H             ;'4'的接通键码
        DB    2EH             ;'5'的接通键码
        DB    36H             ;'6'的接通键码
        DB    06H             ;'F2'的接通键码
        DB    16H             ;'1'的接通键码
        DB    1EH             ;'2'的接通键码
        DB    26H             ;'3'的接通键码
        DB    04H             ;'F3'的接通键码
        DB    45H             ;'0'的接通键码
        DB    66H             ;'BACK'的接通键码
        DB    5AH             ;'ENTER'的接通键码
        DB    0CH             ;'F4'的接通键码

;子程序---发送1个字节,入口参数:A=字节数据, 出口参数:A=原字节数据
SEND_B: MOV   22H,A           ;转存A
        MOV   C,KBCLK         ;等待PC允许发送,即KBCLK、KBDAT均未被PC拉为低电平
        JNC   CANCEL
        MOV   C,KBDAT
        JNC   CANCEL
        LCALL SLEEP
        MOV   C,P
        CPL   C               ;重要! 因为PC接收是按奇校验方式进行校验的,即8位+P位=9位为奇
        MOV   20H.0,C         ;转存奇偶校验位
        MOV   R4,#08H
        CLR   C               ;发起始位0
        MOV   KBDAT,C
        CLR   KBCLK
        LCALL SLEEP
        SETB  KBCLK
        LCALL SLEEP
        MOV   C,KBCLK         ;每发完1位都检查KBCLK是否被拉低,被拉低则放弃
        JNC   CANCEL
LOOP_S: RRC   A               ;发8位数据位
        MOV   KBDAT,C
        CLR   KBCLK
        LCALL SLEEP
        SETB  KBCLK
        LCALL SLEEP
        MOV   C,KBCLK
        JNC   CANCEL
        DJNZ  R4,LOOP_S
        MOV   C,20H.0         ;发奇偶校验位
        MOV   KBDAT,C
        CLR   KBCLK
        LCALL SLEEP
        SETB  KBCLK
        LCALL SLEEP
        MOV   C,KBCLK
        JNC   CANCEL
        SETB  C               ;发停止位1
        MOV   KBDAT,C
        CLR   KBCLK
        LCALL SLEEP
        SETB  KBCLK
        LCALL SLEEP           ;发送完毕后KBCLK、KBDAT均保持高电平
CANCEL: MOV   A,22H           ;恢复A
        RET

;子程序---接收1个字节,出口参数:A=字节数据
RECEV_B:CLR   20H.2
        MOV   R4,#08H
LOOP_R: CLR   KBCLK           ;接8位数据位
        LCALL SLEEP
        SETB  KBCLK
        LCALL SLEEP
        MOV   C,KBDAT
        RRC   A
        MOV   C,KBCLK         ;每接收1位都检查KBCLK是否被拉低,被拉低则放弃
        JNC   SKIP
        DJNZ  R4,LOOP_R
        CLR   KBCLK           ;接奇偶校验位
        LCALL SLEEP
        SETB  KBCLK
        LCALL SLEEP
        MOV   C,KBDAT
        MOV   20H.1,C
        MOV   C,KBCLK
        JNC   SKIP
STOP:   CLR   KBCLK           ;接停止位
        LCALL SLEEP
        SETB  KBCLK
        LCALL SLEEP
        MOV   C,KBCLK
        JNC   SKIP
        MOV   C,KBDAT
        JNC   STOP
        CLR   KBDAT           ;拉低KBDAT(即应答位)以通知PC接收完毕
        LCALL SLEEP
        SETB  KBDAT           ;接收完毕后KBCLK、KBDAT均保持高电平
        SETB  KBCLK
        SETB  20H.2
SKIP:   NOP
        RET

;子程序---键号转换并显示,入口参数:R7=键号
DISP:   CLR C
        MOV   A,#0FH           ;判断是否为'F4'键
        SUBB  A,R7
        JZ    FUNC4
        CLR C
        MOV   A,#0BH           ;判断是否为'F3'键
        SUBB  A,R7
        JZ    FUNC3
        CLR C
        MOV   A,#07H           ;判断是否为'F2'键
        SUBB  A,R7
        JZ    FUNC2
        CLR C
        MOV   A,#03H           ;判断是否为'F1'键
        SUBB  A,R7
        JZ    FUNC1
        CLR C
        MOV   A,#0EH           ;判断是否为'Enter'键
        SUBB  A,R7
        JNZ   JMP1
        AJMP ENTER
JMP1:   CLR C
        MOV   A,#0DH            ;判断是否为'Back'键
        SUBB  A,R7
        JZ    BACK
        CLR C
        MOV   A,R6            ;如果是数字序列开始,先清除原功能键显示,数字滚动显示
        JNZ   NUM
        ACALL LCD_CLR
NUM:    LCALL SOUNDADD
        LCALL TNUM
        INC   R6              ;记录数字按键个数
        MOV   A,R7
        MOV   @R0,A           ;数字键号存入缓冲区
        INC R0                ;指向下一个缓冲区地址
        LJMP  RETURN
FUNC1:  LCALL SOUNDADD
        MOV R2,#00H
        SJMP  ORDER
FUNC2:  LCALL SOUNDADD
        MOV R2,#00H
        SJMP  ORDER
FUNC3:  LCALL SOUNDADD
        MOV R2,#00H
        SJMP  ORDER
FUNC4:  LCALL SOUNDADD
        MOV R2,#00H
        SJMP  ORDER
ENTER:  LCALL TENTER
        SJMP  ORDER
BACK:   LCALL SOUNDADD
        MOV R2,#00H
        MOV   A,R6
        JZ    NONUM
        DEC   R6              ;去掉最后一个数字键
        MOV   A,R6
        JZ    NONUM
        LJMP  RETURN
NONUM:  NOP
ORDER:  MOV   R6,#00H         ;清除数字键已按次数
        MOV   R0,#40H         ;重置数字键存储缓冲区首址
LJMP RETURN

TAB_ASC1:DB    30H             ;'0'的ASCII码
         DB    31H             ;'1'的ASCII码
         DB    32H             ;'2'的ASCII码
         DB    33H             ;'3'的ASCII码
         DB    34H             ;'4'的ASCII码
         DB    35H             ;'5'的ASCII码
         DB    36H             ;'6'的ASCII码
         DB    37H             ;'7'的ASCII码
         DB    38H             ;'8'的ASCII码
         DB    39H             ;'9'的ASCII码

TAB_ASC: DB    37H             ;'7'的ASCII码
         DB    38H            ;'8'的ASCII码
         DB    39H             ;'9'的ASCII码
         DB    0FFH             ;'F1'的ASCII码
         DB    34H             ;'4'的ASCII码
         DB    35H             ;'5'的ASCII码
         DB    36H             ;'6'的ASCII码
         DB    0FFH             ;'F2'的假借ASCII码
         DB    31H             ;'1'的ASCII码
         DB    32H             ;'2'的ASCII码
         DB    33H             ;'3'的ASCII码
         DB    0FFH                      ;'F3'
         DB    30H                      ;'0'

;子程序---LCD显示字符,入口参数:A=字符的ASCII码
LCD_DSP:MOV   DPTR,#8100H     ;指定LCD数据口地址
        MOVX  @DPTR,A
        ACALL F_BUSY
        RET

;子程序---LCD显示清除,并设显示起始在第二行最末
LCD_CLR:MOV   DPTR,#8000H     ;指定LCD指令口地址
        MOV   A,#01H          ;清屏并置AC为0
        MOVX  @DPTR,A
        ACALL F_BUSY
        MOV   A,#(0C0H+10H)   ;设置DDRAM地址
        MOVX  @DPTR,A
        ACALL F_BUSY
        RET


LCD_SET_H:MOV   DPTR,#8000H     ;指定LCD指令口地址
          MOV   A,#38H          ;功能设置,8位接口,双行显示,5X7点阵
          MOVX  @DPTR,A
          ACALL F_BUSY
          MOV   A,#0CH          ;开显示,关光标,不闪烁
          MOVX  @DPTR,A
          ACALL F_BUSY
          MOV   A,#06H          ;显示移位,AC为增量方式
          MOVX  @DPTR,A
          ACALL F_BUSY
          MOV   A,#(80H+0CH)   ;设置DDRAM地址,显示起始在第二行最末
          MOVX  @DPTR,A
          ACALL F_BUSY
          RET
LCD_SET_L:MOV   DPTR,#8000H     ;指定LCD指令口地址
          MOV   A,#38H          ;功能设置,8位接口,双行显示,5X7点阵
          MOVX  @DPTR,A
          ACALL F_BUSY
          MOV   A,#0CH          ;开显示,关光标,不闪烁
          MOVX  @DPTR,A
          ACALL F_BUSY
          MOV   A,#06H          ;显示移位,AC为增量方式
          MOVX  @DPTR,A
          ACALL F_BUSY
          MOV   A,#(80H+0DH)   ;设置DDRAM地址,显示起始在第二行最末
          MOVX  @DPTR,A
          ACALL F_BUSY
          RET


;子程序---LCD初始化及功能设置
LCD_SET:MOV   DPTR,#8000H     ;指定LCD指令口地址
        MOV   A,#01H          ;清屏并置AC为0
        MOVX  @DPTR,A
        ACALL F_BUSY
        MOV   A,#38H          ;功能设置,8位接口,双行显示,5X7点阵
        MOVX  @DPTR,A
        ACALL F_BUSY
        MOV   A,#0CH          ;开显示,关光标,不闪烁
        MOVX  @DPTR,A
        ACALL F_BUSY
        MOV   A,#07H          ;显示移位,AC为增量方式
        MOVX  @DPTR,A
        ACALL F_BUSY
        MOV   A,#(0C0H+10H)   ;设置DDRAM地址,显示起始在第二行最末
        MOVX  @DPTR,A
        ACALL F_BUSY
        RET

;子程序---LCD软件复位
LCD_RST:MOV   DPTR,#8000H     ;指定LCD指令口地址
        LCALL DELAY20
        MOV   A,#30H
        MOVX  @DPTR,A
        LCALL DELAY20
        MOV   A,#30H
        MOVX  @DPTR,A
        LCALL DELAY20
        MOV   A,#30H
        MOVX  @DPTR,A
        LCALL DELAY20
        MOV   A,#34H          ;功能设置
        MOVX  @DPTR,A
        ACALL F_BUSY
        MOV   A,#04H          ;关显示
        MOVX  @DPTR,A
        ACALL F_BUSY
        MOV   A,#01H          ;清屏
        MOVX  @DPTR,A
        ACALL F_BUSY
        MOV   A,#06H          ;设定输入方式
        MOVX  @DPTR,A
        ACALL F_BUSY
        RET

;子程序---判断LCD是否忙,并等待直至非忙状态
F_BUSY: PUSH  DPH
        PUSH  DPL
        PUSH  PSW
        PUSH  A
        MOV   A,#0FFH
LOOP2:  MOV   DPTR,#8200H
        MOVX  A,@DPTR
        JB    ACC.7,LOOP2
        POP   A
        POP   PSW
        POP   DPL
        POP   DPH
        RET

;子程序---延时100ms
DELAY100:MOV   R4,#64H
DL4:    ACALL DELAY1
        DJNZ  R4,DL4
        RET

;子程序---延时20ms
DELAY20:MOV   R4,#14H
DL3:    ACALL DELAY1
        DJNZ  R4,DL3
        RET

;子程序---延时1ms
DELAY1: MOV   R3,#0AH
DL2:    MOV   R1,#18H
DL1:    NOP
        NOP
        DJNZ  R1,DL1
        DJNZ  R3,DL2
        RET

;子程序---延时42us,用以形成12000b/s的KBCLK
SLEEP:  MOV   R1,#14H
DL5:    DJNZ  R1,DL5
        RET

SOUNDADD:PUSH DPH
         PUSH DPL
         PUSH ACC
         mov B,#08H
         MOV A,R7
         MUL AB
         MOV P0,A
         SETB P3.5
         NOP
         CLR P3.5
         POP ACC
         POP DPL
         POP DPH
         RET




LCD_SET2:MOV   DPTR,#8000H     ;指定LCD指令口地址
          MOV   A,#38H          ;功能设置,8位接口,双行显示,5X7点阵
          MOVX  @DPTR,A
          ACALL F_BUSY
          MOV   A,#0CH          ;开显示,关光标,不闪烁
          MOVX  @DPTR,A
          ACALL F_BUSY
          MOV   A,#06                    ;显示移位,AC为增量方式
          MOVX  @DPTR,A
          ACALL F_BUSY
          MOV   A,#(0C0H+00H)   ;设置DDRAM地址,显示起始在第二行最末
          MOVX  @DPTR,A
          ACALL F_BUSY
          RET

LCD_SET_T1:MOV   DPTR,#8000H     ;指定LCD指令口地址
          MOV   A,#38H          ;功能设置,8位接口,双行显示,5X7点阵
          MOVX  @DPTR,A
          ACALL F_BUSY
          MOV   A,#0CH          ;开显示,关光标,不闪烁
          MOVX  @DPTR,A
          ACALL F_BUSY
          MOV   A,#06H          ;显示移位,AC为增量方式
          MOVX  @DPTR,A
          ACALL F_BUSY
          MOV   A,#(80H+0EH)   ;设置DDRAM地址,显示起始在第二行最末
          MOVX  @DPTR,A
          ACALL F_BUSY
          RET

LCD_SET_T2:MOV   DPTR,#8000H     ;指定LCD指令口地址
          MOV   A,#38H          ;功能设置,8位接口,双行显示,5X7点阵
          MOVX  @DPTR,A
          ACALL F_BUSY
          MOV   A,#0CH          ;开显示,关光标,不闪烁
          MOVX  @DPTR,A
          ACALL F_BUSY
          MOV   A,#06H          ;显示移位,AC为增量方式
          MOVX  @DPTR,A
          ACALL F_BUSY
          MOV   A,#(80H+0FH)   ;设置DDRAM地址,显示起始在第二行最末
          MOVX  @DPTR,A
          ACALL F_BUSY
          RET




TNUM:MOV A,#09H      ;判断按下的键是不是"2"
     CLR C
     SUBB A,R7
     JZ T20
     SJMP T21
T20:AJMP TWO

T21:  MOV A,#0CH     ;判断按下的键是不是"0"
     CLR C
     SUBB A,R7
     JZ T0

     MOV A,#01H    ;判断按下的键是不是"8"
     CLR C
     SUBB A,R7
     JZ T8
     AJMP OVER    ;都不是则置R2为“#00H”
TWO:MOV R2,#01H

   AJMP OUT
T0:MOV A,R2
   CLR C
   SUBB A,#01H
   JZ INCRE

   MOV A,R2
   CLR C
   SUBB A,#02H
   JZ INCRE
   AJMP OVER
T8:MOV A,R2
   CLR C
   SUBB A,#03H
   JZ INCRE
   AJMP OVER
TENTER:MOV A,R2
       CLR C
       SUBB A,#04H
       JZ SUCCE
       ACALL SOUNDADD
       SJMP OVER
SUCCE: MOV A,#90H
       MOV P0,A
       SETB P3.5
       NOP
       CLR P3.5
       AJMP OVER

INCRE:INC R2
      AJMP OUT
OVER:MOV R2,#00H
OUT: RET


        ;编译到此前为止
        END

⌨️ 快捷键说明

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