实验9、键盘扫描及数码管显示实验

实验内容
基础部分:
1、编写程序,实现如下功能:初始时数码管无显示;第一次按下键盘时,在最右侧数码管对应的十六进制数字;以后每次按下键盘,则将当前显示的数字全部向左移动一位(最左侧的数字移出数码管),并将刚刚键入的数字显示在数码管的最右侧。
拓展部分:
2、编写程序,将按键所对应的数字(0~E)按要求显示在指定的数码管上:

  • 初始时,6位LED数码管上无显示;
  • 第一次键入的数字显示在最右端的数码管上;之后每次键入新数字,其显示位置向左移动一位;(只显示最后键入的数字)
  • 若当前显示的数字已处于数码管的最左端,此时再键入数字,则将其显示在最左端的数码管上;之后键入数字的显示位置逐次向右移动;
  • 如此往复,直至按下数字键F,程序退出。

代码
1

A8255_A EQU 0600H
A8255_B EQU 0602H
A8255_C EQU 0604H
A8255_CON EQU 0606H   
ROWOUT EQU 200H

DATA    SEGMENT  
    TABLE DB 11101110B 
          DB 11101101B
          DB 11101011B
          DB 11100111B
          DB 11011110B
          DB 11011101B
          DB 11011011B
          DB 11010111B
          DB 10111110B
          DB 10111101B
          DB 10111011B
          DB 10110111B
          DB 01111110B
          DB 01111101B
          DB 01111011B
          DB 01110111B 
    VALUE   DB 3FH    ;0
            DB 06H    ;1
            DB 5BH    ;2
            DB 4FH    ;3
            DB 66H    ;4
            DB 6DH    ;5
            DB 7DH    ;6
            DB 07H    ;7
            DB 7FH    ;8
            DB 6FH    ;9     
            DB 77H    ;A
            DB 7CH    ;B
            DB 39H    ;C
            DB 5EH    ;D
            DB 79H    ;E
            DB 71H    ;F  
    TEMP    DB 0H
    POS1    DB 0H
    POS2    DB 0H
DATA    ENDS  
CODE SEGMENT
    ASSUME CODE:CS,DS:DATA
KEY PROC FAR  ;段间远调用
START:
    PUSH DS   ;保存DS       
    MOV AX,0  ;AX清0         
    PUSH AX   ;保存AX
    MOV AX,DATA
    MOV DS,AX   
    
    MOV DX,A8255_CON
    MOV AL,80H
    OUT DX,AL          ;设置8255的工作方式
    
    MOV DX,A8255_B
    MOV AL,00H      
    OUT DX,AL          ;开放所有端口
    MOV DX,A8255_A
    MOV AL,00H      
    OUT DX,AL          ;让所有灯熄灭
         
X1: MOV DX,ROWOUT   ;设置行输出端口
    MOV AL,00H
    OUT DX,AL       ;行输出0000,准备检查是否有任何键按下
    INC DX          ;设置列输入端口地址ROWOUT+1
    IN AL,DX        ;输入线状态
    AND AL,0FH      ;析取D3~D0列信号线
    CMP AL,0FH
    JZ X1           ;没有任何键按下,继续查询
    CALL D20ms      ;有键按下,延时消抖
    MOV DX,ROWOUT    
    MOV AL,00H
    OUT DX,AL       ;消抖后确定是否有任何键按下
    INC DX         
    IN AL,DX        ;读入列线状态
    AND AL,0FH      ;析取D3~D0列信号线
    CMP AL,0FH
    JZ X1           ;此时,说明延时消抖前的按键判断是源于干扰
                    ;或者,延时消抖时间不足,重新查询
    MOV AH,11111110B ;设置行扫描初值,首先扫描第0行
    MOV CX,4        ;设置行扫描初值,共4行
X2: MOV DX,ROWOUT   ;设置行输出端口地址
    MOV AL,AH       ;传递行扫描值
    OUT DX,AL       ;行扫描值输出,准备检查在哪一列
    INC DX          
    IN AL,DX
    AND AL,0FH
    CMP AL,0FH
    JNZ X3          ;找到按键所在的列号,转X3
    ROL AH,1
    LOOP X2
    MOV AX,80H     ;4行全部扫描完,却未发现有键安喜爱(可
                   ;能出现了干扰),以80H作为这种情况的标志
                   ;该指令的设置,主要考虑到程序的完备性,
                   ;即可以使程序在任何情况下都能正确执行
    JMP XEND
X3: MOV CL,4
    SHL AH,CL      ;AH逻辑左移4位,将低4位的行号移到高4位
    OR  AL,AH      ;行号与列号'或',形成键的位置码
    LEA BX,TABLE   ;设置TABLE位置码表的指针
    MOV CL,0       ;设置键号初值为0
X4: CMP AL,[BX]    ;在TABLE中查找本次形成的键位置码
    JZ X5          ;找到则转X5,对应键号就在CL中
    INC CL
    INC BX
    CMP CL,10H
    JNZ X4
    MOV AH,0FFH    ;CL等于10H,说明在TABLE表中没有找到
                   ;对应的键位置吗,其原因可能是出现了重建
                   ;的情况,以0FFH作为这种情况的标志
    JMP XEND
X5: MOV AH,CL      ;将CL中保存的键号传到AH中
    CALL LMOVESHOW
    CALL RESET
    MOV DX,A8255_A
    MOV AL,11011111B
    OUT DX,AL
    MOV DX,A8255_B
    MOV AL,AH
    OUT DX,AL
    JMP X1

LMOVESHOW:         ;将数码管上每个显示灯上的段码移到其左边的显示灯上
    PUSH AX  
    PUSH CX
    MOV CX,5
    MOV POS1,11111101B   ;将显示灯位码放入POS1中
    MOV POS2,11111110B   ;将上面显示灯左边的位码放入POS2中 
X7: CALL RESET
    MOV DX,A8255_A     
    MOV AL,POS1
    OUT DX,AL           ;选中位码为POS1的显示灯
    MOV DX,A8255_B     
    PUSH AX
    IN  AL,DX           ;读取其段码到TEMP中   
    MOV TEMP,AL
    POP AX
    MOV DX,A8255_A     
    MOV AL,POS2
    OUT DX,AL           ;选中位码为POS2的显示灯
    MOV DX,A8255_B
    MOV AL,TEMP
    OUT DX,AL           ;将POS1处的段码送入POS2处
    ROL POS1,1          ;POS1,POS2均循环左移1位
    ROL POS2,1
    LOOP X7
    POP CX
    POP AX    
    RET  

RESET:       ;保持显示灯状态
    PUSH AX
    PUSH DX
    MOV DX,A8255_A
    MOV AL,00H
    OUT DX,AL
    POP DX
    POP AX
    RET    

XEND:
    NOP
    RET                                                    
D20ms:
    PUSH CX
    MOV CX,0FH
X:  LOOP X
    POP CX
    RET  
KEY ENDP
CODE ENDS
    END START

2

A8255 EQU 0600H    ;选择数字
B8255 EQU 0602H    ;B: 段码
C8255 EQU 0604H
CON8255 EQU 0606H

DATA SEGMENT
TABLELED :		;段码表
	   DB 3FH  ;0的段码
	   DB 06H
	   DB 5BH
	   DB 4FH
	   DB 66H
	   DB 6DH
	   DB 7DH
	   DB 07H
	   DB 7FH
	   DB 6FH  ;9的段码
	   DB 77H
	   DB 7CH
	   DB 39H
	   DB 5EH
	   DB 79H
	   DB 71H
TABLEKEY:  				;位码表
		DB 11101110B           ;键码,前四位表示列,后四位表示行,0表示被按下的键的位置
       	DB 11011110B;1
       	DB 10111110B;2
       	DB 01111110B;3
       	DB 11101101B;4
       	DB 11011101B;5
       	DB 10111101B;6
       	DB 01111101B;7
       	DB 11101011B;8
       	DB 11011011B;9
       	DB 10111011B
       	DB 01111011B
       	DB 11100111B
       	DB 11010111B
       	DB 10110111B
       	DB 01110111B;F
