當前位置:編程學習大全網 - 編程語言 - 求助大俠,微機原理實訓 乒乓球比賽遊戲機 匯編編寫 最好有PCB圖,用的8086,謝了!!

求助大俠,微機原理實訓 乒乓球比賽遊戲機 匯編編寫 最好有PCB圖,用的8086,謝了!!

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 <stdio.h>

#include <conio.h>

#include <string.h>

#include <iostream.h>

#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. 計分、同步顯示比分

  • 上一篇:謎語 腦筋急轉彎
  • 下一篇:AT89C52+DS1302單片機萬年歷程序
  • copyright 2024編程學習大全網