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

📄 jianpang.asm

📁 键盘扫描重复输入功能
💻 ASM
字号:

;功能:5*4键盘扫描程序

KEYNAME DATA 28H    ;b4~b0位记录按键值
                    ;b7-作为按键有效标志,b7为0时,表示b4-b0位中的键值无效。
                    ;b7为1时,表示b4-b0位记录的按键值有效,且未尚未处理,不能
                    ;接受新按键。
                    ;外部程序执行了按键功能后,将按键有效标志清0,允许接收新按键
		    ;b6-保留。
KEYSTU   DATA 2AH   ;键盘按键状态寄存器,其中b2、b1、b0分别记录最近
                    ;三次定时中断的按键状态。
DISPBUF  DATA 30H   ;显示缓冲区首地址(30H-33H)

PORTDR   DATA 34H   ;U105(八上升沿D型触发器74HC273)芯片在内存中的影射地址
                    ;设置影射地址的目的是为了在执行键盘扫描过程中不影响
                    ;该输出口高3位(b7~b5)位内容
TIMEBELL DATA 36H   ;蜂鸣器鸣响时间

KEYRTIME DATA 37H   ;按键时间计数单元

BTIME   DATA 40H    ;50ms计数单元
DISPB   BIT  00H    ;50ms定时时间到标志

SDI     BIT  P1.2   ;串行数据输入
SCLK    BIT  P3.4   ;串行移位脉冲
PCLK    BIT  P3.5   ;并行锁存脉冲

PORTA   EQU 9000H   ;8255A口地址
PORTB   EQU 9100H   ;8255B口地址
PORTC   EQU 9200H   ;8255C口地址
PORTS   EQU 9300H   ;8255控制/状态口地址
PORTD   EQU 8800H   ;U105(八上升沿D型触发器74HC273)地址

ORG 0000H
LJMP MAIN

ORG 002BH
LJMP CTC2              ;定时/计数器T2中断服务程序入口地址

ORG 0050H
;-----主程序开始-----
PROC MAIN
MAIN:
     MOV SP, #0DFH     ;对于具有256字节内部RAM芯片来说,
                       ;将0E0H-0FFH,共计32字节作为堆栈区
     MOV DPTR, #8000H  ;关闭蜂鸣器
     MOV A, #0FFH
     MOVX @DPTR, A

     ;---复位后,将01H-0FF内部RAM单元清0。
     MOV R0, #01H
LOOP1:
     MOV @R0, #0
     INC R0
     CJNE R0, #0, LOOP1
     MOV KEYSTU, #07H 	    ;按键状态初始化为111
     MOV KEYNAME, #1FH	    ;将键值设为1FH(无效)

     ;初始化U107(8255)可编程并行I/O接口芯片的工作方式
     MOV DPTR, #PORTS       ;8255控制/状态口地址
     MOV A, #10011011B      ;A口工作在方式0,输入;B口工作在方式0,输入;
                            ;C口高、低半部暂时定义为输入
     MOVX @DPTR, A          ;送控制字寄存器
     ;将PD4~PD0置为高电平,使U105(74HC273)输出级截止,降低功耗。
     MOV DPTR, #PORTD       ;U105口地址送DPTR
     MOV A, PORTDR          ;读U105口在内存中的映象地址
     ORL  A, #1FH
     MOVX @DPTR, A          ;数据送U105输出口

     ;----初始化定时器T2
     MOV TH2, #0B8H        ;10ms定时时间的对应初值(6时钟)
     MOV TL2, #00H         ;B800H送定时器T2
     MOV RCAP2H, #0B8H
     MOV RCAP2L, #00H      ;初始化重装初值

;     MOV TH2, #0DCH         ;10ms定时时间的对应初值(12时钟)
;     MOV TL2, #00H          ;DC00H送定时器T2
;     MOV RCAP2H, #0DCH
;     MOV RCAP2L, #00H       ;初始化重装初值
     MOV T2CON, #00000100B  ;初始化T2工作方式(自动重装初值、定时),并启动T2

     ;-----初始化中断控制器
     SETB ET2                ;允许定时器T2中断
     SETB EA                 ;开中断
     MOV BTIME, #5           ;初值为5(即每50ms检测一次)

LOOP2:
     JNB DISPB, LOOP2        ;50ms定时时间未到
     CLR DISPB
     LCALL KEYCHK            ;每50ms读键盘状态
     ;检查键盘有无输入
     MOV A, KEYNAME
     JNB ACC.7, LOOP2        ;键盘按键无效,就循环等待

     ;按键有效,先将显示缓冲区笔段码左移一个字节
     MOV R0, #DISPBUF        ;显示缓冲区首地址送R0
     MOV R1, #DISPBUF+1      ;显示缓冲区地址送R1
     MOV R7, #3
LOOP3:
     MOV A, @R1
     MOV @R0, A
     INC R0
     INC R1
     DJNZ R7, LOOP3
     MOV A, KEYNAME          ;读按键值
     ANL A, #1FH             ;保留
     MOV KEYNAME, A          ;清除按键处理标志
     CJNE A, #10H, NEXT1
