📄 实验.asm
字号:
data segment
ioport equ 0e800h-280h
io8255a equ ioport+288h
io8255b equ ioport+289h
io8255c equ ioport+28ah
io8255ctrl equ ioport+28bh
io8253a equ ioport+280h
io8253b equ ioport+281h
io8253ctrl equ ioport+283h
message1 db 0dh,0ah,'Please input the time to delay $'
message2 db 0dh,0ah,'South-North direction :$'
message3 db 0dh,0ah,'East-West direction :$'
message4 db 0dh,0ah,'Please turn off the console switch !!'
db 0dh,0ah,'After you turn off it,the system will work ... $'
led db 3fh,06h,5bh,4fh,66h,6dh,7dh,07h,7fh,6fh
time1 db 30
time2 db 30
count db ?
light db ?
data ends
;-------------------------------------------------------
; 本实验的一些简化假设
; 紧急控制可以打断正常行车、夜间行车、路灯全灭3种状态,
;但是在调节时间状态下不能有其他的打断;在紧急控制、
;夜间行车和路灯全灭时才能设置两方向的显示时间;
;-------------------------------------------------------
;-----------------------------------------------------------
;C口用于输出交通灯和数码管的选通脚S1、S0
;PC7~PC5对应南北路口红黄绿灯,PC2~PC0对应东西路口的红黄绿灯
;PC4接S1
;PC3接S0
;A口用于输出LED数码管显示
;B口用于输入
;PB0用于判断是否有紧急控制信号
;PB1用于判断是否有夜间行车的信号
;PB2用于判断是否有设置两个方向的亮时时间
;PB3用于输入8253产生的一秒的时钟信号
;PB4用于控制交通灯全灭
;-----------------------------------------------------------
code segment
assume cs:code
start :mov ax, data
mov ds, ax
call init8253
mov dx,io8255ctrl
mov al,82h ;工作方式0为A,C口输出,B口输入
out dx,al ;置方式控制字
;------------------------------------------------------
;十字路口交通灯的控制主程序段
;------------------------------------------------------
repeat:
mov al,00100100b ;初始设南北路口绿灯亮,东西路口红灯亮
mov dx,io8255c
out dx,al
mov light,al ;保存当前灯的状态
mov cl,time1
call delay ;延时30秒
mov al,01000100b ;置南北路口黄灯亮,东西路口红灯亮
out dx,al
mov light,al ;保存当前灯的状态
mov cl,5
call delay ;延时5秒
mov al,10000001b ;置南北路红灯亮,东西路绿灯亮
out dx,al
mov light,al ;保存当前灯的状态
mov cl,time2
call delay ;延时30秒
mov al,10000010b ;置南北路红灯亮,东西路黄灯亮
out dx,al
mov light,al ;保存当前灯的状态
mov cl,5
call delay ;延时5秒
mov ah,1 ;读键盘缓冲
int 16h
jz repeat ;无按下键则继续
mov ah,4ch ;按下任意键退出
int 21h
;-----------------------------------------
;延时子模块,CX传递要延时的长度
;-----------------------------------------
delay proc near
push ax ;保护现场
push dx
mov count,cl ;CL的值为要显示的时间长度付给count
lop: cmp count,0
jz exit
call init8253 ;初始化8253
wait1s:
mov dx,io8255b ;读PB口
in al,dx
and al,00000001b ;判断PB0是否为1
cmp al,0
jz next ;为0跳到下一步
call emergency ;否则调用紧急控制子程序
next:
in al,dx ;读PB口
and al,00000010b ;判断PB1是否为1
cmp al,0
jz next1 ;为0跳到下一步
call nighting ;否则调用夜间行车子程序
next1:
in al,dx ;读PB口
and al,00010000b ;判断PB4是否为1
cmp al,0
jz next3 ;为1就跳到下一步
call turnoff ;否则调用路灯全灭子程序
next3:
call display ;显示剩余时间
in al,dx ;读PB口
and al,00001000b ;判断PB3是否为0
cmp al,0
jnz wait1s ;不为0,则表示还没到一秒,等待
dec count ;绿灯延时长度减一
jmp lop
exit: pop dx ;恢复现场
pop ax
ret
delay endp
;---------------------------------------------
;显示剩余时间子程序
;---------------------------------------------
display proc near
push ax ;保护现场
push bx
push cx
push dx
mov bx, offset led
mov cl, 10
mov al, count ;要显示的数为count的值
mov ah, 0
div cl ;除10,求出十位及个位,商(即十位)在AL,余数(即个位)在AH
xlat ;转换对应的码值
mov dx, io8255a
out dx, al ;把十位送到LED灯显示
mov dx, io8255ctrl
mov al, 00000110b ;PC3置0,即关闭数码管的S0
out dx,al
mov dx, io8255ctrl
mov al, 00001001b ;PC4置1,即选通数码管的S1
out dx, al
mov cx,30000
lop1: loop lop1 ;延时
mov dx, io8255a
mov al, ah ;个位的值放到AL中
xlat ;转换对应的码值
out dx,al ;把个位送到LED灯显示
mov dx, io8255ctrl
mov al, 00001000b ;PC4置0,即关闭数码管的S1
out dx, al
mov dx, io8255ctrl
mov al, 00000111b ;PC3置1,即选通数码管的S0
out dx,al
mov cx,30000
lop2: loop lop2 ;延时
pop dx ;恢复现场
pop cx
pop bx
pop ax
ret
display endp
;-----------------------------------------
;初始化8253子程序
;-----------------------------------------
init8253 proc near
push dx ;保护现场
push ax
mov dx, io8253ctrl
mov al, 36h
out dx, al
mov ax, 1000
mov dx, io8253a
out dx, al
xchg ah, al
out dx, al
mov dx, io8253ctrl
mov al, 76h
out dx, al
mov ax, 2000
mov dx, io8253b
out dx, al
xchg ah, al
out dx, al
pop ax ;恢复现场
pop dx
ret
init8253 endp
;------------------------------------
;路灯全灭子程序
;------------------------------------
turnoff proc near
push ax ;保护现场
push bx
push cx
push dx
mov dx,io8255c
mov al,0
out dx,al ;灯全灭
mov bl,count
mov count,0 ;数码管显示0
again:
call display
mov dx,io8255b
in al,dx
and al,00000001b
cmp al,0
jz noemergency
call emergency
noemergency:
mov dx,io8255b ;读PB口
in al,dx
and al,00000100b ;判断PB2是否为1
cmp al,0
jz noadjust ;为0跳到下一步
call adjust ;否则调用调节两方向了绿灯的时间
noadjust:
mov dx,io8255b ;读PB口
in al,dx
and al,00010000b
cmp al,0
jnz again
call init8253
mov count,bl
pop dx ;恢复现场
pop cx
pop bx
pop ax
ret
turnoff endp
;------------------------------------
;紧急控制子程序OK
;------------------------------------
emergency proc near
push ax ;保护现场
push bx
push cx
push dx
mov al,count ;保存count
push ax
mov count,30 ;使数码管要显示的时间为30
mov dx,io8255c
mov al,10000100b ;使两路口红灯亮
out dx,al
mov dx,io8255b
lop3:
call display
in al,dx
and al,00000100b ;判断PB2是否为1
cmp al,0
jz noadjust1 ;为0跳到下一步
call adjust ;否则调用调节两方向了绿灯的时间
noadjust1:
in al,dx
and al,00000001b
cmp al,0
jnz lop3 ;PB0的信号仍为1,即交通在紧急状态下,继续等待
mov al,light ;否则恢复当前交通秩序
mov dx,io8255c
out dx,al
call init8253
pop ax
mov count,al ;恢复count
pop dx ;恢复现场
pop cx
pop bx
pop ax
ret
emergency endp
;-------------------------------------
;夜间行车子程序
;-------------------------------------
nighting proc near
push ax ;保护现场
push bx
push cx
push dx
mov al,count ;保存count
push ax
mov count,0 ;数码管显示0
mov al,01000010b ;两路口的黄灯亮
mov bx,ax ;把ax的值即黄灯的状态保存到bx
lop4: mov ax,bx
mov dx,io8255c ;两黄灯的状态由8255C口输出
out dx,al
mov dx,io8255b
wait1:
call display ;显示剩余时间
in al,dx ;读8255B口
and al,00000001b ;判断PB0是否为1
cmp al,0
jz skip ;不为1跳到下一步
call emergency ;为1则执行紧急控制
skip:
in al,dx ;读PB口
and al,00000100b ;判断PB2是否为1
cmp al,0
jz noadjust2
call adjust
noadjust2:
in al,dx
and al,00001000b ;判断PB3是否为0,为0时到了一秒
cmp al,0
jnz wait1 ;为1,则表示还没到一秒,循环等待,制造黄灯亮一秒
mov ax,bx
xor al,11111111b
and al,01000010b ;两路口的黄灯与前一秒的状态相反,使达到闪烁的效果
mov bx,ax ;把ax的值即两黄灯的状态保存到bx
in al,dx ;读PB口
and al,00000010b
cmp al,0 ;测试PB1是否为1
jnz lop4 ;若为1则表示夜间行车信号仍存在,继续等待
mov al,light ;否则恢复当前交通秩序
mov dx,io8255c
out dx,al
call init8253
pop ax
mov count,al ;恢复count
pop dx ;恢复现场
pop cx
pop bx
pop ax
ret
nighting endp
;-------------------------------
;调节两方向的延时时间OK
;-------------------------------
adjust proc near
push ax ;保护现场
push bx
push cx
push dx
mov dx,offset message1
mov ah,9
int 21h
mov dx,offset message2
mov ah,9
int 21h
call read
mov time1,dl ;设置南北路口延时参数
mov dx,offset message3
mov ah,9
int 21h
call read
mov time2,dl ;设置东西路口延时参数
mov dx,offset message4
mov ah,9
int 21h
mov dx,io8255b
lop5: in al,dx
and al,00000100b
cmp al,0
jnz lop5 ;调节控制开关没有关上
pop dx ;恢复现场
pop cx
pop bx
pop ax
ret
adjust endp
;----------------------------------------
;从键盘读数
;结果放在DX中
;----------------------------------------
read proc near
push ax ;保护现场
push bx
push cx
mov dx,0
dec1: mov ah,1
int 21h
sub al,30h
jl dec2
cmp al,9
jg dec2
cbw
push ax
mov ax,dx
mov cx,10
mul cx
mov dx,ax
pop ax
add dx,ax
jmp dec1
dec2:
pop cx ;恢复现场
pop bx
pop ax
ret
read endp
code ends
end start
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -