这段代码在我的人生史上上演过……

键盘扫描程序段
OUTBIT equ 08002h ; 列地址
IN equ 08001h     ; 行地址

Delay: ; 延时子程序
       mov r7, #0
DelayLoop:
       djnz r7, DelayLoop
       djnz r6, DelayLoop
       ret
     
TestKey:
       mov dptr, #OUTBIT
       mov a, #0
       movx @dptr, a ; 输出线置为0
       mov dptr, #IN
       movx a, @dptr ; 读入键状态
       cpl a
       anl a, #0fh ; 高四位不用
       ret
KeyTable: ; 键码定义

       db 16h, 15h, 14h, 0ffh
       
       db 13h, 12h, 11h, 10h
       
       db 0dh, 0ch, 0bh, 0ah
       
       db 0eh, 03h, 06h, 09h
       
       db 0fh, 02h, 05h, 08h
       
       db 00h, 01h, 04h, 07h
GetKey:
       mov dptr, #OUTBIT
       mov P2, dph
       mov r0, #Low(IN)
       mov r1, #00100000b
       mov r2, #6
KLoop:
       mov a, r1 ; 找出键所在列
       cpl a
       movx @dptr, a
       cpl a
       rr a
       mov r1, a ; 下一列
       movx a, @r0
       cpl a
       anl a, #0fh
       jnz Goon1 ; 该列有键入
       djnz r2, KLoop
       mov r2, #0ffh ; 没有键按下, 返回 0ffh
       sjmp Exit
Goon1:
       mov r1, a ; 键值 = 列 X 4 + 行
       mov a, r2
       dec a
       rl a
       rl a
       mov r2, a ; r2 = (r2-1)*4
       mov a, r1 ; r1 中为读入的行值
       mov r1, #4
LoopC:
       rrc a ; 移位找出所在行
       jc Exit
       inc r2 ; r2 = r2+ 行值
       djnz r1, LoopC
Exit:
        mov a, r2 ; 取出键码
        mov dptr, #KeyTable
        movc a, @a+dptr
        mov r2, a
WaitRelease:
        mov dptr, #OUTBIT ; 等键释放
        clr a
        movx @dptr, a
        mov r6, #10
        call Delay
        call TestKey
        jnz WaitRelease
        mov a, r2
        ret

OUTBIT equ 09002h ; 列地址
IN equ 09001h     ; 行地址
 CWADD1     EQU       8000H ;写指令代码地址(E1)
DWADD1     EQU       8001H ;写显示数据地址(E1)
CRADD1     EQU       8002H ;读状态字地址(E1)
DRADD1     EQU       8003H ;读显示数据地址(E1)
CWADD2     EQU       8004H ;写指令代码地址(E2)
DWADD2     EQU       8005H ;写显示数进地址(E2)
CRADD2     EQU       8006H ;读状态字地址(E2)
DRADD2     EQU       8007H ;读显示数据地址(E2)
KEY_VALUE  EQU       29H ;键值
PD1        EQU       28H ;122/2 分成左右两半屏 122x32
COLUMN     EQU       27H ;
PAGE_SED   EQU       26H ;页地址寄存器 D1,DO:页地址
CODE_SED   EQU       25H ;字符代码寄存器
COUNT      EQU       24H ;计数器
DIR        equ       23h
CTEMP      EQU       22H
COM        EQU       21H ;指令寄存器
DAT        EQU       20H ;数据寄存器

 ORG   0000H
LJMP  start

 start:  mov  sp,#60h
 key_loop: lcall testkey
           jz    key_loop
           lcall  getkey
           cjne   a,#10h,no_show1
no_show1:  jnc    no_show2
           mov    key_value,a
           lcall  exe_key
no_show2:  sjmp   key_loop                      
           

Delay: ; 延时子程序
       mov r7, #0
DelayLoop:
       djnz r7, DelayLoop
       djnz r6, DelayLoop
       ret

TestKey:
       mov dptr, #OUTBIT
       mov a, #0
       movx @dptr, a ; 输出线置为0
       mov dptr, #IN
       movx a, @dptr ; 读入键状态
       cpl a
       anl a, #0fh ; 高四位不用
       ret
KeyTable: ; 键码定义

       db 16h, 15h, 14h, 0ffh

       db 13h, 12h, 11h, 10h

       db 0dh, 0ch, 0bh, 0ah

       db 0eh, 03h, 06h, 09h

       db 0fh, 02h, 05h, 08h

       db 00h, 01h, 04h, 07h
GetKey:
       mov dptr, #OUTBIT
       mov P2, dph
       mov r0, #Low(IN)
       mov r1, #00100000b
       mov r2, #6
KLoop:
       mov a, r1 ; 找出键所在列
       cpl a
       movx @dptr, a
       cpl a
       rr a
       mov r1, a ; 下一列
       movx a, @r0
       cpl a
       anl a, #0fh
       jnz Goon1 ; 该列有键入
       djnz r2, KLoop
       mov r2, #0ffh ; 没有键按下, 返回 0ffh
       sjmp Exit
Goon1:
       mov r1, a ; 键值 = 列 X 4 + 行
       mov a, r2
       dec a
       rl a
       rl a
       mov r2, a ; r2 = (r2-1)*4
       mov a, r1 ; r1 中为读入的行值
       mov r1, #4
LoopC:
       rrc a ; 移位找出所在行
       jc Exit
       inc r2 ; r2 = r2+ 行值
       djnz r1, LoopC
Exit:
        mov a, r2 ; 取出键码
        mov dptr, #KeyTable
        movc a, @a+dptr
        mov r2, a
WaitRelease:
        mov dptr, #OUTBIT ; 等键释放
        clr a
        movx @dptr, a
        mov r6, #10
        call Delay
        call TestKey
        jnz WaitRelease
        mov a, r2
        ret
 ; 8*16点阵字符显示程序段
EXE_KEY:    LCALL INIT
            LCALL CLEAR
            MOV CTEMP,#0
            MOV DIR,#0
            MOV PAGE_SED,#00H
            MOV COLUMN,#0
            MOV CODE_SED,KEY_VALUE
            LCALL WRI_EN816
            RET


;---------------------------------------
; 初始化程序
INIT:          MOV COM, #0E2H ;复位
               LCALL PR0
               LCALL PR3
               MOV COM, #0A4H ;关闭休闭状态
               LCALL PR0
               LCALL PR3
               MOV COM, #0A9H ;设置 1/32 占空比
               LCALL PR0
               LCALL PR3
               MOV COM, #0A0H ;正向排序设置
               LCALL PR0
               LCALL PR3
               MOV COM, #0C0H ;设置显示起始行为第一行
               LCALL PR0
               LCALL PR3
               MOV COM, #0AFH ;开显示设置
               LCALL PR0
               LCALL PR3
               RET
;------------------------------------------------
; 清屏
CLEAR:         MOV R4,#00H ;页面地址暂存器设置
CLEAR1:        MOV A,R4 ;取页地址值
               ORL A,#0B8H ;"或"页面地址设置代码
               MOV COM,A ;页面地址设置
               LCALL PR0
               LCALL PR3
               MOV COM,#00H ;列地址设置为"0"
               LCALL PR0
               LCALL PR3
               MOV R3,#50H ;一页清 80个字节
CLEAR2:        MOV DAT,#00H ;显示数据为"0"
               LCALL PR1
               LCALL PR4
               DJNZ R3,CLEAR2 ;页内字节清零循环
               INC R4 ;页地址暂存器加一
               CJNE R4,#04H,CLEAR1;RAM 区清零循环
               RET
;-----------------------------------
;1.写指令代码子程序(E1)
PR0:           PUSH DPL
               PUSH DPH
               MOV DPTR,#CRADD1 ;设置读状态字地址
PR01:          MOVX A,@DPTR ;读状态字
               JB ACC.7,PR01 ;判"忙"标志为句"0",否再读
               MOV DPTR,#CWADD1 ;设置写指令代码地址
               MOV A,COM ;取指令代码
               MOVX @DPTR,A ;写指令代码
               POP DPH
               POP DPL
               RET
