求助大侠,微机原理实训 乒乓球比赛游戏机 汇编编写 最好有PCB图,用的8086,谢了!!

2024年11月29日 08:56
有4个网友回答
网友(1):

1.问题描述
用 8 个 LED 发光管 (4 个红, 4 个绿 ) 的来回滚动显示来模拟打乒乓球时乒乓球在两边球台上的来回运动。比赛双方用按按钮 ( 双方各用 1 个按钮 ) 的方法来模拟发球与接球 , 即发球方按动其控制的按钮 , 球从发球方一侧向对方运动 (LED 发光管从发球方到对方逐个点亮 , 滚动显示 ), 当球运动至接球方时 , 接球方立即按动其控制的按钮 , “击球”使球“弹回”发球方一侧 , 如此周而复始 , 直至在规定的击球时间内有一方未能完成击球动作 , 从而对方得一分 , 然后继续比赛。
2.设计要求
比赛规则可参照一般的乒乓球比赛规则。要求:
(1)球以每0.5秒滚过1个LED的速度移动;
(2)回球需在球到达后的0.5秒内进行(按下按钮), 否则按失球计;
(3)球未到达提前按下按钮不起回球作用 ;
(4)用 4 个八段码为双方记分 ( 每方 2 个八段码 ,10 进制计数 , 初始值 0:0) 。

设备:单脉冲电路,可编程并行接口8255,可编程定时计数器8253,LED流水灯,七段数码管,开关等。

一、 实验原理
1.8253定时器选用方式0,实现定时功能。两个七段数码管要实现连续显示,必须每隔5~10ms刷新一次,而灯移动速度为300~500ms。设定定时周期为5ms,当计数停止,8253输出高电平时,分别显示比分的高位和低位。经过一定数量的定时周期后,再进行灯移动的操作。
2.8255并行接口A口B口分别用来控制LED流水灯及数码管的显示,C口则用于读入各开关状态及输出数码管片选信号。
3.单脉冲开关模拟击球,当8255读入脉冲信号为高电平时,通过判断灯当前移动方向和击球者,来确定灯下一次的移动方向。
4.LED流水灯表示乒乓球移动,灯每次移动应留有足够的时间给操作者拨动调速开关,或按下脉冲开关。
5.七段数码管与比赛同步显示比分,显示0~f相应的16进制控制数为0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x7b,0x71。

二、 硬件接线图

三、 程序框图

