1、题目
当开关合上,16个LED灯从上而下依次循环发光,每次只能点亮一个LED灯;
当开关打开,保持当前LED灯的点亮状态不变,下次开关合上时,从当前的LED灯开始点亮。
2、电路图
2.1总图
2.2分图
3、编程
;当开关合上,16个LED灯从上而下依次循环发光,每次只能点亮一个LED灯(灯亮 -> 延时 -> 灯灭(下一个亮) ->延时...)
;当开关打开,保持当前LED灯的点亮状态不变,下次开关合上时,从当前的LED灯开始点亮。
;输入端口为IO5(0000 0010 1110 0**0B)
;定义符号常量
IOCON EQU 02D6H ;控制口(0000 0010 1110 0110B),输出
IOA EQU 02D0H ;端口A (0000 0010 1110 0000B),输入
IOB EQU 02D2H ;端口B (0000 0010 1110 0010B),输入
IOC EQU 02D4H ;端口C (0000 0010 1110 0010B),输入
CODE SEGMENT
ASSUME CS:CODE
;初始化8255A(往控制口写控制字,即对CPU而言就是输出)
START: MOV AL,10001001B ;从左到右:1表示工作方式控制字 00表示工作方式选择 0端口A输出 1端口C输入 0端口B工作方式选择 0端口B输出 1端口C输入。CPU控制字经AL输出
MOV DX,IOCON ;口地址为16位,写入控制口输出,将控制口地址送给DX
OUT DX,AL ;把工作方式控制字写入控制口
MOV BX,0001H ;BX的值控制哪个灯亮即为1,;初始状态PA0=1(无论开始开关断开还是闭合,总是第一个亮着的)
;从上往下A端口、B端口各决定8个灯(BX = BH + BL)
NEXT: MOV AL,BL ;将BL(初始是01H送给AL,即端口A控 制的8个灯)
MOV DX,IOA ;将端口A地址送给DX
OUT DX,AL ;输出端口A灯亮的情况
MOV AL,BH ;将BH(初始是00H送给AL,即端口B控制的8个灯)
MOV DX,IOB ;将端口B的地址送给DX
OUT DX,AL ;输出端口B灯亮的情况
MOV DX,IOC ;将端口C的地址送给DX
IN AL,DX ;读取PC口检测开关状态
TEST AL,00000010B;测试PC1是0还是1
JNZ NEXT ;ZF=0,即PC1=1(开关断开)跳转到NEXT(ZF零标志位,结果为0ZF=1,结果不为0ZF=0),对当前BX再次输出(开关一直断开,一直重复当前灯亮的代码,就是看起来灯亮暂停了)
ROL BX,1 ;开关闭合,ROL对BX循环左移,控制流水灯效果(如:第一次执行到此处,BX(0001H -> 0002H,将会(继续执行A1内容到OUT后)由第一个灯亮变成第二个灯亮)
Delayed_jump: CALL DELAY ;调用子函数,延时控制
JMP NEXT ;跳转到NEXT,NEXT决定下一个动作灯是亮还是灭(灯亮 -> 延时 -> 灯灭(下一个亮) ->延时)
DELAY PROC
MOV CX,0FFFFH ;LOOP 指令循环次数须放在CX 中
Null_loop: NOP ;NOP指令执行时花去一个时钟周期(多个NOP就花去多个时钟周期),可把它用在延时程序中作为循环体,用以估计一个延时时间
LOOP Null_loop ;空循环达到延时目的(这种软件延时时间上不太精准)
RET
DELAY ENDP
CODE ENDS
END START