汇编实验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连续右流动。为了使流水显示明显,每个位置应加延时程序。

连线图

汇编实验1——利用8255实现LED的流水点亮实验_第1张图片
注意那个美丽的彩虹线不要接反了,要一一对应(是个坑!!

代码分解

数据段初始化端口地址

DSEG SEGMENT
	PORTA EQU 280H; A端口
	PORTB EQU 281H; B端口
	PORTD EQU 283H; 命令与状态口
DSEG ENDS

方式命令设置

PA口接8个拨动开关K1-K8所以为1输入,PB口接8个LED所以为0输出。

    MOV DX,PORTD
	MOV AL,90H;1001 0000 初始化命令:A端口0方式输入,B端口0方式输出
	OUT DX,AL;将初始化命令输入到命令状态口

保存最开始的流水状态

    MOV DX,PORTA; 
	IN AL,DX; 输入初始开关状态到AL
	MOV CL,AL; CL保存流水状态
	MOV BL,AL; BL保存旧的开关状态, 在此初始化BL

亮灯

这个点,不理解之前觉得好难,理解了之后觉得不过如此——无非就是读PA处的代码,然后输出到PB去,由于都是八位,只需要一个中间寄存器CL。
汇编实验1——利用8255实现LED的流水点亮实验_第2张图片

    MOV AL,CL; AL中存入流水线状态
	MOV DX,PORTB;
	OUT DX,AL; 灯亮

控制时延

要让灯亮就必须控制延长时间啊,一次循环最多ffffh,那就多来几个循环呗!哈哈哈

DELAY1 PROC ;子程序
 	mov cx,25
    AGAIN:
    mov dx,0ffffh
    delay:dec dx
    jnz delay
    LOOP AGAIN
RET
DELAY1 ENDP

流水灯流动

软件控制硬件,也就是靠程序实现实际功能。如下一行代码,令人叹服!妙哉妙哉。

	ROR AL,1;右移一个灯

核心

救命,我的字好吃藕
CL负责控制当前该亮的灯,在light程序段中负责控制灯的亮和延时.
而BL,BH分别保存上一时刻的开关和现在的开关,注意这里每移动一个灯就判断一次。
汇编实验1——利用8255实现LED的流水点亮实验_第3张图片

    MOV DX,PORTA
	IN AL,DX
	MOV BH,AL;  BH存放新的开关状态
	
	CMP BH,BL; 判断开关状态是否发生改变
	JZ LIGHT; 如果开关状态未变,则调转到LIGHT
	MOV BL,BH; 否则旧的开关状态变为新状态
	MOV CL,BL; 把当前开关状态存入CL, 更新流水线状态

代码

下面这个是第一次写的。漏洞百出…而且写的很不美观,看着乐呵乐呵就好,比如那个可怕的delay大循环hhh惨不忍睹,最后趁着老师还在检查别人代码的时候改成了使用双层函数,此外也调了很多很多的不过。

	.model small 
	.386 ;老师说要加...
DSEG SEGMENT
	PORTA EQU 280H; A端口
	PORTB EQU 281H; B端口
	PORTD EQU 283H; 命令与状态口
DSEG ENDS



CSEG SEGMENT
ASSUME CS:CSEG,DS: DSEG
START: 
	
	MOV AX,DSEG;
	MOV DS,AX;

	MOV DX,PORTD
	MOV AL,90H;1001 0000 初始化命令:A端口0方式输入,B端口0方式输出
	OUT DX,AL;将初始化命令输入到命令状态口
	
	MOV DX,PORTA;
	IN AL,DX; 输入初始开关状态到AL
	MOV CL,AL; CL保存流水状态
	MOV BL,AL; BL保存旧的开关状态, 在此初始化BL
LP1:
	MOV DX,PORTA
	IN AL,DX
	MOV BH,AL;  BH存放新的开关状态
	
	CMP BH,BL; 判断开关状态是否发生改变
	JZ LIGHT; 如果开关状态未变,则调转到LIGHT
	MOV BL,BH; 否则旧的开关状态变为新状态
	MOV CL,BL; 把当前开关状态存入CL, 更新流水线状态
	
LIGHT:
	MOV AL,CL; AL中存入流水线状态
	MOV DX,PORTB;
	OUT DX,AL; 灯亮
	
	mov bx,0ffffh; 	
delay:dec bx
       jnz delay	   
       mov bx,0ffffh
delay1:dec bx
       jnz delay1
       mov bx,0ffffh
delay2:dec bx
       jnz delay2
       mov bx,0ffffh
delay3:dec bx
       jnz delay3
       mov bx,0ffffh
delay4:dec bx
       jnz delay4
       mov bx,0ffffh
delay5:dec bx
       jnz delay5
       mov bx,0ffffh
delay6:dec bx
       jnz delay6  
	 
	ROR AL,1;右移一个灯
	MOV CL,AL; CL 保存下一个要亮的灯
	
	JMP LP1;
	
CSEG ENDS
END START 
    .model small 
    .386 ;老师说要加...
DSEG SEGMENT
    PORTA EQU 280H; A端口
    PORTB EQU 281H; B端口
    PORTD EQU 283H; 命令与状态口
DSEG ENDS



CSEG SEGMENT
ASSUME CS:CSEG,DS: DSEG
START: 
    
    MOV AX,DSEG;
    MOV DS,AX;

    MOV DX,PORTD
    MOV AL,90H;1001 0000 初始化命令:A端口0方式输入,B端口0方式输出
    OUT DX,AL;将初始化命令输入到命令状态口
    
    MOV DX,PORTA;
    IN AL,DX; 输入初始开关状态到AL
    MOV CL,AL; CL保存流水状态
    MOV BL,AL; BL保存旧的开关状态, 在此初始化BL
LP1:
    MOV DX,PORTA
    IN AL,DX
    MOV BH,AL;  BH存放新的开关状态
    
    CMP BH,BL; 判断开关状态是否发生改变
    JZ LIGHT; 如果开关状态未变,则调转到LIGHT
    MOV 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,25
    AGAIN:
    mov dx,0ffffh
    delay:dec dx
    jnz delay
    LOOP AGAIN
RET
DELAY1 ENDP



CSEG ENDS
END START 

又是一个被汇编实验折磨的夜晚啊

你可能感兴趣的:(汇编,单片机,嵌入式硬件)