本题模拟场景为十字路口交通信号灯及路口公共时钟,通过Proteus8仿真平台进行模拟。南北路口方向和东西路口方向均设有红、黄、绿三种状态灯以及数字倒计时显示,同时设有路口公共时钟模拟显示当前时间,提供时钟控制开关。为了演示方便,设定交通路口信号灯红灯和绿灯的状态为10s。程序开始时,南北路口方向绿灯和东西路口方向红灯持续亮10s(第一阶段),过后南北路口方向黄灯交替闪烁3s和东西路口方向红灯亮(第二阶段),接着南北路口方向红灯和东西路口方向绿灯持续亮10s(第三阶段),最后南北路口方向红灯亮和东西路口方向黄灯交替闪烁3s(第四阶段),不断循环重复以上四个阶段。
整个系统主要由控制模块、地址译码模块、显示模块三个部分组成。首先以8086微处理器作为CPU,8253做定时器进行计时,8259提供中断服务程序来处理完成交通信号灯计算显示状态、10s倒计时数字显示刷新、公共时钟逻辑单位换算。其中:
(1)显示模块通过8255并行接口芯片和74LS373锁存器,其中A口和B口来共同控制八位共阴极数码管来模拟显示路口公共时钟,C口用于控制模拟南北、东西四个路口的红灯、黄灯、绿灯等六个LED灯显示状态。74LS373锁存器控制显示交通信号灯10s倒计时的数字(0–9)输出。
(2)控制模块采用8253定时计数器来提供定时启动8259中断服务功能。8253的clk时钟信号频率设定为1MHz,使用8253的计数器0和计数器串联实现间隔1s产生一次中断,8253输出信号OUT1接通8259的IRQ1输入信号,进而转到中断服务处理程序。时钟控制开关则是在8253GATE端和GND接地端两端通过一个开关来实现暂停计时功能,注意启动程序计时需要断开时钟控制开关。
(3)地址译码模块主要通过3-8译码器(74LS138)来进行8253、8255、8259、接口芯片、74LS373锁存器等地址译码。
系统使用74LS138进行端口译码,其中 、A0和 共同选通接74LS373的LE, 接8253A的 , 接8255A的 , 接8259的IR3。8253的CLK信号输入频率为1MHz,计数器0和计数器1进行串联,输出信号OUT1接IR1,GATE1通过时钟控制开关和接地端相连,8086CPU工作主频设定为5MHz。具体各部分的连接如图所示:
图2 控制及译码模块图
系统在源代码的编写过程中,对常用的I/0端口寻址操作、以及接口芯片的初始化操作编写宏指令,进行模块化封装,简化易读。其中OUT_PUT用于端口输出,SET_8253用于8253初始化,SET_VEC用于中断向量的设置,SET_8259用于8259的初始化,INT_PRO用于时间的单位换算,详见2.3的源代码。此外,对8259、8253、8255等芯片的选通地址进行伪指令定义,比如TCON0表示8253计数器0的端口地址等等,还包括公共时钟显示延时子程序DELAY和中断服务程序IRQ1FUN。
第一步完成8255、8253、8259接口芯片的初始化,接着开中断,进入一个显示等待中断的循环。
初始化过程中,调用预先设定好的宏来设置中断向量,宏调用如下:SET_VEC 91H,IRQ1FU。其中IRQ1FUN为中断服务程序,中断向量码设置为91H,接入8259的IR1引脚。需设置ICW1,ICW2和ICW4,使用单片8259,采用边沿触发,单片,需要ICW4,采用自动结束方式,ICW1=13H,ICW2=91H,ICW4=03H,同样初始化8259采用宏调用完成。即:OUT_PUT PORT8259,13H;OUT_PUT PORT8259+2,91H; OUT_PUT PORT8259+2,03H。
完成中断初始化之后,完成8255初始化,使用A口,B口和C口,方式0,输出,故命令内容为:80H,向其控制口写入即可,控制口地址为IOCON。调用宏,OUT_PUT IOCON,80H。
8253的初始化要设置计数器0,在OUT1自动发出周期为1S的方波,接8259的IR1,即每隔1s产生一次中断。初始化8253控制寄存器及计数器调用的宏如下:
SET_8253 TCONTR,00110111B,TCON0,1000H ;TCON0是计数器0的地址
SET_8253 TCONTR,01110111B,TCON1,1000H ;TCON1是计数器1的地址
图3 系统程序流程图
完整的代码参见 2.3 部分。
显示模块由六个LED灯、一个共阴极八数码管、两个7SEG-DIGITAL七段数码管组成。
共阴极八数码管模拟公共时钟(包含时分秒),由8255A口和B口共同控制,假定本程序模拟交通路口场景启动初始时间为14时30分,通过中断服务程序来更新公共时钟显示数字。查阅资料可知,以下是其在数据段定义的显示0—9数字的对应编码。
LIGHT DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH
接着采用8255C口控制模拟交通灯的东西南北方向LED灯,AD数据总线通过74LS373锁存器控制交通灯10s倒计时显示7SEG-DIGITAL数码管。程序运行时通过8253间隔1s发出时钟信号,中断服务程序响应后累计当前时间值除以32(一个周期,0s-9s为状态1,10s-15s为状态2,16s-25s为状态3,26s-31s为状态4)求余,余数存在AH中,作为交通灯状态标记位。此做法摒弃了传统单一8255芯片实验利用人为设定的长短延时来固定刷新显示时间,而是结合8253的计时功能进行刷新,这样更加精准,减少设定时长不合理导致时间上的误差。
计算获得交通灯状态标记位后,进行对应状态内容的显示。状态一:南北路口绿灯亮10s,东西路口红灯亮10s。状态二:接着进行3s的南北路口黄灯交替闪烁亮灭,东西路口红灯亮。状态三:南北路口红灯亮10s,东西路口绿灯亮10s。
状态四:接着进行3s的南北路口红灯亮,东西路口黄灯交替闪烁亮灭。通过对当前累计时间进行取模求余,则可以实现以上四个状态的循环显示。
除了LED灯规律循环显示以外,同时也在时钟信号达到时刻更新显示倒计时数码管显示数字,通过数据总线和74LS373来输出显示。下面是倒计时显示数字对应的7SEG-DIGITAL数码管编码,对应(9s-0s,3s-0s,9s-0s,3s-0s)的显示规律。
TABLE DB 0FFH,0C0H,0FFH,0F9H,0FFH,0A4H,0C0H,0F9H,0A4H,0B0H,99H,92H,
82H,0F8H,80H,90H
而公共时钟数字显示部分也是类似的方法,在时钟信号达到时刻进行时分秒的换算,比如模10求余获取低位和高位数字进行处理进位等操作,接着通过8255A口和B口进行输出显示。
图4 显示模块流程图
中断服务程序主要对当前累计时间进行运算处理,进而计算当前交通信号灯对应状态编码AH和由SI控制的倒计时显示数字对应数码管编码和DI控制的公共时钟对应显示数码管编码。
首先判断当前计数值并自增,若公共时钟计数已经达到最大值,则下一计数单元递增(时分秒换算),接着模10取余获取高位、地位,转化成对应的数字编码,通过DI获取在数据段定义好的数码管显示编码LIGHT。
倒计时显示数字(0–9)则是先DEC SI,判断SI是否位于在数据段定义好的倒计时显示数编码TABLE首地址,若是则置SI于显示数编码末地址,接着通过数据总线输出给373锁存器再进行显示。
交通状态标志位则是通过AX(累计时间)模32求余,接着判断余数AH。如果AH大于等于26,则说明处于状态4,然后进行TEST AH,01H。IOC为8255 C端口地址,调用宏定义,若AH为奇数则OUT_PUT IOC,10000000B(南北红灯亮东西黄灯灭),偶数则OUT_PUT IOC,10000010B(南北红灯亮东西黄灯亮)。接着如果AH大于等于16,则说明处于状态3,然后进行OUT_PUT IOC,10000001B(南北红灯亮东西绿灯亮)。接着如果AH大于等于10,则说明处于状态2,然后进行TEST AH,01H。若AH为奇数则OUT_PUT IOC,00000100B(南北红灯亮东西黄灯灭),偶数则OUT_PUT IOC,01000100B(南北红灯亮东西黄灯亮)。最后则位于状态1,进行OUT_PUT IOC,00100100B(南北绿灯亮东西红灯亮)。
图5 中断服务程序流程图
;====================================================================
; author:GUET_diadestiny
; 计时十字路口交通信号灯及公共时钟
;====================================================================
OUT_PUT MACRO PORT,DATA
MOV DX, PORT
MOV AL, DATA
OUT DX, AL
ENDM
;8253初始化,CONTROLER为命令口地址,CMD为命令内容,TIMEPORT为计数器N的端口,COUNT为计数初值
SET_8253 MACRO CONTROLER,CMD,TIMEPORT,COUNT
OUT_PUT CONTROLER,CMD
MOV DX, TIMEPORT
MOV AX, COUNT
OUT DX, AL
MOV AL,AH
OUT DX,AL
ENDM
;中断向量设置,VECTOR为中断向量,FUNCNAME为中断子程序名
SET_VEC MACRO VECTOR,FUNCNAME
PUSH DS
MOV AX,0
MOV DS,AX
MOV DI,VECTOR*4
MOV AX,OFFSET FUNCNAME
MOV [DI],AX
MOV AX,SEG FUNCNAME
MOV [DI+2],AX
POP DS
ENDM
; INI_A为偶数口地址,ICW1,ICW2,ICW4为对于要写入的命令,适合单片8259初始化
SET_8259 MACRO INI_A,ICW1,ICW2,ICW4
OUT_PUT INI_A,ICW1
OUT_PUT INI_A+2,ICW2
OUT_PUT INI_A+2,ICW4
ENDM
;NOW用于表示当前计数单元,MAX用于当前计时最大值,NEXT表示下一计数单元,STORAGE为转换的LED编码存储单元
INT_PRO MACRO NOW,MAX,NEXT,STORAGE
LOCAL JUST
MOV AX,0
MOV AL,NOW
CMP AL,MAX ;比较计数是否到最大值
JNE JUST ;不是则跳转
INC NEXT ;是则下一计数单元加一
MOV NOW,0
JUST:
MOV BL,10
DIV BL
MOV BL,AL
MOV AL,LIGHT[BX] ;转换高位
MOV STORAGE,AL
MOV BL,AH
MOV AL,LIGHT[BX] ;转换低位
MOV STORAGE+1,AL
ENDM
DATA SEGMENT
TCON0 EQU 0090H ;8253计数器0地址
TCON1 EQU 0092H
TCON2 EQU 0094H
TCONTR EQU 0096H
OUT373 EQU 0080H
IOA EQU 00A0H ;8255A端口地址
IOB EQU 00A2H
IOC EQU 00A4H
IOCON EQU 00A6H
PORT8259 EQU 00B0H ;8259端口地址
TABLE DB 0FFH,0C0H,0FFH,0F9H,0FFH,0A4H,0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H ; 交通灯倒计时数码管顺序显示数字对应编码
TABLE_END = $ ;下文计算偏移
LIGHT DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH ;共阴极八数码管0-9对应编码,公共时钟
NOW_FLAG DW 0 ;当前累计数
N_HOUR DB 14 ;当前时时刻(假定当前时间是14点30分)
N_MIN DB 30 ;当前分时刻
N_SEC DB 0 ;当前秒时刻
HOUR DB 0,0,40H ;用于存放LED时显示编码
MINTU DB 0,0,40H ;用于存放LED分显示编码
SEC DB 0,0 ;用于存放LED秒显示编码
TEMP DB 0 ;临时保存编码
DATA ENDS
STACK SEGMENT
DW 2048 DUP(0)
STACK ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:STACK
START:
MOV AX,DATA ;设置数据段
MOV DS,AX
SET_VEC 91H,IRQ1FUN;设置中断向量IRQ1
SET_8259 PORT8259,13H,91H,03H ;初始化8259,设定ICW2=90H
OUT_PUT IOCON,80H ;初始化8255
SET_8253 TCONTR,00110111B,TCON0,1000H ;初始化8253
SET_8253 TCONTR,01110111B,TCON1,1000H ;初始化8253
OUT_PUT PORT8259+2,00H ;OCW1,开放中断输入
LEA SI,TABLE_END ;装载地址至SI
STI ;开中断
LEA DI,LIGHT ;装载地址至DI
ENDLESS:
MOV CX,7F08H ;控制输出共阴极数码管
LEA DI,HOUR ;装载存储编码
SHOW:
OUT_PUT IOA,[DI]
OUT_PUT IOB,CH
CALL DELAY
OUT_PUT IOB,0FFH
INC DI
ROR CH,1
DEC CL
JNZ SHOW
JMP ENDLESS
IRQ1FUN PROC NEAR
INC N_SEC
INT_PRO N_SEC,60,N_MIN,SEC ;秒
INT_PRO N_MIN,60,N_HOUR,MINTU ;分
INT_PRO N_HOUR,24,TEMP,HOUR ;小时
DEC SI ;倒计时逆序
CMP SI,OFFSET TABLE-1
JNZ THEN1
LEA SI,TABLE_END-1
THEN1: MOV AL,[SI]
MOV DX,OUT373
OUT DX,AL ;373输出到倒计时数码管
MOV AX,NOW_FLAG
MOV BL,20H
DIV BL ;经过推算,32个红绿灯状态为设定的一个周期
INC NOW_FLAG
CMP AH,26 ;将余数AH进行比较,得到状态编码
JB NN1
TEST AH,01H
JZ FOUR_ONE
OUT_PUT IOC,10000000B ;红绿灯状态4.2
IRET
FOUR_ONE: OUT_PUT IOC,10000010B ;红绿灯状态4.1
IRET
NN1: CMP AH,16
JB NN2
OUT_PUT IOC,10000001B ;红绿灯状态3
IRET
NN2: CMP AH,10
JB NN3
TEST AH,01H
JZ TWO_ONE
OUT_PUT IOC,00000100B ;红绿灯状态2.2
IRET
TWO_ONE: OUT_PUT IOC,01000100B ;红绿灯状态2.1
IRET
NN3: OUT_PUT IOC,00100100B ;红绿灯状态1
IRET
IRQ1FUN ENDP
;共阴极数码管所需延时子程序
DELAY PROC NEAR
PUSH CX
PUSH DI
MOV CX,30H
Y1:
LOOP Y1
POP DI
POP CX
RET
DELAY ENDP
CODE ENDS
END START
若需要程序源代码以及电路图的pdsprj文件,可以私信或者评论留下邮箱~~
(觉得有帮助的可以点个赞哈)
仿真结果如图所示:
断开时钟控制开关,假定场景当前时间为14点30分,南北方向可通行,东西方向禁止通行(状态一)进行10s倒计时。
图6 交通信号灯状态1
10s倒计时过后,南北方向进行3s倒计时的黄灯闪烁交替(状态二)。
图7 交通信号灯状态2
3s倒计时过后,东西方向可通行,南北方向禁止通行(状态三)进行10s倒计时。
图8 交通信号灯状态3
10s倒计时过后,东西方向进行3s倒计时的黄灯闪烁交替(状态四)。
图9 交通信号灯状态4
同时在程序运行的过程中,可以闭合时钟控制开关,暂停该场景下公共时钟计时功能,再次断开时钟控制开关即可继续计时。
图10 闭合时钟控制开关
经过测试,系统实现了计时十字路口交通信号灯及公共时钟的功能。在仿真测试的过程中,LED模拟灯和倒计时数码管和公共时钟的运行计时保持同步,并且没有闪烁,能正确模拟各个状态的交通信号灯循环工作状态。同时,通过闭合设定的时钟控制开关可以实现控制暂停计时功能,断开则继续计时。
通过借助protues仿真平台动手实践完成本次大作业,我加深了对微机原理和接口技术这两大模块的理解,熟悉运用汇编语言与接口进行交互,利用接口芯片(中断控制器8259,定时计数器8253,并行接口8255等),实现了模拟特定场景的需求功能。经过思考,本次大作业系统还存在一些可以改善和优化的地方,比如增加LED跑马灯模拟人行道以及来往的车辆,或者利用两个七段数码管模拟真实十字交通路口场景下60s的红绿灯倒计时以及复位时钟等功能,还可以进一步优化源代码。