NEXT1:
     JC NEXT2
     ;按下了功能键,键值>=10H,用两位LED来显示
     ANL A, #0F0H
     SWAP A
     MOV DPTR, #LEDTAB       ;0-F字模表首地址送DPTR
     MOVC A, @A+DPTR         ;查表取模
     MOV R1, #DISPBUF+2      ;显示缓冲区地址送R1
     MOV @R1, A              ;字模送显示缓冲区
NEXT2:
     MOV A, KEYNAME          ;读按键值
     ANL A, #0FH             ;保留低4位
     MOV DPTR, #LEDTAB       ;0-F字模表首地址送DPTR
     MOVC A, @A+DPTR         ;查表取模
     MOV R1, #DISPBUF+3      ;显示缓冲区地址送R1
     MOV @R1, A              ;字模送显示缓冲区
     LCALL S_DISP            ;串行显示
     LJMP LOOP2              ;循环等待

END

PROC S_DISP                  ;串行输出子程序
S_DISP:
    MOV R0, #DISPBUF         ;显示缓冲区首地址送R0
    MOV R7, #4
LOOP2:
    MOV A, @R0
    MOV R6, #8
LOOP1:
    CLR SCLK
    RLC A
    MOV SDI, C               ;串行数据送SDI引脚
    NOP
    SETB SCLK                ;锁存串行输入数据
    DJNZ R6, LOOP1
    ;取下一显示码
    INC R0
    DJNZ R7, LOOP2
    ;4位笔段码已全部移到串入并出芯片中
    CLR PCLK
    NOP                      ;延迟一个机器周期
    SETB PCLK
    RET
END

;定时/计数器T2中断服务程序
PROC CTC2
CTC2:
     PUSH PSW
     PUSH ACC
     PUSH DPH
     PUSH DPL

     ;检查是否需要关闭蜂鸣器

     MOV A, TIMEBELL
     JZ BLEXIT
     DJNZ TIMEBELL, BLEXIT
     ;延迟时间到,关闭
     MOV DPTR, #8000H   ;关闭蜂鸣器
     MOV A, #0FFH
     MOVX @DPTR, A
BLEXIT:
     ;按键时间减1处理
     MOV A, KEYRTIME
     JZ KEYREXIT
     ;按键时间不为0,减1
     DJNZ KEYRTIME, KEYREXIT
KEYREXIT:

     DJNZ  BTIME, EXIT  ;溢出次数减1,不为0跳转
     ;溢出次数已经回到0,重新初始化溢出次数
     MOV BTIME, #5
     SETB DISPB         ;置位50ms时间到标志
EXIT:

     CLR TF2            ;清除定时器T2溢出标志
     POP DPL
     POP DPH
     POP ACC
     POP PSW
     RETI
END

PROC KEYCHK            ;键盘检测
KEYCHK:
;---键盘检测-----------
    MOV DPTR, #PORTD         ;U105口地址送DPTR
    MOV A, PORTDR            ;读U105口在内存中的映象地址
    ANL A, #0E0H             ;输出全为低电平的扫描信号
    MOVX @DPTR, A            ;数据送U105输出口,将PD4~PD0置为低电平

    MOV DPTR, #PORTB         ;8255(U107)B口地址送DPTR
    MOVX A, @DPTR            ;读出B口
    ANL A, #0FH              ;屏蔽高4位
    CJNE A, #0FH, NEXT1
    ;等于0F,说明没有按键被按下
    SETB C                   ;将C标志置1
    SJMP NEXT2
NEXT1:
    CLR C                    ;C标志清0
NEXT2:
    MOV A, KEYSTU
    RLC A                  ;左移一位,记录最新的按键状态
    ANL A, #07H            ;保留按键状态
    MOV KEYSTU, A          ;保存按键状态

    ;判别按键状态,决定是否执行按键扫描
    CJNE A, #2, NEXT3
    ;处于010态,视为干扰,作000态处理
    ANL KEYSTU, #0F8H      ;重置按键状态
    SJMP NEXT5
NEXT3:
    CJNE A, #4, NEXT4
    ;处于100态,说明按键已稳定闭合,可进行按键扫描
    LCALL KEYSCAN          ;执行键盘扫描,确定哪一按键被按下
    SJMP NEXT5
NEXT4:
    CJNE A, #0, NEXT5
    ;键盘处于稳定按下状态,执行按键重复输入处理
    MOV A, KEYRTIME
    CJNE A, #0, NEXT5      ;时间未到!
    LCALL KEYSCAN          ;执行键盘扫描
NEXT5:
    ;将PD4~PD0置为高电平,使74HC273输出级截止,降低功耗。
    MOV DPTR, #PORTD       ;U105口地址送DPTR
    MOV A, PORTDR          ;读U105口在内存中的映象地址
    ORL  A, #1FH
    MOVX @DPTR, A          ;数据送U105输出口
;---键盘检测结束-----------
    RET
END

PROC KEYSCAN                 ;键盘扫描程序
KEYSCAN:
    MOV R7, #5               ;定义扫描次数
    MOV R1, #0               ;初始化列地址
    MOV R3, #01111111B       ;扫描码初值

LOOP1:
    ;生成扫描码
    MOV A, R3
    RL A                     ;左移一位(从PD0开始扫描)
    MOV R3, A                ;保存扫描码
    ANL A, #00011111B        ;保留扫描码
    MOV B, A                 ;暂时保存在B寄存器中

    MOV DPTR, #PORTD         ;U105口地址送DPTR
    MOV A, PORTDR            ;读U105口在内存中的映象地址
    ANL A, #0E0H             ;保留与键盘扫描无关的b7~b5位。
    ORL A, B                 ;与扫描码或
    MOVX @DPTR, A            ;数据送U105输出口,将PD4~PD0置为低电平
    NOP                      ;延迟一个机器周期等待输出口状态稳定

    MOV DPTR, #PORTB         ;B口地址送DPTR
    MOVX A, @DPTR            ;读B口
    ANL A, #0FH              ;屏蔽高4位
    XRL A, #0FH              ;与0FH异或
    JNZ NEXT1                ;不为0,说明该列上有键被按下
    ;反之,该列上没有按键被按下
    INC R1                   ;列地址加+1,继续扫描
    DJNZ R7, LOOP1
    ;已扫描了所有列,均没发现有键被按下,本次扫描无效
    SJMP EXIT

NEXT1:
    JNB ACC.0, NEXT2
    ;ACC.0位为1,说明0行有按键被按下
    MOV R2, #0               ;行地址为0
    SJMP NEXT5
NEXT2:
    JNB ACC.1, NEXT3
    ;ACC.1位为1,说明1行有按键被按下
    MOV R2, #1               ;行地址为1
    SJMP NEXT5
NEXT3:
    JNB ACC.2, NEXT4
    ;ACC.2位为1,说明2行有按键被按下
    MOV R2, #2               ;行地址为2
    SJMP NEXT5
NEXT4:
    ;Acc.2~Acc.0均为0,则可肯定是Acc.3为1
    MOV R2, #3               ;行地址为3
NEXT5:
    ;计算行列地址,查表取得键名
    MOV A, R1
    RL A
    RL A                   ;列地址乘4(每列对应4行)
    ADD A, R2              ;加行地址
    MOV DPTR, #KEYTAB
    MOVC A, @A+DPTR        ;查表获取键值
    MOV KEYNAME, A         ;按键值送键名寄存器
    ORL KEYNAME, #80H      ;按键有效标志置1
    MOV KEYRTIME, #25      ;设置按键检测时间,即每秒中允许重复输入2次
    ;开蜂鸣器,响一短声
    MOV DPTR, #8000H       ;开蜂鸣器
    MOV A, #7FH
    MOVX @DPTR, A
    MOV TIMEBELL, #25      ;响25*10ms,即250Ms

EXIT:
    RET
END

;***********按键扫描码、键值对应关系******************
KEYTAB:
DB 0FH		;扫描码为0,即PD0与PB0交叉点对应数字键"F"
DB 0EH		;扫描码为1,即PD0与PB1交叉点对应数字键"E"
DB 0DH		;扫描码为2,即PD0与PB2交叉点对应数字键"D"
DB 0CH		;扫描码为3,即PD0与PB3交叉点对应数字键"C"

DB 09H		;扫描码为4,即PD1与PB0交叉点对应数字键"9"
DB 06H		;扫描码为5,即PD1与PB1交叉点对应数字键"6"
DB 03H		;扫描码为6,即PD1与PB2交叉点对应数字键"3"
DB 0BH		;扫描码为7,即PD1与PB3交叉点对应数字键"B"

DB 08H		;扫描码为8,即PD2与PB0交叉点对应数字键"8"
DB 05H		;扫描码为9,即PD2与PB1交叉点对应数字键"5"
DB 02H		;扫描码为A,即PD2与PB2交叉点对应数字键"2"
DB 00H		;扫描码为B,即PD2与PB3交叉点对应数字键"0"

DB 07H		;扫描码为C,即PD3与PB0交叉点对应数字键"7"
DB 04H		;扫描码为D,即PD3与PB1交叉点对应数字键"4"
DB 01H		;扫描码为E,即PD3与PB2交叉点对应数字键"1"
DB 0AH		;扫描码为F,即PD3与PB3交叉点对应数字键"A"

DB 13H		;扫描码为10,即PD4与PB0交叉点对应"↑"
DB 12H		;扫描码为11,即PD4与PB1交叉点对应"Enter"
DB 11H		;扫描码为12,即PD4与PB2交叉点对应"ESC"
DB 10H		;扫描码为13,即PD4与PB3交叉点对应"↓"




LEDTAB:                 ;八段LED共阳数码管字模
;数码  0     1     2     3     4     5    6    7
DB     0C0H, 0F9H, 0A4H, 0B0H, 99H, 92H, 82H, 0F8H

;数码  8     9     A     B     C     D     E     F
DB     80H,  90H,  88H, 83H,  0C6H, 0A1H, 86H, 8EH

⌨️ 快捷键说明

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