实验内容:

1.8253定时实验,利用8253完成1秒的延时。
2.利用8253硬件延时控制跑马灯运行。
3.8255键盘显示实验

1.8253定时实验,利用8253完成1秒的延时

CODE SEGMENT
	ASSUME CS:CODE
START:	MOV AL,00110101B;8253初始化,选择通道0,采用BCD计数方式
		MOV DX,2BBH
		OUT DX,AL
		MOV AL,00H;计数器初值均为2000,周期为2s,先写低字节,后写高字节
		MOV DX,2B8H
		OUT DX,AL
		MOV AL,20H
		OUT DX,AL
		MOV AL,01110111B;8253初始化,选择通道1,采用BCD计数方式
		MOV DX,2BBH
		OUT DX,AL
		MOV AL,00H;计数器初值均为2000,周期为2s,先写低字节,后写高字节
		MOV DX,2B9H
		OUT DX,AL
		MOV AL,20H
		OUT DX,AL
CODE ENDS
	END START

2.利用8253硬件延时控制跑马灯运行

CODE SEGMENT
ASSUME CS:CODE
MOV AL,10010010H;8255初始化
		MOV DX,283H
		OUT DX,AL
;8253硬件延时1s程序
START:	MOV AL,00110101B;8253初始化,选择通道0,采用BCD计数方式
		MOV DX,2BBH
		OUT DX,AL
		MOV AL,00H;计数器初值均为2000,周期为2s,先写低字节,后写高字节
		MOV DX,2B8H
		OUT DX,AL
		MOV AL,20H
		OUT DX,AL
		MOV AL,01110111B;8253初始化,选择通道1,采用BCD计数方式
		MOV DX,2BBH
		OUT DX,AL
		MOV AL,00H;计数器初值均为2000,周期为2s,先写低字节,后写高字节
		MOV DX,2B9H
		OUT DX,AL
		MOV AL,20H
		OUT DX,AL
;8255输出程序
MOV AL,01H
MOV BL,AL;将Al值送到BL暂存
;8253输出电平上升沿进入
XUN1: 	MOV DX,281H;从8255B口输入
IN AL,DX
TEST AL,01H;测试8253是否为高电平
JNZ XUN1;否,继续循环测试
XUN2: 	MOV DX,280H;从8255A口输入
IN AL,DX
TEST AL,01H;测试开关输出是否为高电平
JNZ XUN2;否,继续循环测试
;8255输出
MOV AL,BL;将暂存在BL中的值送到AL中
MOV DX,282H 
OUT DX,AL;C口输出
;8253输出电平下降沿退出
XUN3: 	MOV DX,281H;从8255B口输入
IN AL,DX
TEST AL,01H;测试8253是否为高电平
JZ XUN3;是,继续循环测试
;左移一位,暂存在BL中,防止AL被修改
ROL BL,1
JMP XUN1;循环检测该程序
CODE ENDS
END START

3.8255键盘显示实验

PORT_A EQU 280H;A口地址
PORT_B EQU 281H;B口地址
PORT_C EQU 282H  ;C口地址
PORT_CTL EQU 283H;控制字寄存器地址
DATA SEGMENT 
;键盘扫描码表
TABLE DB 77H,7bH,7DH,7EH,0B7H,0BBH,0BDH,0BEH
      DB 0D7H,0DBH,0DDH,0DEH,0E7H,0EBH,0EDH,0EEH
;0~F的七段代码编码
TABLE1 DB 0BFH,86H,0dbH,0CFH,0E6H,0EdH,0FDH,87H
        DB 0FFH,0E7H,0F7H,0FCH,0B9H, 0DEH,0F9H,0F1H
DATA ENDS
;堆栈段
STACK SEGMENT STACK
    DW 50 DUP(0)
TOP_STACK LABEL WORD
STACK ENDS
;代码段
CODE SEGMENT
    ASSUME CS:CODE,DS:DATA;SS:STACK
START:  MOV AX,STACK
        MOV SS,AX
        LEA SP,TOP_STACK
        MOV AX,DATA
        MOV DS,AX
        MOV DX,PORT_CTL
        MOV AL,10000010B;8255初始化,A口输出,B口和C口输入,方式0
        OUT DX,AL
;向所有行送0
S:  	 MOV DX,PORT_A
        MOV AL,0
        OUT DX,AL
;读列,查看所有键是否松开
        MOV DX,PORT_B
WAIT_OPEN:	IN AL,DX
        		AND AL,0FH
        		CMP AL,0FH
        		JNE WAIT_OPEN
;各键均已松开,查列是否有键按下
WAIT_PRES:	IN AL,DX
        		AND AL,0FH
        		CMP AL,0FH
        		JE WAIT_PRES
;再查列,看键是否仍被压着
        IN AL,DX
        AND AL,0FH
        CMP AL,0FH
        JE WAIT_PRES
;键仍被压着,确定哪一个键被压下
        MOV AL,0FEH
        MOV CL,AL
NEXT_ROW:	MOV DX,PORT_A
       		OUT DX,AL
        		MOV DX,PORT_B
        		IN AL,DX
        		AND AL,0FH
        		CMP AL,0FH
        		JNE ENCODE;列值不全为1,表示有键按下,转去编码
        		ROL CL,01
        		MOV AL,CL
        		JMP NEXT_ROW
;已找到某一列为0,对压键的行列值编码
ENCODE: 		MOV BX,000FH
        		IN AL,DX
NEXT_TRY:   CMP AL,TABLE[BX];比较读出的行列值和表中是否一致
            	JE DONE
            	DEC BX
            	JNS NEXT_TRY
            	MOV AH,01
            	JMP EXIT
DONE:  MOV DX,PORT_C;C口输出
        MOV AL,TABLE1[BX];查0~F的七段代码编码
        OUT DX,AL
        JMP S ;循环检测该程序
EXIT: HLT
CODE ENDS
     END START