TABLEWEI:				;移动的位置
		DB 11011111B
		DB 11101111B
		DB 11110111B
		DB 11111011B
		DB 11111101B
		DB 11111110B
		DB 11111110B
		DB 11111101B
		DB 11111011B
		DB 11110111B
		DB 11101111B

DUAN DB 00H;要显示的段码
WEI DB 10111111B;要显示的位码
TURN DB 00H
DATA ENDS

CODE SEGMENT
	ASSUME CS:CODE,DS:DATA
START: 
		MOV AX,DATA
		MOV DS,AX
	       
		MOV AL,81H		;控制字A口输出,B口输出,C口低四位输入
		MOV DX,CON8255
		OUT DX,AL    ;初始化
       
X1:    
		CALL SHOW	;显示
		CALL SCAN	;扫描是否有键按下
		JZ X1         ;没有任何键按下,继续查询
		CALL DELAY20;延迟消抖
		CALL SCAN
       	JZ X1 
       	                        ;消除抖动??
       	CALL CHECK
		CMP AH,0FH
		JZ XEND;按下F,程序终止	   
       	LEA SI,TABLELED
       	MOV AL,AH    	;键值
       	MOV AH,0	
       	MOV BX,AX
       	MOV AH,[SI+BX]	;键值对应的段码
       	MOV DUAN,AH;存段码
		;操作位码
		LEA SI,TABLEWEI
		MOV BL,TURN
		;AND BX,00FFH
		MOV BH,00H
		MOV AH,[SI+BX]
		MOV WEI,AH
		INC TURN	
		CMP TURN,0BH
		JZ X6
		JMP X7
X6:
		MOV TURN,00H	
X7:
       	CALL SHOW
       	CALL SCAN
       	JNZ X7
       	JMP X1
		
;检查哪个键被按下		
CHECK:
		MOV AH,11111110B      
       	MOV CX,4              
X2:    
		MOV DX,A8255           ;输入,A port stands for row
		MOV AL,AH
		OUT DX,AL
		MOV DX,C8255    
		IN AL,DX
		AND AL,0FH        
		CMP AL,0FH          ;比较指令,如果低四位都是1111的话代表没有输入,继续循环
		JNZ X3
		ROL  AH,1            ;左移一位
		LOOP X2
		MOV AH,80H
		JMP XEND            
X3:    
		MOV CL,4         ;输入
       	SHL AH,CL       ;将AH左移四位
       	OR AL,AH        ;al contribute low digits,ah high digits
       	LEA BX,TABLEKEY  ;BX代表的是键位的起始位置
       	MOV CL,0      ;offset for correct position
X4:    	
		CMP AL,[BX]
       	JZ X5
       	INC CL
       	INC BX
       	CMP CL,10H
       	JNZ X4
       	MOV AH,0FFH
       	JMP XEND
X5:
		MOV AH,CL;AH保存键值     	
		RET
		
XEND:  
		MOV AH,4CH
       	INT 21H   		

SHOW:
		PUSH AX
       	MOV DX,A8255
		MOV AL,WEI
       	OUT DX,AL;位码
       	MOV DX,B8255
		MOV AL,DUAN
		OUT DX,AL;段码
       	CALL DELAY
		POP AX
		RET

;检查是否有键按下
SCAN:
		MOV DX,B8255
       	MOV AL,00H
       	OUT DX,AL;清空显示缓冲
       	
       	MOV DX,A8255
		MOV AL,00H  ;选择所有位,所以要清除显示缓冲  
		OUT DX,AL	
	
		MOV DX,C8255    
		IN AL,DX
		AND AL,0FH
		CMP AL,0FH
		RET


DELAY: 
		PUSH CX
       	MOV CX,0300H
LL:    
		LOOP LL
       	POP CX
       	RET

       
DELAY20:
		PUSH CX
       	MOV CX,0100H
T1:    
		MOV AX,009FH
T2:    
		DEC AX
       	JNZ T2
       	LOOP T1
       	POP CX
       	RET
 
      
    
CODE ENDS
	END START

你可能感兴趣的:(微机接口实验,键盘扫描,数码管显示)