;------------------------------------
;2.写显示数据子程序(E1)
PR1:           PUSH DPL
               PUSH DPH
               MOV DPTR,#CRADD1 ;设置读状态字地址
PR11:          MOVX A,@DPTR ;读状态宇
               JB ACC.7,PR11 ;判"忙"标志为"0",否再读
               MOV DPTR,#DWADD1 ;设置写显示数据地址
               MOV A,DAT ;取数据
               MOVX @DPTR,A ;写数据
               POP DPH
               POP DPL
               RET
;-------------------------------------
;3.读显示数据子程序(E1)
PR2:           PUSH DPL
               PUSH DPH
               MOV DPTR,#CRADD1 ;设置读状态字地址
PR21:          MOVX A,@DPTR ;读状态字
               JB ACC.7,PR21 ;判"忙"标志为"0"否,否再读
               MOV DPTR,#DRADD1 ;设置读显示数据地址
               MOVX A,@DPTR ;读数据
               MOV DAT,A ;存数据
               POP DPH
               POP DPL
               RET
;-------------------------------------
;4.写指令代码子程序(E2)
PR3:  PUSH DPL
      PUSH DPH
      MOV DPTR,#CRADD2 ;设置读状态字地址
PR31: MOVX A,@DPTR ;读状态字
      JB ACC.7,PR31 ;判"忙"陈志为"0"否,否再读
      MOV DPTR,#CWADD2 ;设置写指令代码地址
      MOV A,COM ;取指令代码
      MOVX @DPTR,A ;写指令代码
      POP DPH
      POP DPL
      RET
;-------------------------------------
; 5.写显示数据子程序(E2)
PR4:  PUSH DPL
      PUSH DPH
      MOV DPTR,#CRADD2 ;设置读状态字地址
PR41: MOVX A,@DPTR ;读状态字
      JB ACC.7,PR41 ;判"忙"标志为"0"否,否再读
      MOV DPTR, #DWADD2 ;设置写显示数据地址
      MOV A,DAT ;取数据
      MOVX @DPTR,A ;写数据
      POP DPH
      POP DPL
      RET
;---------------------------------------
; 6.读显示数据子程序(E2)
PR5:  PUSH DPL
      PUSH DPH
      MOV DPTR,#CRADD2 ;设置读状态字地址
PR51: MOVX A,@DPTR ;读状态字
      JB ACC.7,PR51 ;判"忙"标志为"0",否再读
      MOV DPTR,#DRADD2 ;设置写显示数据地址
      MOVX A,@DPTR ;读数据
      MOV DAT,A ;存数据
      POP DPH
      POP DPL
      RET

; 8*16点阵字符显示程序段
WRI_EN816: MOV DPTR,#CCTAB ;确定字符字模块首地址
           MOV A,CODE_SED ;取代码
           MOV B,#10H ;字模块宽度为16个字节
           MUL AB ;代码×16
           ADD A,DPL ;字符字模块首地址
           MOV DPL,A ;字模库首地址+代码×16
           MOV A,B
           ADDC A,DPH
           MOV DPH,A
           CLR 50H
           PUSH COLUMN
           PUSH COLUMN
           MOV CODE_SED,#00H ;代码寄存器借用为间址寄存器
WRI_1:     MOV COUNT,#8H ;计数器设置为8
           MOV A,PAGE_SED  ;读页地址寄存器
           ANL A,#03H ;取页地址有效值
           ORL A,#0B8H ;"或"页地址设置代码
           MOV COM,A ;设置页地址
           LCALL PR0
           LCALL PR3
           POP  COLUMN
           MOV A,COLUMN ;读列地址寄存器
           CLR C
           SUBB A,#PD1 ;列地址-模块参数
           JC WRI_2 ;<0为左半屏显示区域(E1)
           MOV COLUMN,A ;≥0为右半屏显示区域(E2)
           SETB 50H ;设置区域标志位。
WRI_2:     MOV COM,COLUMN ;设置列地址值
           JNB 50H,WRI_3
           LCALL PR3 ;区域E2
           SJMP WRI_4
WRI_3:     LCALL PR0 ;区域E1
WRI_4:     MOV A,CODE_SED ;取间址寄存器值
           MOVC A,@A+DPTR ;取汉字字模数据
           MOV DAT,A ;写数据
           ;MOV A,PAGE_SED
           JNB 50H,WRI_5
           LCALL PR4 ;区域E2
           SJMP WRI_6
WRI_5:     LCALL PR1 ;区域E1
WRI_6:     INC CODE_SED ;间址寄存器加一
           INC COLUMN ;列地址寄存器加一
           MOV A,COLUMN ;判列地址是否超出区域范围、
           CJNE A,#PD1,WRI_7
WRI_7:     JC WRI_8 ;未超出则继续
           JB 50H,WRI_8 ;在区域E2 则退出
           SETB 50H ;在区域E1 则修改成区域E2
           MOV COM,#00H ;设置区域E2列地址为"0"
           LCALL PR3
WRI_8:     DJNZ COUNT,WRI_4 ;当页循环
           MOV A,PAGE_SED ;读页地址寄存器
           JB ACC.7,WRI_9 ;判完成标志D7 位,"1"则完成退出
           INC A ;否则页地址加一
           SETB ACC.7 ;置完成位为"1"
           MOV PAGE_SED,A
           CLR 50H
           MOV CODE_SED,#8H ;间址寄存器设置为8
           LJMP WRI_1 ;大循环
WRI_9:     RET
;--------------------------------------
;字符库
CCTAB:
;0
DB 0F8H,0FCH,004H,0C4H,024H,0FCH,0F8H,000H
DB 007H,00FH,009H,008H,008H,00FH,007H,000H

;1
DB 000H,010H,018H,0FCH,0FCH,000H,000H,000H
DB 000H,008H,008H,00FH,00FH,008H,008H,000H

;2
DB 008H,00CH,084H,0C4H,064H,03CH,018H,000H
DB 00EH,00FH,009H,008H,008H,00CH,00CH,000H

;3
DB 008H,00CH,044H,044H,044H,0FCH,0B8H,000H
DB 004H,00CH,008H,008H,008H,00FH,007H,000H

;4
DB 0C0H,0E0H,0B0H,098H,0FCH,0FCH,080H,000H
DB 000H,000H,000H,008H,00FH,00FH,008H,000H

;5
DB 07CH,07CH,044H,044H,0C4H,0C4H,084H,000H
DB 004H,00CH,008H,008H,008H,00FH,007H,000H

;6
DB 0F0H,0F8H,04CH,044H,044H,0C0H,080H,000H
DB 007H,00FH,008H,008H,008H,00FH,007H,000H

;7
DB 00CH,00CH,004H,084H,0C4H,07CH,03CH,000H
DB 000H,000H,00FH,00FH,000H,000H,000H,000H

;8
DB 0B8H,0FCH,044H,044H,044H,0FCH,0B8H,000H
DB 007H,00FH,008H,008H,008H,00FH,007H,000H

;9
DB 038H,07CH,044H,044H,044H,0FCH,0F8H,000H
DB 000H,008H,008H,008H,00CH,007H,003H,000H

;A
DB 0E0H,0F0H,098H,08CH,098H,0F0H,0E0H,000H
DB 00FH,00FH,000H,000H,000H,00FH,00FH,000H

;B
DB 004H,0FCH,0FCH,044H,044H,0FCH,0B8H,000H
DB 008H,00FH,00FH,008H,008H,00FH,007H,000H

;C
DB 0F0H,0F8H,00CH,004H,004H,00CH,018H,000H
DB 003H,007H,00CH,008H,008H,00CH,006H,000H

;D
DB 004H,0FCH,0FCH,004H,00CH,0F8H,0F0H,000H
DB 008H,00FH,00FH,008H,00CH,007H,003H,000H

;E
DB 004H,0FCH,0FCH,044H,0E4H,00CH,01CH,000H
DB 008H,00FH,00FH,008H,008H,00CH,00EH,000H

;F
DB 004H,0FCH,0FCH,044H,0E4H,00CH,01CH,000H
DB 008H,00FH,00FH,008H,000H,000H,000H,000H



;------------------------------------.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值