四、 源程序
程序源代码如下:
(含注解)
//--------------------------------------------------------------------------------------------------
// File Name: table tennis.cpp
// Version: 1.0标准版
// Created By: 枫飞
// Created date: 01/12/2010
// Description: 实现可记分、判断胜负,可速度调整的乒乓球对打
// 本程序全部由本人编写,如有雷同,不胜荣幸!
//--------------------------------------------------------------------------------------------------
#include
#include
#include
#include
#include "ApiEx.h"
#pragma comment(lib,"ApiEx.lib")
int pa=0x280;
int pb=0x281;
int pc=0x282;
int pn1=0x283;
int p0=0x288;
int p1=0x289;
int p2=0x28a;
int pn2=0x28b;
int s[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x7b,0x71};
// 0 1 2 3 4 5 6 7 8 9 a b c d e f
void leddic(unsigned char &led, int f) //灯移动函数
{
int x=led;
if(f==0) x=x/2; //若方向向右,灯向右移动一个
else if(f==1) x=x*2; //若方向向左,灯向左移动一个
else printf("Error!");
led=x;
}
void speed(int &s) //球速控制,从8255C口读入开关状态,
{ //若为高电平,调整速度为高速
unsigned char data;
int x;
PortReadByte(pc,&data);
x=data;
x=x&4;
if(x==0) s=100; //默认5*100ms
if(x==1) s=60; //高速5*60ms
}
void scorem(int m) //通过数码管显示比分
{
unsigned char data;
data=s[m];
PortWriteByte(pc,0x20); //选择数码管高位
PortWriteByte(pa,data); //显示甲得分
}
void scoren(int n)
{
unsigned char data;
data=s[n];
PortWriteByte(pc,0x10); //选择数码管低位
PortWriteByte(pa,data); //显示乙得分
}
void start(unsigned char &led, int &f,int &s,int m,int n) //发球子函数
{
unsigned char data;
int x;
PortWriteByte(pn2,0x57); //8253计数器1初始化,低八位,方式3,控制字01010111B
PortWriteByte(p1,0x10); //8253计数器1计数初值10
for(;1<2;)
{
speed(s);
PortReadByte(pc,&data);
x=data;
x=x&1;
if(x==1) //若甲发球,灯从左往右
{
led=0x80;
f=0;
break;
}
x=data;
x=x&2;
if(x==1) //若乙发球,灯从右往左
{
led=0x1;
f=1;
break;
}
x=data;
x=x&8;
if(x==1) //当8253输出为高电平时,显示甲得分
{
scorem(m);
}
else //当8253输出为低电平时,显示乙得分 scoren(n);
}
}
void out(unsigned char &led, int &f,int &m,int &n) //判断球是否出界,即选手得分
{
if(f==1) //球向左运动时
{
if(led==0x0) //球超出左边界
{
printf("乙得分!\n");
n++;
printf("比分:");
printf("%d-%d",m,n);
printf("\n\n");
}
}
else //球向右运动时
{
if(led==0x0) //球超出右边界
{
printf("甲得分!\n");
m++;
printf("比分:");
printf("%d-%d",m,n);
printf("\n\n");
}
}
if(((m==11)&&(m-n>=2))||((m>11)&&(m-n>=2))) //判断整局比赛的胜负
{
printf("此局甲获胜!重新计分!\n\n\n");
m=n=0;
}
else if(((n==11)&&(n-m>=2))||((n>11)&&(n-m>=2)))
{
printf("此局乙获胜!重新计分!\n\n\n");
m=n=0;
}
}
void attack(unsigned char &led,int &s, int &f,int &m,int &n) //击球子函数
{
unsigned char data;
int x,y;
STA:
printf("请发球!\n");
start(led,f,s,m,n);
PortWriteByte(pn2,0x51); //8253计数器1初始化,低八位,方式0,控制字01010001B
Red:
PortWriteByte(pb,led);
for(int i=1;i<=s;i++)
{
PortWriteByte(p1,5); //8253计数器1计数初值5
Goo:
PortReadByte(pc,&data);
x=data;
y=data;
y=y&8;
if(y==0) goto Goo; //当8253未输出高电平时,继续读入
if(i%2==1)scorem(m);
else scoren(n);
if(f==1) //球向左运动
{
x=x&1;
if((x==1)&&(led>=0x10)) //球靠近甲且甲击球
{
f=0; //调整球的运动方向为向右
}
}
else //球向右运动
{
x=data;
x=x&2;
if((x==2)&&(led<=0x8)) //球靠近乙且乙击球
{
f=1; //调整球的运动方向为向左
}
}
}
leddic(led,f);
out(led,f,m,n);
if(led==0x0)
{
PortWriteByte(pb,led);
goto STA;
}
goto Red;
}
void main()
{
unsigned char led;
int f=1,s=0; //f为灯移动方向,默认向右;s为灯移动速度
int m=0,n=0; //m为甲得分,n为乙得分
Startup(); //打开设备
PortWriteByte(pn1,0x81); //8255初始化,A口B口输出,
//C口高位输出,低位输入,控制字10000001B
PortWriteByte(pn2,0x27); //8253计数器0初始化,高八位,方式3,控制字00100111B
PortWriteByte(p0,0x20); //8253计数器0计数初值2000
attack(led,s,f,m,n); //调用击球子函数
Cleanup(); //关闭设备
}
五、 结论
实现了能够计分、同步显示比分的模拟乒乓球比赛。
能够实现或完成的功能如下:
1. LED灯模拟乒乓球的移动
2. 模拟乒乓球的击球、发球
3. 与实际比赛一样判断得分和整局的胜负情况
4. 可以调整发球速度
5. 计分、同步显示比分

网友(2):

这个应该是比较简单了,但是30分估计没人做

网友(3):

要求太高,分值不高,性价比低啊。

网友(4):

谁回答了我也送Ta 100的积分!