赞
踩
实验要求通过编写汇编语言在电路箱硬件上实际运用8254以及8255,进一步深化对于8255芯片工作方式的理解,掌握8254芯片的工作原理。学会控制LED、数码管等元件,通过编写小的程序实现信号的分频,并能够利用分频完成计数、测速任务。在此基础上,了解PC机和实验系统板的连接原理,理解系统扩展原理。
硬件上,使用实验室的TPC-ZK-II硬件实验箱,系统由USB总线接口模块、TPC-ZK-II实验系统及集成开发环境软件组成。USB总线接口模块通过USB总线电缆与pc机相连,模块直接插在TPC-ZK-II实验系统上。具体硬件见使用指导书。
软件上,使用TPC-ZK-II集成开发环境。为用户提供了程序的编辑、汇编、调试、运行等功能。
(1)由于实验台能提供1MHz、2MHz的时钟频率过高,无法直接实现本次实验的计数值显示,需要同学采用合理的时钟频率来实现数码管的显示,故建议先做分频(1Hz)。并能够用逻辑笔观察出时钟信号的变化。
(2)合理选择8253/8254的工作方式以及计数初值,通过计数器来间接计算出时间,并通过DOS功能调用在屏幕上打印出来。通过拨码开关的开闭模拟车辆进入或驶离测速区域,闭合状态时(向上拨通)表示车辆进入测速区,此时GATE有效,计数器以方式2工作开始减1计数;当开关断开(向下拨断)后,表示车辆驶离,计数结束。
开关拨断状态时(计数结束)通过8255查询读入,同时发指令锁存计数值并读出,计算出与初始值的差值得到计数次数。进而算出计数时间。
(3)设计七段数码管连接方式以及相应的程序,实现对于时间数值的显示。本次实验只使用一个数码管进行显示,0~F代表计数值0~15;为方便计算出的时间数值的数 码管显示,采取“取整”处理,即保留整数部分即可,小数部分可删去。例如:1.3s取1s即可,2.8s取2s即可。
(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的操作,最后将速度显示出来。完成显示任务。
7端数码管显示的实现,通过查表的方式实现。设置数码管显示表,将TIME变量转化为表中对应的指针,通过8255A的端口输出,控制数码管段码的显示字符。由于要求只显示一位,则位码固定为最低位。并不复杂,这里就不展示连接理论图了。
经过上述的分析,可以得到整个实验的电路连接图如图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显然是行不通的。可能会涉及中断跳出循环取数这样的问题。那就应该用更高频率的时钟,但高频时钟一位对应的时间也相应缩短。这又间接的增加的速度计算的处理难度。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。