如图所示proteus7仿真图,实现以下几点功能:
按键检测+7段数码管显示+循环显示数字+闪烁
通过8086驱动8255的ABC三个端口,检测C口按键状态,并做出响应。
1. SW0按下, PA闪烁显示0,
2. SW1按下, PB闪烁显示1,
3. SW0,1闭合,循环显示1~9
4. SW0,1断开,全部熄灭
---首先要确定 8255的工作模式:
这设置 8255的ABC口分别为 0模式输出,0模式输出,输入
> 参考8255如何设置https://blog.csdn.net/wuzhihun111/article/details/124573768
--然后要确定8255 A B C 以及控制寄存器的地址:
--接下来才是驱动8255输出数码管
这里选取的是共阳极数码管
--最后,确定好硬件连接,编写asm汇编代码
asm源代码
IOA EQU 0FFD0H ;8255A的 PA口地址 0FFD0H in binary is 1111 1111 1101 0000.
IOB EQU 0FFD2H ;8255A的 PB口地址 0FFD2H in binary is 1111 1111 1101 0010.
IOC EQU 0FFD4H ;8255A的 PC口地址 0FFD4H in binary is 1111 1111 1101 0100.
IOCON EQU 0FFD6H ;8255A的控制寄存器的地址 0FFD6H in binary is 1111 1111 1101 0110.
DATA SEGMENT ;数据段定义
; 7段数码管共阳极编码16进制
; 0 1 2 3 4 5 6 7 8 9 a b c d e f 全灭
Table DB 0C0H,0F9H,0A4H,0B0H,099H,092H,082H,0F8H,080H,090H,088H,083H,0c6H,0a1H,086H,08eH,0ffH
Table_num = $-Table
; 按键我们选取 C0为SW0, C1为SW1; 对于单个按键,例如 IOC0 =0 表示按下 ; IOC0 =1 表示断开
DATA ENDS
; 按键检测+7段数码管显示+循环显示数字+闪烁
; 代码段实现 以下功能
; 1.SW0按下,PA闪烁显示0,
; 2.SW1按下,PB闪烁显示1,
; 3.SW01闭合,循环显示1~9
; 4.SW01断开,全部熄灭
CODE SEGMENT ;代码段段定义
ASSUME CS:CODE,DS:DATA
START:
MOV AX, DATA
MOV DS, AX ;程序开始切入点
init:
CALL Init_8255_A0_B0_Cin ;初始化8255工作模式 A模式0输出,B模式0输出,C输入
checkSW_status:
CALL CheckSW ; 检查开关状态
SW01_close: ;如果0闭合,1闭合PA PB 0~9循环显示
CALL Disp_0123456789
SW0_close: ; 如果0闭合,1打开,PA显示数字0,PB灭
CALL Extinguish ; 清除显示,全部熄灭
CALL Delay ; 延时阻塞一段时间
MOV AL, BYTE PTR[Table+0] ; 取出Table中 共阳极0的编码
MOV DX, IOA
OUT DX, AL ;A口数码管显示数字0
CALL Delay ; 延时阻塞一段时间
JMP checkSW_status ;重新循环
SW1_close: ; 如果0打开,1闭合, PB显示数字1,PA灭
CALL Extinguish ;清除显示,全部熄灭
CALL Delay ; 延时阻塞一段时间
MOV AL, BYTE PTR[Table+1] ;取出Table中 共阳极1的编码
MOV DX, IOB
OUT DX, AL ;B口数码管显示数字1
CALL Delay ; 延时阻塞一段时间
JMP checkSW_status ;重新循环
SWothers: ; 其他情况,; 如果0打开,1打开,全部熄灭
CALL Extinguish ; 清除显示,全部熄灭
CALL Delay ; 延时阻塞一段时间
JMP checkSW_status
; 下方均为CODE SEGMENT 段内子程序,被上面CALL的都在下面
Init_8255_A0_B0_Cin PROC ; 子程序,初始化8255工作模式 A模式0输出,B模式0输出,C输入
MOV AL, 10001001B ; 初始化8255工作模式 A模式0输出,B模式0输出,C输入
MOV DX, IOCON ; 控制寄存器地址存入DX
OUT DX, AL ; 向控制寄存器地址 写入 AL指令,设置8255工作模式 A模式0输出,B模式0输出,C输入
RET
Init_8255_A0_B0_Cin ENDP
CheckSW PROC ;子程序 检查开关状态 在Init_8255_A0_B0_Cin 之后调用
MOV DX,IOC ; 将IOC 地址写入DX
IN AL,DX ; 读取IOC 输入
TEST AL, 00000011B ; 如果0闭合,1闭合,则跳转到SW01_close标签
JZ SW01_close ;
TEST AL, 00000001B ; 如果0闭合,1打开,跳转到SW0_close标签
JZ SW0_close ;
TEST AL, 00000010B ; 如果0打开,1闭合,跳转到SW1_close标签
JZ SW1_close ;
JMP SWothers ; 如果0打开,1打开,跳转到SWothers标签
CheckSW ENDP
Extinguish PROC ; 子程序,同时熄灭A口和B口的数码管函数 在Init_8255_A0_B0_Cin 之后调用
MOV AL, 0FFH
MOV DX, IOB ; 关闭B口数码管 熄灭
OUT DX, AL
MOV DX, IOA
OUT DX, AL ; 关闭A口数码管 熄灭
RET
Extinguish ENDP
Disp_0123456789 PROC ;子程序 循环在IOA ICB口显示 0-9
dispInit:
MOV SI, OFFSET Table ;LEA SI, Table ; 0-9共阳极编码的首地址放入 SI
MOV CX, 10 ;循环十次
dispLoop:
MOV AL, BYTE PTR[SI]
MOV DX, IOA
OUT DX, AL
MOV DX, IOB
OUT DX, AL
CALL Delay ;延时
ADD SI, 1
satisfy:
MOV DX,IOC ; 将IOC 地址写入DX
IN AL,DX ; 读取IOC 输入 ,也就是读按键状态
TEST AL, 00000011B ; 如果不满足条件:0闭合,1闭合,则跳转到checkSW_status标签
JNZ checkSW_status ;
LOOP dispLoop
JMP dispInit ;重新循环
Disp_0123456789 ENDP
Delay PROC ;子程序 延时函数
PUSH CX
MOV CX, 0FFFFh
DelayLoop:
NOP
LOOP DelayLoop
POP CX
RET
Delay ENDP
OVER:
MOV AH,4CH ;程序结束 无限循环程序到不了这里吧
INT 21H
CODE ENDS ;代码段结束
END START;
然后就是整理文件,总结梳理,加注释。
8086汇编实验让我学习到了很多,比C语言抽象,思维奇特。