这次介绍的是我大二下《微机系统与接口》课程的课程设计,纯手撸1000行汇编,最后验收出大问题,老师理解的题目要求和我想的不一样,不过最后老师也没过多要求我重新修改,说这正好证明了是我自己写的,疑惑???这里依旧按照我自己的思路并结合对课程设计报告的修改进行讲解,仅供参考。
一、简介
1.1、设计项目名称: 停车场出入管理系统
1.2、课程设计目的
① 巩固已学的理论课原理和基本知识;
② 加强编程和调试能力,学会用汇编语言编写简单使用的系统
③ 学会对 8086,8253,8255 等芯片进行综合应用
1.3、基本要求
设计实现一停车场实时管理系统。要求实时显示车位空闲情况(初值可修改,最多 99 辆),并分别控制 A、B两个出入口。每个出入口需要控制进出栏杆,并检测车辆进出,修改统计、显示车位空闲情况,并根据空闲情况控制进入。用 2*2 个开关模拟两个出入口的车辆进出光电信号,2 个 LED灯模拟栏杆输出控制(亮代表有效,禁止出入) 。允许A口进B口出,反之亦是。
1.4、设计指标
① 要求用两个数码管实时显示车位空闲数目(00~99);
② 当有空位时,如有车辆到来,则在检测到信号(有效)后 2 秒钟打开进入栏杆,待车进入(信号无效)后 1 秒钟放下栏杆,空车位数减 1 修改;若无空位,则车辆等待,直至有车位空出;
③ 当有车出停车场时则在检测到信号后 2 秒钟打开出车栏杆,带车离开 3 秒钟放下栏杆,空车位数加 1 修改;
④ 车位发生变化时, PC上同步显示记录。
1.5 、拓展功能
① 8*8 点阵显示进出箭头,有车辆进出空时绿色,满时红色;
② 自动记录车将进出时间和属性;
③ 考虑 A、B、C、D四个出入口同时控制的情况,自动显示空位数,控制车辆
1.6、实现情况
基本要求全部完成,提高要求中仅第一项完成,第二项没明白属性是什么,第三项基本上是代码的复制粘贴,意义不大。
二、基本设计原理
2.1、需求分析
为了实现该系统,我们至少需要3个模块:信号读取模块,计时模块,显示模块。
2.2、基本设计思想
利用简单输入输出、8253定时器、8255并行输入输出等多个模块的综合应用进行设计。
2.3、硬件模块选型
结合基本要求和设计指标进行需求分析,同时考虑到实际的硬件资源,我们采用了以下的
方案:
(1)对于车辆的进出信号,通过8255的C口高四位进行输入判断,C7、C6对应A口的进出信号,C5、C4对应B口的进出信号;
(2)C3、C2控制 A、B口的两个栏杆信号的通断(LED灯的熄灭和点亮),C1、C0控制数码管的选通信号;
(3)数码管采用动态显示,利用8255的A口进行数码管译码输出;
(4)8255的B口用于读取计时结束信号;
(5)8253(8254)定时器的计数器0采用方式3,对实验箱上的1MHZ时钟分频得到1000HZ的周期信号;
(5)8253(8254)定时器的计时器1采用方式0,以计数器0产生的1000HZ信号作为始终信号,当计时需求不同时,赋以不同的计数初值(如本次实验中所需的1s、2s、3s计时信号可分别设置计数初值为1000、2000、3000),8255的B口可读取计时器1计数结束后产生的高电平信号识别计时结束。
三、程序流程和编程实现
3.1、系统工作流图
3.2、关键程序片段
3.2.1、端口信号检测和判断
checkA1 :
test state_ax,2;当前A出信号虽然没了, 但是却还是正在出的状态
jnz checkA2plus
test state_b,2; 当前B进信号虽然没了, 但是却还是正在进的状态
jnz checkB1plus
test state_bx,2;当前B出信号虽然没了, 但是却还是正在出的状态
jnz checkB2plus
test al, 10000000b;检测A口开关1
jz checkA1plus;
call TestA1; 否则A号口开关 1 上拉,有车要进入,此时应该检测当前A号口状态
jmp main
checkA1plus :
test state_a,2;当前进信号虽然没了,但是却还是正在进的状态
jz checkA2
call TestA1;
jmp main
checkA2 :
test al,01000000b;检测A口开关2
jz checkA2plus;等于0则检查下一状态
call TestA2; A号口开关 2 上拉,有车要出去,此时应该检测当前A号口状态
jmp main
checkA2plus :
test state_ax,2;当前出信号虽然没了,但是却还是正在出的状态
jz checkB1
call TestA2;
jmp main
Tomain:
jmp main
checkB1 :
test al, 00100000b;检测B口开关1
jz checkB1plus;等于0;当前开关未上拉, 则检查下一开关
call TestB1; 否则B号口开关 1 上拉,有车要进入,此时应该检测当前B号口状态
jmp Tomain
checkB1plus :
test state_b,2;当前进信号虽然没了,但是却还是正在进的状态
jz checkB2
call TestB1;
jmp Tomain
checkB2 :
test al,00010000b;检测B口开关2
jz checkB2plus;等于0则检查下一状态
call TestB2; B号口开关 2 上拉,有车要出去,此时应该检测当前B号口状态
jmp Tomain
checkB2plus :
test state_bx,2;当前进信号虽然没了,但是却还是正在进的状态
jz Tomain
call TestB2;
jmp Tomain
3.2.2、状态检测和控制(以A口为例,B口同理)
;#;;;;;;;;;;;;;;;;;;;A口开关1上拉,检测A口状态;;;;;;;;;;;;;;;;;;;;;;;;;;;#
TestA1 proc near
push ax ;保护现场
push dx;
mov state_ax, 0; A口出信号置0
mov state_b, 0; B口进信号置0 防止上一过程信号无效时状态停留在1,即未结束
mov state_bx, 0; B口出信号置0
mov checktimeAx,00h;
mov checktimeB,00h;
mov checktimeBx,00h;
cmp state_a, 0;
jz state_A1; 等于0,停车场处于空闲状态,进行倒计时2s赋值
cmp state_a, 1;状态1
jz timein_a2s;为状态1,有车准备进,检测倒计时2s是否结束
cmp state_a, 2;状态2,有车正在进,检测倒计时1s是否结束
jz timein_a1s
jmp exit1;退出
;#;;;;;;;;;;;;;;;;;;;;;;当前为0,置A口状态1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#
state_A1 :
mov dx, offset String3; 提示有车准备从A进入
mov ah, 09h
int 21h
test FullFlag,1
jnz fulljmp
jmp contjudgeA
fulljmp:
mov dx, offset String7;显示已满
mov ah, 09h
int 21h;
pop ax
pop dx
ret
contjudgeA:
mov state_a, 1; 置为状态1
mov dx, io82531;
mov ax, 2000;第二次分频产生周期为2s的最后一次为高电平的脉冲
out dx, al
mov al, ah
out dx, al;高低位分两次写入
jmp exit1;跳出A口开关1检测,检测B口开关1
;#;;;;;;;;;;;;;;;;;;检测A口2s倒计时,结束置A口状态为2;;;;;;;;;;;;;;;;;;;;;;#
timein_a2s :
mov dx, io8255b;
in al, dx
test al,01h
jnz enterance ;2s时间到
and checktimeA,1
jnz exit1plus
mov dx, offset String4;2s倒计时未到,提醒正在检测身份
mov ah, 09h
int 21h
mov checktimeA,1;保证只显示一次checking语句
exit1plus:
pop dx;因为exit1太远了
pop ax
ret
enterance:
mov dx, offset String5;2s倒计时到,提醒栏杆已经打开
mov ah, 09h
int 21h
mov state_a, 2;正在进入,准备开始1s倒计时
mov dx, io8255ctrl; 开灯(栏杆打开)
mov al, 00000111b;C按位置控制,0111: 011使得PC3口置1;C 的 3 号口对应于A栏杆信号)
out dx, al
mov dx, io82531;
mov ax, 1000;第二次分频产生周期为1s的最后一次为高电平的脉冲
out dx, al
mov al, ah
out dx, al;高低位分两次写入
jmp exit1;跳出A口开关1检测,检测B口开关1
;#;;;;;;;;;;;;;;;;;;;检测A口1s倒计时,结束置A口状态为2;;;;;;;;;;;;;;;;;;;;;;#
timein_a1s :
mov dx, io8255b;
in al, dx
test al, 01h;
jnz entered ;1s时间到
jmp exit1
entered :
mov state_a, 0;已经进入,置0
mov EmptyFlag, 0
mov checktimeA,00h;语句checking次数重新置0
mov dx, io8255ctrl; 关灯(栏杆关闭)
mov al, 00000110b;C按位置控制,0110: 011使得PC3口置0;C 的 3 号口对应于A栏杆信号)
out dx, al
mov al, empty[0];1s时间到,停车位减一
mov ah, empty[1]
cmp ax, 0;判断是否停车位是否已满
jz fulled;停车场满了,返回
cmp al,0
jnz aldec
sub ax,10
mov al,0Ah
aldec:
sub ax, 1;停车位减一
mov empty[0], al;当前停车位数量赋值
mov empty[1], ah
mov dx, offset String6; 屏幕显示剩余车位
mov ah, 09h
int 21h
mov dl, empty[1]
add dl, 30h
mov ah, 02h
int 21h ;显示高位
mov dl, empty[0]
add dl, 30h
mov ah, 02h
int 21h ;显示低位
mov dl, 0ah
mov ah, 02h
int 21h ; 回车
mov dl, 0dh
mov ah, 02h
int 21h; 换行
mov al, empty[0];1s时间到,停车位减一
mov ah, empty[1]
cmp ax, 0;判断是否停车位是否已满
jz fulled;停车场满了,返回
jmp exit1
fulled:
mov FullFlag, 1
mov dx, offset String7;显示已满
mov ah, 09h
int 21h;
exit1:
pop dx
pop ax
ret
TestA1 endp
;#;;;;;;;;;;;;;;;;;A口开关2上拉,检测A口状态,1s倒计时结束则置A口状态为0;;;;;;;;;;;;;;;;;;#
TestA2 proc near
push ax
push dx
mov state_a, 0; A口出信号置0
mov state_b, 0; B口进信号置0 防止上一过程未结束
mov state_bx, 0; B口出信号置0
mov checktimeA,00h;
mov checktimeB,00h;
mov checktimeBx,00h;
cmp state_ax, 0
jz stateout_a1;A口状态为0,说明前面无车
cmp state_ax,1
jz timeout_a1s;A口状态为1,说明准备出行
cmp state_ax,2
jz timeout_a3s;A口状态为2,说明正在出行
jmp exit2
stateout_a1:
test EmptyFlag,1
jnz emptyjmp
jmp contjudgeAx
emptyjmp:
pop ax
pop dx
ret
contjudgeAx:
mov dx, offset String10; 提示有车准备从A离开
mov ah, 09h
int 21h
mov state_ax, 1;置A口为1
mov dx, io82531;开始分频1s
mov ax,1000;第二次分频产生周期为1s的最后一次为高电平的脉冲
out dx, al
mov al, ah
out dx, al;分高低位写入
jmp exit2
timeout_a1s:
mov dx, io8255b;
in al, dx
and al, 01h;
jnz outrance ;1s时间到
and checktimeAx,1
jnz exit2plus
mov dx, offset String4;显示正在查询
mov ah, 09h
int 21h;
mov checktimeAx,1
exit2plus:
pop dx;因为exit2太远了
pop ax
ret
outrance:
mov dx, offset String9;显示栏杆已经打开
mov ah, 09h
int 21h;
mov state_ax, 2;正在出行,准备开始3s倒计时
mov dx, io8255ctrl; 开灯(栏杆打开)
mov al,00000111b;C按位置控制,0101: 010使得PC2口置1;C 的 2 号口对应于A栏杆信号)
out dx, al
mov dx, io82531;
mov ax, 3000;第二次分频产生周期为2s的最后一次为高电平的脉冲
out dx, al
mov al, ah
out dx, al;高低位分两次写入
jmp exit2;
timeout_a3s:
mov dx,io8255b;
in al, dx
and al, 01h;
jnz outed ;3s时间到
jmp exit2
outed:
mov state_ax, 0;已经离开,置0
mov FullFlag, 0
mov checktimeAx,0
mov dx, io8255ctrl; 关灯(栏杆关闭)
mov al, 00000110b;C按位置控制,0100: 010使得PC2口置0;C 的 2 号口对应于A栏杆信号)
out dx, al
mov al, empty[0]
mov ah, empty[1]
xor ax, 0909h;判断是否停车位是否已空
jz emptyed;停车场已空,返回
mov al, empty[0]
mov ah, empty[1]
inc ax;停车位加一
aaa;将16进制调整为BCD码
mov empty[0], al;当前停车位数量赋值
mov empty[1], ah
mov dx, offset String6; 屏幕显示剩余车位
mov ah, 09h
int 21h
mov dl, empty[1]
add dl, 30h
mov ah, 02h
int 21h ;显示高位
mov dl, empty[0]
add dl, 30h
mov ah, 02h
int 21h ;显示低位
mov dl, 0ah
mov ah, 02h
int 21h ; 回车
mov dl, 0dh
mov ah, 02h
int 21h; 换行
mov al, empty[0]
mov ah, empty[1]
xor ax, 0909h;判断是否停车位是否已空
jz emptyed
jmp exit2
emptyed:
mov EmptyFlag, 1
mov dx, offset String8; 屏幕显示停车场已空
mov ah, 09h
int 21h
exit2 :
pop dx
pop ax
ret
TestA2 endp
3.2.3、两位数码管动态显示
;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;数码管显示;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#
LED_show proc near
;个位显示
mov al,0
mov dx, io8255a
out dx,al;全灭数码管
mov dx, io8255ctrl;
mov al, 00000010b;C按位置控制,0010: 100使得PC1置0;C 的 1 号口对应于数码管十位信号)
out dx, al
mov al, 00000001b;C按位置控制,0001: 100使得PC0置1;C 的 0 号口对应于数码管个位信号)
out dx, al
mov ah, 0
mov al, 1
mov si,ax
mov al, empty[si];取数码管各位
mov si,ax
mov al, LED[si];取各个数的七段码
mov dx, io8255a; A 口输出
out dx, al
mov cx, 3000h
LED_delay:
loop LED_delay; 延时
;十位显示
mov al,0
mov dx, io8255a
out dx,al;全灭数码管
mov dx, io8255ctrl;
mov al, 00000000b;C按位置控制,0000: 000使得PC0置0;C 的 0 号口对应于数码管个位信号)
out dx, al
mov al, 00000011b;C按位置控制,0011: 001使得PC1置1;C 的 1 号口对应于数码管十位信号)
out dx, al
mov ah, 0
mov al, 0
mov si,ax
mov al, empty[si];取数码管各位
mov si,ax
mov al, LED[si];取各个数的七段码
mov dx, io8255a; A 口输出
out dx, al
mov cx, 3000h
LED_delay1:
loop LED_delay1; 延时
ret
LED_show endp
3.2.4、8x8点阵灯显示(以禁止信号为例)
;#;;;;;;;;;;;;;;;;;;;;;;;;;;;;8X8 矩阵灯显示;;;;;;;;;;;;;;;;;;;;;;;;#
Arrow_show proc near
push si
push ax
push cx
push dx
mov al, state_a
test al, 02h; 2 标志状态中,
jnz ledin ;零标志位ZF为0,说明al = 02h;
mov al, state_ax
test al, 02h; 2 标志状态中,
jnz ledoutx ;零标志位ZF为0,说明al = 02h;
mov al, state_b;检测b口
test al, 02h
jnz ledin
mov al, state_bx;检测b口
test al, 02h
jnz ledoutx
test FullFlag,1
jnz ledfullx
test EmptyFlag,1
jnz ledemptyxx
;都不是则进入禁止显示
mov cx, 08h;每循环一次点亮一列
mov si, 0;
mov ah, 01
;禁止信号
loop_no:
mov dx, red
mov al, 00h
out dx, al;红选熄灭
mov dx, green;
out dx, al ;绿选熄灭
mov dx, row;行选
mov al, forbid[si];选择当前的列选信号
out dx,al ;输出
mov dx,red ;红选
mov al,ah;
out dx,al
shl ah,01;
push cx
mov cx,3000
delay2:
loop delay2
pop cx
inc si ;显示下一行
loop loop_no
jmp exit7
ledemptyxx:
jmp ledemptyx
五、成果展示及问题分析
5.1、系统运行结果
5.1.1、硬件连线图
5.1.2、功能展示
(1)欢迎界面
(2)输入空闲车位为89,数码管显示89,8x8点阵灯显示禁止信号“X”
(3)拨上A口进开关,2s有效信号检测,PC端显示Checking,2s结束显示Permit To Enter, 8*8点阵显示进右箭头,1s之后停车位减一,数码管显示88,PC端同步记录:
(4)拨上A口出开关,1有效信号检测,PC端显示Checking,1s结束显示Permit To Leave, 8*8点阵显示出左箭头,3s之后停车位减一,数码管显示90(初值为89),PC端同步记录:
(5)拨上B口进开关,2s有效信号检测,PC端显示Checking,2s结束显示Permit To Enter, 8x8点阵显示进右箭头,1s之后停车位减一,数码管显示88(数码管和8*8点阵灯显示情况同A口进,故图略),PC端同步记录:
(7)极端情况:
a、当空位为0,8x8点阵灯全红,数码管显示00,有车想要进入时,PC端显示Full提示信息:
b、当空位为99,即停车场全空,8x8点阵灯全绿,数码管显示99,PC端显示Empty提示信息:
5.2、存在问题分析
对于信号的有效性检测方案上,老师提出我们的和题目上的要求不太符合,题设的意思是车辆进出信号要先达到一定时间(进2s出1s),并完成一次反转才算是打开栏杆进行下一动作的标志,而我理解的是在有效信号达到一定时间(进2s出1s),则可认为该动作要求有效,然后打开栏杆,进行下一动作,所以当前的方案有一定的缺陷存在。
六、总结
项目本身其实看起来难度不大,但是在实际编程的时候,大大小小的问题却不少,同时又要结合实际硬件进行调试,综合性还是挺高的。对于老师提出的问题,我下来琢磨琢磨,其实确实有道理,不过由于当时临近期末,没有太多的时间去对程序进行大改,因此也算是一个小小的遗憾,希望看到这篇博客的同学能够在这个基础上做进一步的提升,白嫖可耻hhhhh