一、实验目的
实验要求通过编写汇编语言在电路箱硬件上实际运用8254以及8255,进一步深化对于8255芯片工作方式的理解,掌握8254芯片的工作原理。学会控制LED、数码管等元件,通过编写小的程序实现信号的分频,并能够利用分频完成计数、测速任务。在此基础上,了解PC机和实验系统板的连接原理,理解系统扩展原理。
二、实验设备与环境
硬件上,使用实验室的TPC-ZK-II硬件实验箱,系统由USB总线接口模块、TPC-ZK-II实验系统及集成开发环境软件组成。USB总线接口模块通过USB总线电缆与pc机相连,模块直接插在TPC-ZK-II实验系统上。具体硬件见使用指导书。
![](https://i-blog.csdnimg.cn/blog_migrate/d7a36909445d7fe6ffbe8c2edd068658.png)
软件上,使用TPC-ZK-II集成开发环境。为用户提供了程序的编辑、汇编、调试、运行等功能。
![](https://i-blog.csdnimg.cn/blog_migrate/e46f8397728e5d95716222338b2de7eb.png)
三、实验内容与指标
3.1设计要求
(1)由于实验台能提供1MHz、2MHz的时钟频率过高,无法直接实现本次实验的计数值显示,需要同学采用合理的时钟频率来实现数码管的显示,故建议先做分频(1Hz)。并能够用逻辑笔观察出时钟信号的变化。
(2)合理选择8253/8254的工作方式以及计数初值,通过计数器来间接计算出时间,并通过DOS功能调用在屏幕上打印出来。通过拨码开关的开闭模拟车辆进入或驶离测速区域,闭合状态时(向上拨通)表示车辆进入测速区,此时GATE有效,计数器以方式2工作开始减1计数;当开关断开(向下拨断)后,表示车辆驶离,计数结束。
开关拨断状态时(计数结束)通过8255查询读入,同时发指令锁存计数值并读出,计算出与初始值的差值得到计数次数。进而算出计数时间。
(3)设计七段数码管连接方式以及相应的程序,实现对于时间数值的显示。本次实验只使用一个数码管进行显示,0~F代表计数值0~15;为方便计算出的时间数值的数 码管显示,采取“取整”处理,即保留整数部分即可,小数部分可删去。例如:1.3s取1s即可,2.8s取2s即可。
3.2设计目标和性能指标
3.2.1基础功能
(1)1HZ分频的实现
对于1HZ分频的实现其N=1MHz÷1=1000000,而处于二进制计数的单个计数器最大计数为65535,无法直接满足分频需要。因此,令计数器工作在方波状态,选用两片计数器级联共同完成分频任务,根据要求第一片设计分频1000,第二片在第一片所给的时钟基础上再分1000,则总分频数N=1000×1000=1000000.输出为要求的1HZ方波。
(2)通过计数器间接计算时间并显示
选用计数器二完成计时任务,当选用1Hz当做计数器2的CLK时,在不考虑小数的情况下,此时的计数值等于所经过的时间。根据工作方式2跟随GATE电平自动复位的特点,选用计数器2工作在方式2。则对于计时的任务已经完成,下面还有对于按键的判断以及屏幕的显示任务。
首先对于按键判断,将8255A的PC口设置为输入模式。PC口与排开关相连,通过编写程序,设置标志位的方式来实现开关控制计时的开关。设置K_FLAG标志位,程序在主程序不断扫描PC端口,当发现设置的开关为高电平时,将标志位置为1,此时再进入计数子程序时完成相应操作。
对于显示功能,首先将时间存入定义好的变量TIME里,通过除10取出个位和十位,再将其转化为ASCII码显示出来。随后通过计算速度存入SPEED变量,重复上面TIME的操作,最后将速度显示出来。完成显示任务。
3.2.2扩展功能
7端数码管显示的实现,通过查表的方式实现。设置数码管显示表,将TIME变量转化为表中对应的指针,通过8255A的端口输出,控制数码管段码的显示字符。由于要求只显示一位,则位码固定为最低位。并不复杂,这里就不展示连接理论图了。
3.3硬件电路图
经过上述的分析,可以得到整个实验的电路连接图如图5所示。
四、程序流程图
首先是主体程序框图,在主循环中不断的检测K7端口的电平。以此来不断调整标志位FLAG的数值。当检测到开关高电平时,更改FLAG数值,执行计数的相关操作。每执行完一轮,在此观察电平情况判断是否退出计数循环。基于所述完成计时。
进入计数循环后,首先锁存实时刷新的计时时间。首先对标志位进行判断,随后锁存计数值,由于计数器是减一计数。为了获取最大计数幅度,取初值为0.因此首先拿到的是剩余数存入NUM,为了拿到时间还需用初值减去NUM,存入TIME。
随后进入计数时间的实时显示模块,由于数码管与DOS屏幕显示类似,因此以DOS显示为例。在拿到TIME后,对时间进行处理,分为个位和十位,在转换为ASCII码后,调用INT20的功能进行实时显示。
若完成一轮计时实时显示后,发现标志位清零,这时执行退出循环后的操作。显示车辆的速度(这里假设测量的是车辆通过100m距离的时间)。其显示原理与前面也是一样的。只不过是对时间进行了进一步处理而已。
这里想提到的一点,是关于BUFFER,即时间缓冲位的使用。在一开始设计往往会忽略这一点。如果不设置这一点,将导致不稳定的情况出现,即必须在时间发生变化的前提下能进入后续的显示环节。
五、方案设计与讨论
在实现时,本程序设计了时间的实时显示,而不是只在计时开关关闭时显示时间,增强了程序的实时性。此外,程序还对计时的阈值做出了限制。如超过16s会自动显示计时时间过长并返回。这是考虑到避免实际情况下错误的计时导致无法退出计时循环的现象。
此外,本实验的程序有很多种嵌套方式以及表现形式。也可以进一步利用LCD显示活8×8点阵进行显示以增强效果。对于测速的区间也可以利用4×4键盘进行进一步细化。
首先,对于LCD、点阵显示,其实现需要有相应的刷新子过程,也就是通过8255将数据传输到LCD上。
第二,对于目前的方案,其数码管的显示只有一位,是比较单一的。也可以利用多位数码管显示。
最后,对于DOS的显示功能,方案可以有多种:可以在结束时显示一个确切的时间和速度,也可以以1Hz为频率实时刷新DOS上的累计时间,最后计算速度,显示对应速度。
总之,方案应兼顾灵活性和简易性,在有限的时间里完成尽可能多、尽可能全面的方案,而不是在某一模块过分强调难度。
六、程序展示
;2021.11.23
;计数器0:分频1000,CLK0接1MHZ,GATE0接5V,OUT0接CLK1
;计数器1:分频1000,CLK1接OUT0,GATE1接5V,OUT1接CLK2
;计数器2:计数器,CLK2接OUT1,GATE2接K7开关
;8255A口位码,B口段码,C口接收开关电平
DATAS SEGMENT
P82540 EQU 280H ;定义端口
P82541 EQU 281H
P82542 EQU 282H
P8254S EQU 283H
P8255A EQU 288H
P8255B EQU 289H
P8255C EQU 28AH
P8255S EQU 28BH
SM_TAB DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,77H,7CH,39H,5EH,79H,71H ;定义数码管0~F
PC_ASC DB 30H,31H,32H,33H,34H,35H,36H,37H,38H,39H ;ASC码0~9
S_STR DB 'TIME TOO LONG,Please restart the program','$' ;定义显示字符串
L_STR DB 'Cumulating Time:','$'
H_STR DB 0DH,0AH,'$'
V_STR DB 'Current velocity is :','$'
D_STR DB 'M/s','$'
F_STR DB 'Too Fast!','$'
SPEED DB 0 ;速度缓存
SPEED1 DB 0
SPEED2 DB 0
BUFFER DB 100 ;时间缓存
K_FLAG DB 0
TIME DB 0 ;当前计时
TIME1 DB 0
TIME2 DB 0
NUM DW 0 ;减一计时器数
DATAS ENDS
STACKS SEGMENT
X DB 100 DUP(?)
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
CALL PINIT
MAINLP: ;扫描K7端口,有无高电平,没有继续扫描
MOV DX,P8255C
IN AL,DX
AND AL,01H
CMP AL,1
JZ JISHU
JMP MAINLP
JISHU: ;若有高电平,则置标志位,刷新缓存位
MOV K_FLAG,1
MOV SI,0
MOV SPEED,0
MOV TIME,0
MOV NUM,0
LP: ;进入计数循环,调用dos显示、数码管显示
CALL TIMER
CALL SM_PRINT
CALL DOS_PRINT
MOV DX,P8255C
IN AL,DX
AND AL,01H ;检测开关端口,若发现变低则退出计数循环
CMP AL,1
JZ LP
CALL SPEED_PRINT
MOV K_FLAG,0
JMP MAINLP
MOV AH,4CH
INT 21H
;功能:P8254、P8255初始化
PINIT PROC
MOV DX,P8255S
MOV AL,81H
OUT DX,AL
MOV DX,P8254S
MOV AL,36H
OUT DX,AL
MOV DX,P82540
MOV AX,1000
OUT DX,AL
MOV AL,AH
OUT DX,AL
MOV DX,P8254S
MOV AL,76H
OUT DX,AL
MOV DX,P82541
MOV AX,1000
OUT DX,AL
MOV AL,AH
OUT DX,AL
MOV DX,P8254S
MOV AL,0B2H
OUT DX,AL
MOV DX,P82542
MOV AX,0
OUT DX,AL
MOV AL,AH
OUT DX,AL
RET
PINIT ENDP
;功能:速度计算,显示一次计时的速度
SPEED_PRINT PROC
PUSH AX
PUSH BX
PUSH DX
MOV AL,100
MOV BL,TIME
MOV AH,0
DIV BL
MOV SPEED,AL
CMP SPEED,50
JG EXE
CALL V_PRINT
MOV AH,0
MOV BL,10
DIV BL
MOV SPEED1,AH
MOV AH,0
DIV BL
MOV SPEED2,AH
MOV AH,0
MOV AL,SPEED2
ADD AL,30H
MOV DL,AL
MOV AH,02H
INT 21H
MOV AL,SPEED1
ADD AL,30H
MOV DL,AL
MOV AH,02H
INT 21H
CALL D_PRINT
CALL H_PRINT
JMP EXT5
EXE:
CALL F_PRINT
MOV AL,0FFH
MOV DX,P8255A
OUT DX,AL
MOV AL,71H
MOV DX,P8255B
OUT DX,AX
EXT5:
POP AX
POP BX
POP DX
RET
SPEED_PRINT ENDP
;功能:数码管显示
SM_PRINT PROC
PUSH AX
PUSH BX
PUSH DX
CMP K_FLAG,0 ;状态判断,执行条件:FLAG=1、时间有更新(BUFFER)、计数时间小于16
JZ EXT3
MOV AL,TIME
CMP AL,BUFFER
JZ EXT3
MOV AL,TIME
CMP AL,16
JZ EXT3
MOV AL,TIME
MOV AH,0
MOV SI,AX
MOV AL,01H
MOV DX,P8255A
OUT DX,AL
MOV AL,SM_TAB[SI]
MOV DX,P8255B
OUT DX,AX
INC SI
EXT3:
POP DX
POP BX
POP AX
RET
SM_PRINT ENDP
;功能:时间刷新器
TIMER PROC
PUSH AX
PUSH BX
PUSH DX
CMP K_FLAG,1 ;状态判断,为1持续刷新TIME
JZ TI
T0:
JMP DEND
TI:
MOV AL,10000000B
MOV DX,P8254S
OUT DX,AL
MOV DX,P82542
IN AL,DX
MOV AH,AL
IN AL,DX
XCHG AH,AL
MOV NUM,AX
MOV BX,0
SUB BX,AX
MOV TIME,BL
DEND:
POP DX
POP BX
POP AX
RET
TIMER ENDP
;功能:DOS窗口显示,TIME处理为个位、十位
DOS_PRINT PROC
PUSH AX
PUSH BX
PUSH DX
CMP K_FLAG,0
JZ EXT1
MOV AL,TIME
CMP AL,BUFFER
JZ EXT1
MOV AL,TIME
CMP AL,16
JZ EXT
CALL L_PRINT
MOV AL,TIME ;将新的时间压入BUFFER
MOV BUFFER,AL
MOV AH,0
MOV BL,10
DIV BL ;将时间分别处理为十位、个位送入TIME2、TIME1
MOV TIME1,AH
MOV AH,0
DIV BL
MOV TIME2,AH
MOV AH,0
MOV AL,TIME2
ADD AL,30H
MOV DL,AL
MOV AH,02H
INT 21H
MOV AL,TIME1
ADD AL,30H
MOV DL,AL
MOV AH,02H
INT 21H
CALL H_PRINT
JMP EXT1
EXT:
CALL S_PRINT
MOV AH,4CH
INT 21H
EXT1:
POP DX
POP BX
POP AX
RET
DOS_PRINT ENDP
;功能:字符串输出
H_PRINT PROC
PUSH DX
PUSH AX
PUSH DS
MOV AX,SEG H_STR
MOV DS,AX
MOV DX,OFFSET H_STR
MOV AH,09H
INT 21H
POP DS
POP AX
POP DX
RET
H_PRINT ENDP
L_PRINT PROC
PUSH DX
PUSH AX
PUSH DS
MOV AX,SEG L_STR
MOV DS,AX
MOV DX,OFFSET L_STR
MOV AH,09H
INT 21H
POP DS
POP AX
POP DX
RET
L_PRINT ENDP
F_PRINT PROC
PUSH DX
PUSH AX
PUSH DS
MOV AX,SEG F_STR
MOV DS,AX
MOV DX,OFFSET F_STR
MOV AH,09H
INT 21H
POP DS
POP AX
POP DX
RET
F_PRINT ENDP
S_PRINT PROC
PUSH DX
PUSH AX
PUSH DS
MOV AX,SEG S_STR
MOV DS,AX
MOV DX,OFFSET S_STR
MOV AH,09H
INT 21H
CALL H_PRINT
POP DS
POP AX
POP DX
RET
S_PRINT ENDP
D_PRINT PROC
PUSH DX
PUSH AX
PUSH DS
MOV AX,SEG D_STR
MOV DS,AX
MOV DX,OFFSET D_STR
MOV AH,09H
INT 21H
POP DS
POP AX
POP DX
RET
D_PRINT ENDP
V_PRINT PROC
PUSH DX
PUSH AX
PUSH DS
MOV AX,SEG V_STR
MOV DS,AX
MOV DX,OFFSET V_STR
MOV AH,09H
INT 21H
POP DS
POP AX
POP DX
RET
V_PRINT ENDP
CODES ENDS
END START
七、实验结果与分析
首先给出整个实验箱的连接图:
首先,通过级联计时器,得到了1Hz的分频,可以看到逻辑笔高低电平灯的交替闪烁,频率为1Hz。
向上拨开K7的开关,可以观察到显示屏动态的记录时间信息,当关闭K7时。这里假设测速区间为100m,可以看到测量的速度虽然精度只到整数位,但是正确的。
观察数码管,可以看到时间上随DOS并行显示,完成了基本的任务目标。
八、实验总结
通过这次实验,我亲手通过硬件实现了分频的操作。并学习如何利用分频进行实时的计数显示功能,并通过假定距离,计算车辆的速度。
在实验中想尝试采用两位数码管显示,其实两位与多位的等价的。为保持两位数码管的并行显示,就需要不断的在其之间切换。但这也造成了困扰:程序的循环应该停留在数码管的循环显示上,它的循环周期应该是1s。那么该如何确定周期呢?如果用级联计时器输出的1Hz显然是行不通的。可能会涉及中断跳出循环取数这样的问题。那就应该用更高频率的时钟,但高频时钟一位对应的时间也相应缩短。这又间接的增加的速度计算的处理难度。