📄 bujin2.asm
字号:
IOY0 EQU 0E400H ;片选IOY0对应的端口始地址
;*****************************************************************
MY8255_A EQU IOY0+00H*4 ;8255的A口地址
MY8255_B EQU IOY0+01H*4 ;8255的B口地址
MY8255_C EQU IOY0+02H*4 ;8255的C口地址
MY8255_MODE EQU IOY0+03H*4 ;8255的控制寄存器地址
DATA SEGMENT
MESS DB 0DH,0AH,0DH,0AH
DB 'SPEED-----1~9',0DH,0AH
DB 'DIRE-----A,B',0DH,0AH
SPEED DB '0','$'
SPDLY DB 1
DIRE DB 'A','$'
SPTAB DB ?
DTABLE DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,77H,7CH,39H,5EH,79H,71H
DATA ENDS
STACK1 SEGMENT 'STACK'
STA DW 256 DUP(?)
TOP EQU LENGTH STA
STACK1 ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,ES:DATA,SS:STACK1
START: MOV AX,DATA ;初始化
MOV DS,AX
MOV AX,STACK1
MOV SS,AX
MOV SP,TOP
MOV DX,MY8255_MODE ;8255初始化
MOV AL,81H ;0,A/B口输出,C高口出,低口入
OUT DX,AL
MOV SI,3000H ;建立缓冲区,存放要显示的键值
MOV AL,00H ;先初始化键值为0
MOV [SI],AL
MOV [SI+1],AL
MOV [SI+2],AL
MOV [SI+3],AL
MOV DI,3003H
CALL MES
BEGIN:CALL DIS ;显示刷新
CALL CLEAR ;清屏
CALL CCSCAN ;扫描按键
JNZ GETKEY1 ;有键按下则跳置GETKEY1
MOV AH,1 ;判断PC键盘是否有按键按下
INT 16H
JZ BEGIN ;无按键则跳回继续循环,有则退出
QUIT: MOV AX,4C00H ;返回到DOS
INT 21H
GETKEY1:CALL DIS ;显示刷新
CALL DALLY
CALL DALLY
CALL CLEAR ;清屏
CALL CCSCAN ;再次扫描按键
JNZ GETKEY2 ;有键按下则跳置GETKEY2
JMP BEGIN ;否则跳回开始继续循环
GETKEY2:MOV CH,0FEH
MOV CL,00H ;设置当前检测的是第几列
COLUM: MOV AL,CH ;选取一列,将X1~X4中一个置0
MOV DX,MY8255_A
OUT DX,AL
MOV DX,MY8255_C ;读Y1~Y4,用于判断是哪一行按键闭合
IN AL,DX
L1: TEST AL,01H ;是否为第1行
JNZ L2 ;不是则继续判断
MOV AL,00H ;设置第1行第1列的对应的键值
JMP KCODE
L2: TEST AL,02H ;是否为第2行
JNZ L3 ;不是则继续判断
MOV AL,04H ;设置第2行第1列的对应的键值
JMP KCODE
L3: TEST AL,04H ;是否为第3行
JNZ L4 ;不是则继续判断
MOV AL,08H ;设置第3行第1列的对应的键值
JMP KCODE
L4: TEST AL,08H ;是否为第4行
JNZ NEXT ;不是则继续判断
MOV AL,0CH ;设置第4行第1列的对应的键值
KCODE: ADD AL,CL ;将第1列的值加上当前列数,确定按键值
CALL PUTBUF ;保存按键值
CALL BUJIN
PUSH AX
KON: CALL DIS ;显示刷新
CALL CLEAR ;清屏
CALL CCSCAN ;扫描按键,判断按键是否弹起
JNZ KON ;未弹起则继续循环等待弹起
POP AX
NEXT: INC CL ;当前检测的列数递增
MOV AL,CH
TEST AL,08H ;检测是否扫描到第4列
JZ KERR ;是则跳回到开始处
ROL AL,1 ;没检测到第4列则准备检测下一列
MOV CH,AL
JMP COLUM
KERR: JMP BEGIN
CCSCAN PROC NEAR ;扫描是否有按键闭合子程序
MOV AL,00H
MOV DX,MY8255_A ;将4列全选通,X1~X4置0
OUT DX,AL
MOV DX,MY8255_C
IN AL,DX ;读Y1~Y4
NOT AL
AND AL,0FH ;取出Y1~Y4的反值
RET
CCSCAN ENDP
CLEAR PROC NEAR ;清除数码管显示子程序
MOV DX,MY8255_B ;段位置0即可清除数码管显示
MOV AL,00H
OUT DX,AL
RET
CLEAR ENDP
DIS PROC NEAR ;显示键值子程序
PUSH AX ;以缓冲区存放的键值为键值表偏移找到键值并显示
MOV SI,3000H
MOV DL,0F7H
MOV AL,DL
AGAIN: PUSH DX
MOV DX,MY8255_A
OUT DX,AL ;设置X1~X4,选通一个数码管
MOV AL,[SI] ;取出缓冲区中存放键值
MOV BX,OFFSET DTABLE
AND AX,00FFH
ADD BX,AX
MOV AL,[BX] ;将键值作为偏移和键值基地址相加得到相应的键值
MOV DX,MY8255_B
OUT DX,AL ;写入数码管A~Dp
CALL DALLY
INC SI ;取下一个键值
POP DX
MOV AL,DL
TEST AL,01H ;判断是否显示完?
JZ OUT1 ;显示完,返回
ROR AL,1
MOV DL,AL
JMP AGAIN ;未显示完,跳回继续
OUT1: POP AX
RET
DIS ENDP
PUTBUF PROC NEAR ;保存键值子程序
MOV SI,DI
MOV [SI],AL
DEC DI
CMP DI,2FFFH
JNZ GOBACK
MOV DI,3003H
GOBACK: RET
PUTBUF ENDP
DALLY PROC NEAR ;软件延时子程序
PUSH CX
MOV CX,0FFH
D1: MOV AX,0FFH
D2: DEC AX
JNZ D2
LOOP D1
POP CX
RET
DALLY ENDP
BUJIN PROC NEAR
PUSH AX
PUSH CX
PUSH DX
BG: ADD AL,'0'
CMP AL,'1' ;速度在1~9之间
JC BG1 ;不为1 既跳转判断方向
CMP AL,'9'
JG BG1
SUB AL,'0'
MOV SPEED,AL
MOV SPDLY,AL
JMP BB1
BG1: SUB AL,'0'
CMP AL,0BH ;方向控制键
JE KEYS ;若为反转,转向KEYS将-装入DIRE
JMP BG2
KEYS: MOV DIRE,0BH
JMP BB2
KEYA: MOV DIRE,0AH
JMP BB1
BG2: CMP AL,0AH
JE KEYA
JMP BG3
BG3: CMP AL,0 ;ESC退出
JNE BG
JMP QIT
BB1:
XOR CX,CX
MOV CL,SPDLY
CALL DELAY
MOV DX,MY8255_C
MOV AL,00010000B
OUT DX,AL
CMP DIRE,0AH ;控制转向
JNE BB2
XOR CX,CX
MOV CL,SPDLY
CALL DELAY
MOV DX,MY8255_C
MOV AL,00100000B
OUT DX,AL
XOR CX,CX
MOV CL,SPDLY
CALL DELAY
MOV DX,MY8255_C
MOV AL,01000000B
OUT DX,AL
XOR CX,CX
MOV CL,SPDLY
CALL DELAY
MOV DX,MY8255_C
MOV AL,10000000B
OUT DX,AL
JMP QIT1
BB2: XOR CX,CX
MOV CL,SPDLY
CALL DELAY
MOV DX,MY8255_C
MOV AL,10000000B
OUT DX,AL
XOR CX,CX
MOV CL,SPDLY
CALL DELAY
MOV DX,MY8255_C
MOV AL,01000000B
OUT DX,AL
XOR CX,CX
MOV CL,SPDLY
CALL DELAY
MOV DX,MY8255_C
MOV AL,00100000B
OUT DX,AL
JMP QIT2
QIT1: CALL CCSCAN ;扫描按键
JZ BB1 ;无按键责继续运行
JMP QIT
QIT2: CALL CCSCAN ;扫描按键
JZ BB2 ;无按键责继续运行
JMP QIT
QIT: CALL MES
POP DX
POP CX
POP AX
RET
BUJIN ENDP
DELAY PROC NEAR ;延时子程序
PUSH CX
MOV CX,4000
DELAY1:
PUSH CX
MOV CX,2000H
LOOP $
POP CX
LOOP DELAY1
POP CX
LOOP DELAY
RET
DELAY ENDP
MES PROC NEAR
LEA DX,MESS ;显示信息1 ? 度按 0~9方 向按+或-退 出按 ESC当前速度 $'
MOV AH,09H
INT 21H
LEA DX,SPEED ;显示速度信息,初始为1
MOV AH,09H
INT 21H
LEA DX,DIRE ;显示方向信息初始为A
MOV AH,09H
INT 21H
RET
MES ENDP
MAIN: CALL MES
CODE ENDS
END START
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -