汇编实验1——利用8255实现LED的流水点亮实验
前言
做这个实验耗时近半天,其中安装虚拟机5小时,编写程序3小时。
踩过不少的坑,比如说一开始一直显示不出来usb插件,最后发现是开关没开;又比如,程序逻辑没有问题,但始终显示不出正确的结果,最后发现是先连接反了…不过好在,在一天快要结束的时候和搭档一起完成了实验。成就感满满,虽然本人没怎么参与编写代码
实验目的
掌握8255A和微机接口的连接方法,了解8255A的基本的工作原理和编程方法。
实验内容
PA口接8个拨动开关K1-K8,PB口接8个LED。初始由开关K1-K8设定8位不同的值,当执行程序后LED按K1-K8初始设定的值点亮,并向右流动。8255工作在0方式。
实验编程提示
在LED右流水中,如果开关的位置发生了变化,LED右流水从变化的位置重新开始。
提示:程序要能检测到某个时间开关状态的变化,并针对变化后的开关状态右流水,因此程序中要有两个变量,一个保存当前开关的状态以检测开关状态是否发生了变化,一个存LED右流水的状态,以便使LED连续右流动。为了使流水显示明显,每个位置应加延时程序。
连线图
注意那个美丽的彩虹线不要接反了,要一一对应(是个坑!!
代码分解
数据段初始化端口地址
DSEG SEGMENTPORTA EQU 280H; A端口PORTB EQU 281H; B端口PORTD EQU 283H; 命令与状态口
DSEG ENDS
方式命令设置
PA口接8个拨动开关K1-K8所以为1输入,PB口接8个LED所以为0输出。
MOV DX,PORTDMOV AL,90H;1001 0000 初始化命令:A端口0方式输入,B端口0方式输出OUT DX,AL;将初始化命令输入到命令状态口
保存最开始的流水状态
MOV DX,PORTA; IN AL,DX; 输入初始开关状态到ALMOV CL,AL; CL保存流水状态MOV BL,AL; BL保存旧的开关状态, 在此初始化BL
亮灯
这个点,不理解之前觉得好难,理解了之后觉得不过如此——无非就是读PA处的代码,然后输出到PB去,由于都是八位,只需要一个中间寄存器CL。
MOV AL,CL; AL中存入流水线状态MOV DX,PORTB;OUT DX,AL; 灯亮
控制时延
要让灯亮就必须控制延长时间啊,一次循环最多ffffh,那就多来几个循环呗!哈哈哈
DELAY1 PROC ;子程序mov cx,25AGAIN:mov dx,0ffffhdelay:dec dxjnz delayLOOP AGAIN
RET
DELAY1 ENDP
流水灯流动
软件控制硬件,也就是靠程序实现实际功能。如下一行代码,令人叹服!妙哉妙哉。
ROR AL,1;右移一个灯
核心
救命,我的字好吃藕
CL负责控制当前该亮的灯,在light程序段中负责控制灯的亮和延时.
而BL,BH分别保存上一时刻的开关和现在的开关,注意这里每移动一个灯就判断一次。
MOV DX,PORTAIN AL,DXMOV BH,AL; BH存放新的开关状态CMP BH,BL; 判断开关状态是否发生改变JZ LIGHT; 如果开关状态未变,则调转到LIGHTMOV BL,BH; 否则旧的开关状态变为新状态MOV CL,BL; 把当前开关状态存入CL, 更新流水线状态
代码
下面这个是第一次写的。漏洞百出…而且写的很不美观,看着乐呵乐呵就好,比如那个可怕的delay大循环hhh惨不忍睹,最后趁着老师还在检查别人代码的时候改成了使用双层函数,此外也调了很多很多的不过。
.model small .386 ;老师说要加...
DSEG SEGMENTPORTA EQU 280H; A端口PORTB EQU 281H; B端口PORTD EQU 283H; 命令与状态口
DSEG ENDSCSEG SEGMENT
ASSUME CS:CSEG,DS: DSEG
START: MOV AX,DSEG;MOV DS,AX;MOV DX,PORTDMOV AL,90H;1001 0000 初始化命令:A端口0方式输入,B端口0方式输出OUT DX,AL;将初始化命令输入到命令状态口MOV DX,PORTA;IN AL,DX; 输入初始开关状态到ALMOV CL,AL; CL保存流水状态MOV BL,AL; BL保存旧的开关状态, 在此初始化BL
LP1:MOV DX,PORTAIN AL,DXMOV BH,AL; BH存放新的开关状态CMP BH,BL; 判断开关状态是否发生改变JZ LIGHT; 如果开关状态未变,则调转到LIGHTMOV BL,BH; 否则旧的开关状态变为新状态MOV CL,BL; 把当前开关状态存入CL, 更新流水线状态LIGHT:MOV AL,CL; AL中存入流水线状态MOV DX,PORTB;OUT DX,AL; 灯亮mov bx,0ffffh;
delay:dec bxjnz delay mov bx,0ffffh
delay1:dec bxjnz delay1mov bx,0ffffh
delay2:dec bxjnz delay2mov bx,0ffffh
delay3:dec bxjnz delay3mov bx,0ffffh
delay4:dec bxjnz delay4mov bx,0ffffh
delay5:dec bxjnz delay5mov bx,0ffffh
delay6:dec bxjnz delay6 ROR AL,1;右移一个灯MOV CL,AL; CL 保存下一个要亮的灯JMP LP1;CSEG ENDS
END START
.model small .386 ;老师说要加...
DSEG SEGMENTPORTA EQU 280H; A端口PORTB EQU 281H; B端口PORTD EQU 283H; 命令与状态口
DSEG ENDSCSEG SEGMENT
ASSUME CS:CSEG,DS: DSEG
START: MOV AX,DSEG;MOV DS,AX;MOV DX,PORTDMOV AL,90H;1001 0000 初始化命令:A端口0方式输入,B端口0方式输出OUT DX,AL;将初始化命令输入到命令状态口MOV DX,PORTA;IN AL,DX; 输入初始开关状态到ALMOV CL,AL; CL保存流水状态MOV BL,AL; BL保存旧的开关状态, 在此初始化BL
LP1:MOV DX,PORTAIN AL,DXMOV BH,AL; BH存放新的开关状态CMP BH,BL; 判断开关状态是否发生改变JZ LIGHT; 如果开关状态未变,则调转到LIGHTMOV BL,BH; 否则旧的开关状态变为新状态MOV CL,BL; 把当前开关状态存入CL, 更新流水线状态LIGHT:MOV AL,CL; AL中存入流水线状态MOV DX,PORTB;OUT DX,AL; 灯亮CALL DELAY1 ROR AL,1;右移一个灯MOV CL,AL; CL 保存下一个要亮的灯JMP LP1;DELAY1 PROC ;子程序mov cx,25AGAIN:mov dx,0ffffhdelay:dec dxjnz delayLOOP AGAIN
RET
DELAY1 ENDPCSEG ENDS
END START
又是一个被汇编实验折磨的夜晚啊