东南大学 微机接口与实验 课程设计 乒乓球比赛 实验报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
东南大学
《乒乓球比赛》
微机课程设计实验报告
姓名:学号:
专业:吴健雄学院实验室:
实验时间:2013年00月00日报告时间:2013年00月00日评定成绩:审阅教师:
目录
一、实验目的与内容 (2)
二、总方案设计及原理 (3)
(一)比赛规则 (3)
(二)面板设计 (3)
(三)方案流程图 (3)
三、方案实现与测试 (5)
(一)各模块硬件设计 (5)
(二)整体硬件连线图 (6)
(三)系统框图 (7)
(四)主程序设计 (7)
(1)主程序流程图 (7)
(2)主要程序片段 (9)
(五)子程序设计 (11)
(1)延时子程序 (11)
(2)屏幕显示子程序 (12)
(3)数码管扫描比分子程序 (13)
(4)移动速度选择子程序 (16)
(5)规定等待时间选择子程序 (17)
四、程序设计中遇到的问题及解决方法 (18)
五、分析与总结 (18)
附录 (19)
一. 实验目的与内容
1)基本要求
用8个LED 发光管(红黄绿)的来回滚动显示来模拟打乒乓球时乒乓球在两边球台上的来回运动。
比赛双方用按钮/开关(双方各用1个按钮/开关)来模拟发球与接球,即发球方按动其控制的按钮/开关,球从发球方一侧向另一方运动(LED发光管从发球方到对方逐个点亮,滚动显示),当球运动至接球方时,接球方立即按动其控制的按钮/开关,“击球”使球“弹回”发球方一侧,如此周而复始,直至在规定的击球时间内有一方未能完成击球动作,从而对方得一分,然后继续比赛。
比赛规则可参照一般的乒乓球比赛规则。
要求:
(1) 球以每0.5秒滚过1个LED的速度移动;
(2) 回球需在球到达后的0.5秒内进行(按下按钮),否则按失球计;
(3) 球未到达提前按下按钮按失球处理,不起回球作用;
(4) 在PC机上显示比赛过程,同时用2个八段数码管显示比分(按10进制计数,初始值 0:0,可自行
设计显示及规则,可简化为0-9,也可为0-99);
(5) 要求精确计时。
2)设计提示
球到达接球方后,立即读接球方的按钮状态,若未按则有效(若已按下则按失球计),并开始0.5秒的计时,在这个0.5秒内不断读接球方按钮状态,直到按下代表“击球”动作。
3)进一步设计要求
(1)通过拨动开关控制球的移动速度,即可设置每个LED点亮时间(0.5 秒、0.3秒、0.2 秒);(2)通过拨动开关控制允许击球的时间(0.3 秒、0.2 秒、0.1 秒);
(3)用8×8点阵配合比赛过程,显示比分;
(4)用一个开关控制进入智能模式,智能模式要求:球移动速度取决于击球时间,球移动速度(每个LED 点亮时间)在 0.2~0.5秒内可变,具体取决于球到达接球方后击球所花的时间 0~0.5 秒,如花费的时间短则回球后球移动速度快,反之回球后移动速度慢,如下表所示。
球移动速度与击球时间对应表
二. 总方案设计及原理
(一)比赛规则
对题目进行理解和深化后,将乒乓球比赛的规则规定如下:
(1) 使用两个开关K0、K7模拟左方和右方的发球和接球,拨向0表示不做任何动作,拨向1则表示接球和
发球。
(2) 球未到达提前将开关拨向1则按失球处理,不起回球作用。
(3) 回球需在球到达后的规定时间内进行(按下按钮),否则按失球计。
接球的规定时间默认为0.5秒,但
是可以通过相应开关K4/K5选择其它规定时间,如0.3秒、0.2秒和0.1秒。
(4) 球的移动速度默认为0.5秒,但是可以通过相应开关K2/K3选择其它速度,如0.3秒、0.2秒。
(5) 该比赛采取9分制,即先得到9分的选手获胜,即一场比赛结束。
(6) 每次发球由上一次失分方执行(输方发球)。
(7) 在PC 机上显示比赛过程,同时用两个八段数码管显示比分。
(8) 使用K6控制是否进入智能模式
(二)面板设计
实验方案的面板设计如下:
(三)方案流程图
K7 K6
K5 K4 K3 K2 K1 K0
控制右边选手的发球和接球
控制左边选手的发球和接球
8盏灯显示乒乓球的移动
共同调节控制球的移动速度
共同调节控制接球的规定时间
数码管显示比赛分数
三. 方案实现与测试
(一)各模块硬件设计
通过分析,确定需要用到芯片8255监测开关状态、输出灯的动态流向和输出数码管的段选。
需要用到芯片8253精确计时。
需要芯片74LS273用于位选。
(1)8255
8255是实现并行输入输出功能的芯片,对于流水灯和数码管显示有很好的实现效果。
8255有三个口供选择,我将其设定为方式0,A 、B 口输出、C 口输入,C 口对应的PC0~PC7(除PC1、PC6外)分别与开关K0~K7(除K1、K6外)相对应,用于监测左方和右方的发球与接球、改变灯移动时间间隔和改变规定的等待时间。
A 口对应的PA0~PA7与LED 灯L0~L7相连接,通过A 口并行输出控制灯的流动。
B 口对应的PB0~PB7与八段数码管的a~h 相对应,通过B 口并行输出控制数码管断码的选择。
(2)8253
8253用于精确定时,由于用于定时器要定时到0.5秒、0.3秒、0.2秒和0.1秒,又由于最大初始值为65536,所以需要计数器通道0和1级联使用。
GATE0、GATE1都接5V 高电平,CLK0输入接1MHZ 脉冲信号,计数器通道0输出的OUT0与计数器通道1的输入CLK1相连接,最终的通道1的输出OUT1与8255的PC1口相连接,监测是否计数已满,计数器通道0采用计数方式3,计数器通道1采用计数方式2。
(3)74LS273
由于8255的口都被占用了,所以要使用74LS273对数码管的位选进行选择。
数码管的显示在比赛过程中一直显示,两个数码管的显示要用动态显示,即通过位选,使数码管一位一位地显示,由于显示的速度过快,则肉眼看到觉得两个数码管是一起亮的。
74LS273的输出Q1接位选的S0,输出Q2接位选的S1,而74LS273的输入接实验箱的D0、D1的数据输出。
但是不能一直对其进行位选,所以应该将数码管显示程序多放在整个程序当中,使得数码管看上去在整个比赛过程中一直亮着。
(二)整体硬件连线图
(三)系统框图
(四)主程序设计(1)主程序流程图
(2)主要程序片段
①、8255设置控制字
InitializeFor8255:
MOV DX,IO8255 ;给8255控制字
MOV AL,89H ;方式0,A、B输出,C口输入 OUT DX,AL
②、8255C口监测开关状态及计数器计数状态
A:是否发球(右方):
WaitFor_Right_ToServeTheBall:
CALL DISP ;扫描比分
MOV DX,IO8255C ;监视开关,是否开始;右边发球
IN AL,DX
TEST AL,01H ;右边是否开关已拨
JZ WaitFor_Right_ToServeTheBall
B:是否接球(左方):
MOV DX,IO8255C ;先检测左边开关的状态
IN AL,DX
TEST AL,80H ;=1000000 则说明按下过早
JNZ Left_FailOnePoint ;按失球计
;左侧没有过早按下,则
JMP Left_BeginTiming ;开始检测是否接到球
Left_TimingConstrain:
CALL WAITTIME ;开始等待响应计时
Left_WaitingTheHit: ;等待左边接球
CALL DISP ;扫描比分
MOV DX,IO8255C
IN AL,DX ;IN AL,8255C
TEST AL,80H ;判断左边是否击到球
JNZ Left_HitBackTheBall ;击到球,比赛继续
;没击到球,判断计时器
IN AL,DX ;IN AL,8255C
TEST AL,02H
JNZ Left_WaitingTheHit ;一直循环,当(0.5S)(0.1s)计完时,算失球 Test IntelModeFlag,01B
;判断智能模式是否打开,打开状态下计到时间并不一定是失败
JNZ IntelMode_Left ;打开状态则转移, 否则,按正常失球算
JMP Left_FailOnePoint
③、8255A口并行输出(球的移动)
A:发球后球的移动(从右到左):
MOV BL,01H ;起始状态,最右边开始亮
MOV AL,BL
MOV DX,IO8255A ;输出A口
OUT DX,AL ;00000001
MOV CL,8 ;八次移动
BISAI1: CALL DISP ;扫描比分
MOV DL,0FFH ;判断是否有ESC键按下
MOV AH,06H
INT 21H
CMP AL,27
CALL DELAY ;从右边到左边
ROL BL,1 ;向左移动一次
MOV AL,BL
MOV DX,IO8255A ;输出A口
OUT DX,AL
CALL DISP
DEC CL ;每移动一次减一
CMP CL,1 ;判断是否在最左边
JNZ BISAI1 ;若未完,继续
B:接球后球的移动(从左到右):
MOV BL,40H ;左边第二个马上亮;左边击到球
MOV DX,IO8255A
MOV AL,BL
OUT DX,AL
MOV CL,7 ;7次移动
JMP BISAI2
C:失球后灯要全灭(左失球后):
CALL DISP ;先显示一下以前的比分
MOV BL,00H ;一次结束后灯全部熄灭
MOV AL,BL
MOV DX,IO8255A
OUT DX,AL
④、显示字符串程序
例如:
Println MACRO StringNameInDataSegment ;打印字符串并换行
;print a string in data segment with a LineEnd
push dx
push ax
mov dx,offset StringNameInDataSegment
mov AH,09h
int 21h
Call PrintLineEnd ;打印换行符
pop ax
pop dx
EndM
(五)子程序设计
(1)延时子程序
①流程图
②主要程序
DELAY PROC NEAR ;延迟子程序
PUSH AX
PUSH DX
CALL LEDTIME ;送初始值
JM: CALL DISP ;扫描比分
MOV DX,IO8255C ;看计时状态
IN AL,DX ;右边第二个开关检测计时器是否满 TEST AL,02H
JNZ JM ;未满,继续监测
POP DX
POP AX
RET ;开始移动
DELAY ENDP
(2)屏幕显示子程序
①流程图
②主要程序
PCXS PROC NEAR ;显示屏幕子程序
PUSH AX
PUSH DX
MOV DX,OFFSET STRING10
MOV AH,09H ;显示信息“现在比分”
INT 21H
MOV AL,YF ;比分转换,转换为对应的ASCII码 MOV AH,ZF
ADD AL,30H
ADD AH,30H
MOV YX,AL
MOV ZX,AH
MOV DL,ZX ;显示真实比分,左边得分
MOV AH,02H
INT 21H
MOV DL,3AH ;显示“:”
MOV AH,02H
INT 21H
MOV DL,YX ;显示右方得分 MOV AH,02H
INT 21H
POP DX
POP AX
RET
PCXS ENDP
(3)数码管扫描比分子程序
①流程图
②主要程序
例如输出左边分数:
MOV DX,LS273 MOV AL,00H
OUT DX,AL ;左边LED灭
XOR SI,SI
MOV SI,OFFSET LED
MOV BH,00H
MOV BL,YF
ADD SI,BX
MOV AL,BYTE PTR [SI]
MOV DX,IO8255B
OUT DX,AL ; 输出右边数
MOV DX,LS273
MOV AL,01H
OUT DX,AL ;右边LED亮
MOV CX,3000
如果要输出右边分数,则应选择右边分数相对应的断码,位选选择01H,使右边数码管亮。
(4)移动速度选择子程序
①流程图
②主要程序
通过K2/K3选择灯的移动速度,速度默认为0.5.,另可选择0.3/0.2: MOV DX,IO8255C ;读开关状态
IN AL,DX
AND AL,00001100B;开关2/3调节速度
CMP AL,04H ;2/3=1/0
JNZ NEXT1
MOV AX,600 ;速度0.3
JMP TIME
NEXT1: CMP AL,08H ;2/3=0/1
JNZ NEXT2
MOV AX,400 ;速度0.2
JMP TIME
NEXT2: MOV AX,1000 ;速度0.5
JMP TIME
TIME: MOV DX,IO8253A
OUT DX,AL ;先写低字节
MOV AL,AH
OUT DX,AL ;后写高字节
MOV DX,IO8253C
MOV AL,74H ;方式2
OUT DX,AL
MOV AX,500 ;写入循环计数初值500 MOV DX,IO8253B
OUT DX,AL ;先写低字节
MOV AL,AH
OUT DX,AL ;后写高字节,开始计时
智能模式:
IntelMode_LEDTime:
MOV DL,BallSpeed
MOV AX,1000
CMP DL,0
JE TIME
CMP DL,1
JE TIME
MOV AX,800
CMP DL,2
JE TIME
MOV AX,600
CMP DL,3
JE TIME
MOV AX,400
(5)规定等待时间选择子程序
①流程图
②主要程序
子程序中的其它部分与上面的移动速度子程序相同,规定等待时间默认为0.5,另可通过K4、K5选择速度0.3/0.2/0.1,不同的部分程序如下:
WAITTIME PROC NEAR ;回球计时
PUSH AX
PUSH DX
MOV DX,IO8253C ;给8253控制字
MOV AL,36H ;计数器0先写低后写高,方式3,二进制
Test IntelModeFlag,01B ;判断智能模式是否打开
JNZ IntelMode_WatingTime
;打开状态则转移到0.1秒计时, 否则,按正常开关判断
OUT DX,AL
MOV DX,IO8255C ;读开关状态
IN AL,DX
AND AL,00110000B;开关4/5调节等待响应时间 CMP AL,10H ;5/4=0/1
JNZ WAIT1
MOV AX,600 ;速度0.3
JMP WTIME
WAIT1: CMP AL,20H ;5/4=1/0
JNZ WAIT2
MOV AX,400 ;速度0.2
JMP WTIME
WAIT2: CMP AL,30H ;5/4=1/1
JNZ WAIT3
MOV AX,200 ;速度0.1
JMP WTIME
WAIT3: MOV AX,1000 ;速度0.5
JMP WTIME
IntelMode_WatingTime:
MOV AX,200 ;速度0.1
WTIME: MOV DX,IO8253A
OUT DX,AL ;先写低字节
MOV AL,AH
OUT DX,AL ;后写高字节
MOV DX,IO8253C
MOV AL,74H ;方式2
OUT DX,AL
MOV AX,500 ;写入循环计数初值500
MOV DX,IO8253B
OUT DX,AL ;先写低字节
MOV AL,AH
OUT DX,AL ;后写高字节,开始计时
POP DX
POP AX
RET
WAITTIME ENDP
四.程序设计中遇到的问题及解决方法
1、8255的A、B、C口都被占用,数码管的位选无法使用8255实现。
解决方法:8255B口连接断码a~h,两个数码管要动态显示,需要使用74LS273进行位选,实现数码管显示。
2、在调试过程中发现只有右边的数码管亮,左边的不亮。
解决方法:先检查硬件设备,没有问题。
再利用单步调试,发现程序也没有问题。
后来发现左边的数码管有亮,但是因为亮的时间不够,肉眼看到的就是不亮,而右边的之所以一直亮,是因为在退出
数码管扫描显示子程序时,选中了位码S0,所以一直亮。
只需要将扫描子程序多多放在流水灯
的主程序里面,多运行几次,肉眼看到数码管就都是亮的,就能解决这个问题。
3、当接到球后,从左到右移动时,发现会有两个两个灯一起移动的情况。
解决方法:单步调试时发现程序有问题。
赋给流水灯的值为60H,即01100000,应将赋的值为40H,即01000000,左边第二个灯亮。
4、当在主程序中有的地方加上数码管扫描比分子程序后,出现了流水灯不走的情况。
解决方法:在单步调试中发现,这种情况都是发生在子程序加在JZ 、JNZ等判断条件前一行的。
说明子程序是改变了标志寄存器中的一些标志位。
所以应将子程序的调用放在其它地方,不能放在判
断条件的前一行。
五.分析与总结
1、具体实验分析见各部分的调试实验分析。
2、硬件是基础,做实验时要首先检查硬件设备是否可用,保证后续实验的可检测性。
3、在实验中应不要带电接线、插拔芯片;插拔接线时轻微转动,便于插拔。
4、在实验中学会使用示波器、万用表、逻辑笔观察、测量。
5、实验中出现问题时,要进行单步调试来发现问题。
6、在程序设计中,设计流程图是十分关键的,有了流程图后对软件设计有一定的指导方向。
附录:程序代码
IOPORT EQU 0b800H-0280H ;tpc卡中设备的io地址
IO8255A EQU IOPORT+288H ;8255A口地址
IO8255B EQU IOPORT+289H ;8255B口地址
IO8255C EQU IOPORT+28AH ;8255C口地址
IO8255 EQU IOPORT+28BH ;8255控制寄存器端口地址
IO8253C EQU IOPORT+283H ;8253控制寄存器地址
IO8253A EQU IOPORT+280H ;计数器通道0地址
IO8253B EQU IOPORT+281H ;计数器通道1地址
LS273 EQU IOPORT+2A8H ;273,位选地址;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
DATA SEGMENT
ZF DB 00H ;左边队员的比分
YF DB 00H ;右边队员的比分
ZX DB 00H ;左边队员比分显示
YX DB 00H ;右边队员比分显示
BallSpeed DB 00H ;记录球速
IntelModeFlag DB 00H
str_GameStart DB 0DH,0AH,'Competiton Begin!!!!!!',0DH,0AH,'$'
str_RightHit DB 0DH,0AH,'<Rigth> Please Serve the Ball',0DH,0AH,'$'
str_LeftHit DB 0DH,0AH,'<Left> Please Serve the Ball',0DH,0AH,'$'
str_Info_RightReady DB 0DH,0AH,'<Rigth> please Get Ready.',0DH,0AH,'$'
str_Info_LeftReady DB 0DH,0AH,'<Left> please Get Ready.',0DH,0AH,'$'
str_RightGoal DB 0DH,0AH,'<Rigth> get Goal!!',0DH,0AH,'$'
str_LeftGoal DB 0DH,0AH,'<Left> get Goal!!',0DH,0AH,'$'
str_Win_Right DB 0DH,0AH,'<Rigth> win!',0DH,0AH,'$'
str_Win_Left DB 0DH,0AH,'<Left> win!',0DH,0AH,'$'
str_Info_GameOver DB 0DH,0AH,'Game Over...',0DH,0AH,'$'
str_Info_CurrentScore DB 0DH,0AH,'Current Score Left:Right = ','$'
ProjectLine DB '------------------------------------------','$'
ProjectHead2 DB 'College: WJX . Class:000000 ','$'
ProjectHead3 DB ' GroupMember: Your Name ','$'
ProjectHead4 DB ' GroupMember: Your Name ','$'
ProjectWait DB ' Please Get The Right Setting. Then Press any Key to start a game...
','$'
str_Info_INIntelMode DB ' INFO: You are in Inteligent Mode.','$'
LED DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH ;段码(分别为0,1,2,3,4,5,6,7,8,9)DATA ENDS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
STACKS SEGMENT STACK
DB 100 DUP(?)
STACKS ENDS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Println MACRO StringNameInDataSegment ;打印字符串并换行
;print a string in data segment
push dx
push ax
mov dx,offset StringNameInDataSegment
mov AH,09h
int 21h
Call PrintLineEnd
pop ax
pop dx
EndM
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:STACKS
START: MOV AX,STACKS
MOV SS,AX
MOV AX,DATA
MOV DS,AX
InitializeFor8255:
MOV DX,IO8255 ;给8255控制字
MOV AL,89H ;方式0,A、B输出,C口输入 OUT DX,AL
ShowTeamHeading:
Println ProjectLine
Println ProjectHead2
Call PrintLineEnd
Println ProjectHead3
Println ProjectHead4
Call PrintLineEnd
Println ProjectLine
Call PrintLineEnd
Println ProjectWait
WaitKeyPressForNewGameStart:
push ax ;设置好模式后,任意输入开始游戏
mov AH,08h
int 21h
pop ax
MOV DX,IO8255C ;监视开关,是否开始;右边发球
IN AL,DX
TEST AL,01000000B ;智能模式开关已拨
JZ PTR_GameStart ;没拨不改变00设置
MOV IntelModeFlag,01H ;拨了改变设置到01
Println str_Info_INIntelMode
PTR_GameStart:
MOV DX,OFFSET str_GameStart
MOV AH,09H ;显示信息“比赛开始”
INT 21H
StartOneRound_Right: MOV DX,OFFSET str_RightHit MOV AH,09H ;显示信息“请右边队员发球”
INT 21H
WaitFor_Right_ToServeTheBall:
CALL DISP ;扫描比分
MOV DX,IO8255C ;监视开关,是否开始;右边发球 IN AL,DX
TEST AL,01H ;右边是否开关已拨
JZ WaitFor_Right_ToServeTheBall
MOV DX,OFFSET str_Info_LeftReady
MOV AH,09H ;显示信息“请左边队员接球”
INT 21H
MOV BL,01H ;起始状态,最右边开始亮
MOV AL,BL
MOV DX,IO8255A ;输出A口
OUT DX,AL ;00000001
MOV CL,8 ;八次移动
BISAI1: CALL DISP ;扫描比分
MOV DL,0FFH ;判断是否有ESC键按下
MOV AH,06H
INT 21H
CMP AL,27
;JZ EXIT1 ;有键按下,则退出
CALL DELAY ;从右边到左边
ROL BL,1 ;向左移动一次
MOV AL,BL
MOV DX,IO8255A ;输出A口
OUT DX,AL
CALL DISP
DEC CL ;每移动一次减一
CMP CL,1 ;判断是否在最左边
JNZ BISAI1 ;若未完,继续
MOV DX,IO8255C ;先检测左边开关的状态
IN AL,DX
TEST AL,80H ;=1000000 则说明按下过早
JNZ Left_FailOnePoint ;按失球计
;左侧没有过早按下,则
JMP Left_BeginTiming ;开始检测是否接到球;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; BEGIN4: JMP StartOneRound_Right ;远程跳转;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Left_BeginTiming:
Mov CX,5;归零CX,作为智能模式记数
Left_TimingConstrain:
CALL WAITTIME ;开始等待响应计时
Left_WaitingTheHit: ;等待左边接球
CALL DISP ;扫描比分
MOV DX,IO8255C
IN AL,DX ;IN AL,8255C
TEST AL,80H ;判断左边是否击到球
JNZ Left_HitBackTheBall ;击到球,比赛继续
;没击到球,判断计时器
IN AL,DX ;IN AL,8255C
TEST AL,02H
JNZ Left_WaitingTheHit ;一直循环,当(0.5S)(0.1s)计完时,算失球 Test IntelModeFlag,01B
;判断智能模式是否打开,打开状态下计到时间并不一定是失败
JNZ IntelMode_Left ;打开状态则转移, 否则,按正常失球算
JMP Left_FailOnePoint
IntelMode_Left:
DEC CX
CMP CX,0
JNA Left_FailOnePoint;等于零失球
JMP Left_TimingConstrain ;否则开始下一次0.1s计时
Left_HitBackTheBall:
MOV BallSpeed,CL ;记录回球时刻
MOV DX,OFFSET str_Info_RightReady
MOV AH,09H ;显示信息“请右边队员接球”
INT 21H
MOV BL,40H ;左边第二个马上亮;左边击到球
MOV DX,IO8255A
MOV AL,BL
OUT DX,AL
MOV CL,7 ;7次移动
JMP BISAI2
Left_FailOnePoint:
MOV BallSpeed,00H
CALL DISP ;先显示一下以前的比分
MOV BL,00H ;一次结束后灯全部熄灭
MOV AL,BL
MOV DX,IO8255A
OUT DX,AL
ADD YF,1 ;右边队员加1
CALL DISP ;再显示比分
MOV DX,OFFSET str_RightGoal
MOV AH,09H ;显示信息“右边队员得分”
INT 21H
CALL PCXS ;调用屏幕显示比分
CALL DISP
CMP YF,09H
JNZ StartOneRound_Left ;输家发球
JMP EXIT1 ;比赛结束
;退出程序:
EXIT1: MOV DX,OFFSET str_Info_GameOver
MOV AH,09H ;显示信息“比赛结束”
INT 21H
CALL DISP ;扫描比分
MOV DX,OFFSET str_Win_Right
MOV AH,09H ;显示信息“比赛结束”
INT 21H
MOV AH,4CH
INT 21H ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;由左边发球
StartOneRound_Left:
MOV DX,OFFSET str_LeftHit
MOV AH,09H ;显示信息“请左边队员发球”
INT 21H
WaitFor_Left_ToServeTheBall:
CALL DISP ;扫描比分
MOV DX,IO8255C ;监视开关,是否开始
IN AL,DX
TEST AL,80H ;左边是否开关已拨
JZ WaitFor_Left_ToServeTheBall
MOV DX,OFFSET str_Info_RightReady
MOV AH,09H ;显示信息“请右边队员接球”
INT 21H
MOV BL,80H ;起始状态,最左边开始亮
MOV AL,BL
MOV DX,IO8255A ;输出A口
OUT DX,AL ;10000000
MOV CL,8 ;八次移动
BISAI2: CALL DISP
MOV DL,0FFH ;判断是否有ESC键按下
MOV AH,06H
INT 21H
CMP AL,27
CALL DELAY ;左边到右边
ROR BL,1 ;向右移动一次
MOV AL,BL
MOV DX,IO8255A ;输出A口
OUT DX,AL
CALL DISP
DEC CL ;每移动一次减一
CMP CL,1 ;判断是否在最右边
JNZ BISAI2 ;若未完,继续
MOV DX,IO8255C ;先判断右边开关的状态
IN AL,DX
TEST AL,01H ;00000001
JNZ Right_FailOnePoint ;先按下,按失球计
;开始检测是否接到球
JMP Right_BeginTiming ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; BEGIN3: JMP BEGIN4 ;远程跳转;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Right_BeginTiming:
Mov CX,5;归零CX,作为智能模式记数
Right_TimingConstrain:
CALL WAITTIME ;等待响应计
Right_WaitingTheHit:
CALL DISP ;扫描比分
MOV DX,IO8255C
IN AL,DX
TEST AL,01H ;判断右边是否击到球
JNZ Right_HitBackTheBall ;击到球,比赛继续
IN AL,DX
TEST AL,02H
JNZ Right_WaitingTheHit ;一直循环,当0.5S完时,算失球
Test IntelModeFlag,01B
;判断智能模式是否打开,打开状态下计到时间并不一定是失败
JNZ IntelMode_Right ;打开状态则转移, 否则,按正常失球算
JMP Right_FailOnePoint
IntelMode_Right:
DEC CX
CMP CX,0
JNA Right_FailOnePoint;等于零失球
JMP Right_TimingConstrain ;否则开始下一次0.1s计时
Right_HitBackTheBall:
MOV BallSpeed,CL
MOV DX,OFFSET str_Info_LeftReady
MOV AH,09H ;显示信息“请左边队员接球”
INT 21H
MOV BL,02H ;右边第二个马上亮
MOV AL,BL
MOV DX,IO8255A
OUT DX,AL
MOV CL,7 ;7次移动
JMP BISAI1
Right_FailOnePoint:
MOV BallSpeed,00H
CALL DISP ;先显示一下以前的比分
MOV BL,00H ;一次结束后灯全部熄灭
MOV AL,BL
MOV DX,IO8255A
OUT DX,AL
ADD ZF,1 ;左边队员加1
CALL DISP ;再显示比分
MOV DX,OFFSET str_LeftGoal
MOV AH,09H ;显示信息“左边队员淂分”
INT 21H
CALL PCXS ;调用屏幕显示比分
CMP ZF,09H ;判断是否满分
JNZ BEGIN3 ;输家发球
JMP EXIT ;比赛结束
;退出程序:
EXIT: MOV DX,OFFSET str_Info_GameOver
MOV AH,09H ;显示信息“比赛结束”
INT 21H
CALL DISP ;扫描比分
MOV DX,OFFSET str_Win_Left
MOV AH,09H ;显示信息“比赛结束”
INT 21H
mov AH,08h
int 21h ;等待任意键盘输入后关闭程序
MOV AH,4CH
INT 21H ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DELAY PROC NEAR ;延迟子程序
PUSH AX
PUSH DX
CALL LEDTIME ;送初始值,控制LED计时
JM: CALL DISP ;扫描比分
MOV DX,IO8255C ;看计时状态
IN AL,DX ;右边第二个开关检测计时器是否满
TEST AL,02H
JNZ JM
POP DX
POP AX
RET ;开始移动
DELAY ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; PCXS PROC NEAR ;显示屏幕子程序
PUSH AX
PUSH DX
MOV DX,OFFSET str_Info_CurrentScore
MOV AH,09H ;显示信息“现在比分”
INT 21H
MOV AL,YF ;比分转换
MOV AH,ZF
ADD AL,30H
ADD AH,30H
MOV YX,AL
MOV ZX,AH
MOV DL,ZX ;显示真实比分
MOV AH,02H
INT 21H
MOV DL,3AH
MOV AH,02H
INT 21H
MOV DL,YX
MOV AH,02H
INT 21H
POP DX
POP AX
RET
PCXS ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DISP PROC NEAR ;显示LED灯子程序
PUSH CX
PUSH AX
PUSH DX
PUSH BX
MOV CX,3
Z: PUSH CX
MOV DX,LS273
MOV AL,00H
OUT DX,AL
XOR SI,SI
MOV SI,OFFSET LED
MOV BL,ZF
MOV BH,00H
ADD SI,BX
MOV AL,BYTE PTR [SI]
MOV DX,IO8255B
OUT DX,AL ;输出左边分数
MOV DX,LS273
MOV AL,02H
OUT DX,AL
MOV CX,3000
ZZ: LOOP ZZ ;短延时
MOV DX,LS273
MOV AL,00H
OUT DX,AL ;左边LED灭
XOR SI,SI
MOV SI,OFFSET LED
MOV BH,00H
MOV BL,YF
ADD SI,BX
MOV AL,BYTE PTR [SI]
MOV DX,IO8255B
OUT DX,AL ; 输出右边数
MOV DX,LS273
MOV AL,01H
OUT DX,AL ;右边LED亮
MOV CX,3000
ZZZ: LOOP ZZZ
POP CX
LOOP Z
POP BX
POP DX
POP AX
POP CX
RET
DISP ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; LEDTIME PROC NEAR ;流水灯速度
PUSH AX
PUSH DX
MOV DX,IO8253C ;给8253控制字
MOV AL,36H ;计数器0先写低后写高,方式3,二进制
OUT DX,AL
Test IntelModeFlag,01B ;判断智能模式是否打开
JNZ IntelMode_LEDTime
;打开状态则转移到按BallSpeed判断计时, 否则,按正常开关判断
MOV DX,IO8255C ;读开关状态
IN AL,DX
AND AL,00001100B;开关2/3调节速度
CMP AL,04H ;2/3=1/0
JNZ NEXT1
MOV AX,600 ;速度0.3
JMP TIME
NEXT1: CMP AL,08H ;2/3=0/1
JNZ NEXT2
MOV AX,400 ;速度0.2
JMP TIME
NEXT2: MOV AX,1000 ;速度0.5
JMP TIME
IntelMode_LEDTime:
MOV DL,BallSpeed
MOV AX,1000
CMP DL,0
JE TIME
CMP DL,1
JE TIME
MOV AX,800
CMP DL,2
JE TIME
MOV AX,600
CMP DL,3
JE TIME
MOV AX,400
TIME: MOV DX,IO8253A
OUT DX,AL ;先写低字节
MOV AL,AH
OUT DX,AL ;后写高字节
MOV DX,IO8253C
MOV AL,74H ;方式2
OUT DX,AL
MOV AX,500 ;写入循环计数初值500
MOV DX,IO8253B
OUT DX,AL ;先写低字节
MOV AL,AH
OUT DX,AL ;后写高字节,开始计时
POP DX
POP AX
RET
LEDTIME ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; WAITTIME PROC NEAR ;回球计时
PUSH AX
PUSH DX
MOV DX,IO8253C ;给8253控制字
MOV AL,36H ;计数器0先写低后写高,方式3,二进制
Test IntelModeFlag,01B ;判断智能模式是否打开
JNZ IntelMode_WatingTime
;打开状态则转移到0.1秒计时, 否则,按正常开关判断
OUT DX,AL
MOV DX,IO8255C ;读开关状态
IN AL,DX
AND AL,00110000B;开关4/5调节等待响应时间
CMP AL,10H ;5/4=0/1
JNZ WAIT1
MOV AX,600 ;速度0.3
JMP WTIME
WAIT1: CMP AL,20H ;5/4=1/0
JNZ WAIT2
MOV AX,400 ;速度0.2
JMP WTIME
WAIT2: CMP AL,30H ;5/4=1/1
JNZ WAIT3
MOV AX,200 ;速度0.1
JMP WTIME
WAIT3: MOV AX,1000 ;速度0.5
JMP WTIME
IntelMode_WatingTime:
MOV AX,200 ;速度0.1
WTIME: MOV DX,IO8253A
OUT DX,AL ;先写低字节
MOV AL,AH
OUT DX,AL ;后写高字节
MOV DX,IO8253C
MOV AL,74H ;方式2
OUT DX,AL
MOV AX,500 ;写入循环计数初值500
MOV DX,IO8253B
OUT DX,AL ;先写低字节
MOV AL,AH
OUT DX,AL ;后写高字节,开始计时
POP DX
POP AX
RET
WAITTIME ENDP
PrintLineEnd Proc near ;打印回车子过程
push dx
push ax
MOV AH,02H
MOV DL,0DH ;key enter字符
INT 21H
MOV DL,0AH ;line end字符
INT 21H
pop ax
pop dx
ret
PrintLineEnd EndP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; CODE ENDS
END START。