汇编 -- 停车场出入管理控制系统

    这次介绍的是我大二下《微机系统与接口》课程的课程设计,纯手撸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、系统工作流图

 
20899536-b82edfb4b0e85bb5.png
 

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、硬件连线图

 
20899536-cc8f55ec28218007.png
 


5.1.2、功能展示
(1)欢迎界面

 
20899536-be5a77479e854c7d.png
 

(2)输入空闲车位为89,数码管显示89,8x8点阵灯显示禁止信号“X”

 
20899536-5b69e15e4ac955eb.png
 
 
20899536-d7bbb98d8398ef48.png
 

(3)拨上A口进开关,2s有效信号检测,PC端显示Checking,2s结束显示Permit To Enter, 8*8点阵显示进右箭头,1s之后停车位减一,数码管显示88,PC端同步记录:

 
20899536-288ec859ee53648e.png
 

(4)拨上A口出开关,1有效信号检测,PC端显示Checking,1s结束显示Permit To Leave, 8*8点阵显示出左箭头,3s之后停车位减一,数码管显示90(初值为89),PC端同步记录:

 
20899536-b0e9db03452201e1.png
 

(5)拨上B口进开关,2s有效信号检测,PC端显示Checking,2s结束显示Permit To Enter, 8x8点阵显示进右箭头,1s之后停车位减一,数码管显示88(数码管和8*8点阵灯显示情况同A口进,故图略),PC端同步记录:

 
20899536-623e71ba9e703b23.png
 

(7)极端情况:

    a、当空位为0,8x8点阵灯全红,数码管显示00,有车想要进入时,PC端显示Full提示信息:

 
20899536-80e5b0ba56847e19.png
 
 
20899536-02622127afe5c244.png
 

    b、当空位为99,即停车场全空,8x8点阵灯全绿,数码管显示99,PC端显示Empty提示信息:

 
20899536-4f71dfa0f330e09c.png
 
 
20899536-c2f26297b57c5aeb.png
 

5.2、存在问题分析

    对于信号的有效性检测方案上,老师提出我们的和题目上的要求不太符合,题设的意思是车辆进出信号要先达到一定时间(进2s出1s),并完成一次反转才算是打开栏杆进行下一动作的标志,而我理解的是在有效信号达到一定时间(进2s出1s),则可认为该动作要求有效,然后打开栏杆,进行下一动作,所以当前的方案有一定的缺陷存在。

六、总结

    项目本身其实看起来难度不大,但是在实际编程的时候,大大小小的问题却不少,同时又要结合实际硬件进行调试,综合性还是挺高的。对于老师提出的问题,我下来琢磨琢磨,其实确实有道理,不过由于当时临近期末,没有太多的时间去对程序进行大改,因此也算是一个小小的遗憾,希望看到这篇博客的同学能够在这个基础上做进一步的提升,白嫖可耻hhhhh

      Github Repository: https://github.com/Beta-y/Parking-Lot

猜你喜欢

转载自blog.csdn.net/qq_41658212/article/details/104274905