KEYCARD     BIT    00H             ;用于标志是否有键按下
KEYCOU  EQU    5AH       ;用于记录按下键的次数
    ORG     0000H     ;程序开始
    AJMP    START
    ORG     30H      ;为避免占用中断向量区,主程序从30H开始
START:
    MOV    SP,#5FH     ;设置堆栈的初始地址
    MOV    P3,#0FH     ;P3,P2,P0的初始化
    MOV    P2,#00H
    MOV    P0,#0FFH
    CLR    KEYCARD     ;有按键标志清0
 MOV    KEYCOU,#0       ;计数初值赋0
LOOP:           ;循环扫描键盘
    ACALL  KEY_CHECK
    JNB    KEYCARD,DISPLAY
    INC    KEYCOU
DISPLAY:          ;显示程序
 MOV    A,KEYCOU     ;选显示第一位高位
 DA     A
 ANL    A,#0xF0        ;获得高四位
 SWAP   A      ;将A的高四位和低四位对调
 MOV    DPTR,#TAB    ;获得对应的显示码
 MOVC   A,@A+DPTR
 MOV    P0,A         ;把显示码传至A口
 MOV    P2,#01H        ;选通P2.0,显示
 ACALL  DELAY1S
 MOV    A,KEYCOU
 DA     A
 ANL    A,#0x0F
 MOVC   A,@A+DPTR
 MOV    P0,A
 MOV    P2,#02H     ;选通P2.1,显示
 ACALL  DELAY1S
    AJMP    LOOP
KEY_CHECK:       ;看有没有键按下
    MOV    A,P3
    ANL    A,#0FH
    CJNE    A,#0FH,KEY_CER   ;如果读入的与写出的不相等,延时消抖
    CLR    KEYCARD
    RET
KEY_CER:       ;延时,再读入,看是否真的有键按下
    ACALL    DELAY1S
    MOV    A,P3
    ANL    A,#0FH
    CJNE    A,#0FH,KEY_CE
    CLR    KEYCARD
    RET
KEY_CE:
 MOV     A,P3     ;直等到按键放下,则算作一次
 ANL     A,#0FH
 CJNE    A,#0FH,KEY_CE
    SETB    KEYCARD        ;真的有键按下,则置标志位
    RET
DELAY1S:       ;延时函数
    MOV    R7,#10
D1:
    MOV    R6,#50
    DJNZ    R6,$
    DJNZ    R7,D1
    RET
KEY_VALUE:                          ;键值表
 DB 0EBH,0DBH,0BBH,7BH,0E7H,0D7H,0B7H,77H
TAB:                                ;显示码
    DB    0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90
    END