程序运行效果说明
测试方法说明:只需要一个电路板,按键KEY3用于选手1开球(即左边开球)或回击球,按键KEY2用于选手2开球(即右边开球)或回击球。刚开始的时候数码管上显示“00 VS 00”,LED灯中间有两个亮灯,是初始状态。如果按下KEY3或KEY2键,会有一亮灯从最左边(最右边)出现,并一位位地向右移(左移),当亮灯移至最右边(最左边)时,按下KEY3(KEY2)键则表示回击球成功,亮灯会逆向开始移动,否则开球方得分加一。一局的胜负是某一方取得11分且比对方分数大2为止,数码管中间显示局数比分,如果一方局数得分为2,则表示其比赛取胜,相应数码管会有闪烁图案表示。
程序相关电路及工作原理说明
乒乓球游戏功能主要依靠2个部分来实现,一是数码管与LED部分,二是按键部分。
两个部分原理很简单。需要的注意的是数码管和LED灯不能同时显示,需要利用引脚P2^3分时调控,利用人眼球的视觉残留和LED灯的余晖效应来实现相应功能。
代码如下:
#include "STC15F2K60S2.h"
#define uint unsigned int
#define uchar unsigned char
sbit Led_sel=P2^3;//数码管与LED灯的切换引脚,为1时选择LED灯,为0时选择数码管
sbit Sel0=P2^0;
sbit Sel1=P2^1;
sbit Sel2=P2^2;//位选要用的三个引脚
sbit Key2=P3^3;//Key2
sbit Key3=P1^7;//Key3
uchar show_w1,show_w2,show_w3,show_w4,show_w5,show_w6,show_w7,show_w8,flag,count,v,s;
//show_wi是数码管上数字显示,flag用来分频所用和位选下标所用,count也用于分频,v:s是局比分
uchar duanxuan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40,0x00}; //段选,显示0-f
uchar weixuan[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};//位选
uint i;//状态参数,0表示左边开球,1表示右边开球,2表示等待开球,3表示比赛结束
uint P1score,P2score; //分别是左边和右边的分数
uint shfitcounter; //分频所用的变量
uchar G_value; //LED显示
void Init()
{
P2M0=0xff;
P2M1=0x00;
P0M0=0xff;
P0M1=0x00;//P0和P2设置为推挽输出
G_value=0x18;//LED灯中间显示两个红点
P0=G_value;
Led_sel=1;
i=2;
v=s=0;
flag=0;
count=0;
shfitcounter=0;
P1score=0;
P2score=0;
show_w1=0x3f; //这里是让数码管上显示 00 VS 00
show_w2=0x3f;
show_w3=0x00;
show_w4=0x3E;
show_w5=0x6D;
show_w6=0x00;
show_w7=0x3f;
show_w8=0x3f;
TMOD=0x01;//定时器0,方式1
EA=1;//打开总的中断
ET0=1;//开启定时器中断
TH0=(65535-100)/256;//定时器初值0.1毫秒
TL0=(65535-100)%256;
TR0=1;//启动定时器
}
void Delay_1ms(uint t) //延时函数
{
uchar j;
for(;t>0;t--)
for(j=110;j>0;j--);
}
//定时器中断处理程序
void timer0() interrupt 1 //把数码管的显示提到中断里面来了,定时器中断
{
TH0=(65535-100)/256;//重装定时器0的初值
TL0=(65535-100)%256;
P0=G_value;
Led_sel=1;
flag++;
shfitcounter++;
if(flag==8) //分频作用,同时用来作为位选下标所用
{
flag=0;
count++;
}
if(count==20) //考虑到扫描频率很高这里进行分频显示;
{
count=0;
Led_sel=1; //这一半的时间用来显示LED
}
else if(count<10)
{
P0=0x00;
Led_sel=0; //这一半的时间用来显示数码管
P2=weixuan[flag]; //位选
switch(flag) //段选,show_wi对应负责第i个数码管上的数字显示内容
{
case 0:P0=show_w1;break;
case 1:P0=show_w2;break;
case 2:P0=show_w3;break;
case 3:P0=show_w4;break;
case 4:P0=show_w5;break;
case 5:P0=show_w6;break;
case 6:P0=show_w7;break;
default:P0=show_w8;break;
}
}
else
P0=G_value; //这里显示的是LED灯上的
//这里是处理乒乓球的击打过程
if(shfitcounter==1000) //考虑到扫描频率很高这里进行分频数据更新;
{
shfitcounter=0;
if(i==0)//从左往右开始
{
G_value=G_value>>1; //乒乓球右移
if(G_value==0x00) //如果到右边了还没被击打,左边分数加一
{
P1score++;
show_w1=duanxuan[P1score/10];
show_w2=duanxuan[P1score%10];
}
}
else if(i==1)//从右往左开始
{
G_value=G_value<<1; //乒乓球左移
if(G_value==0x00) //如果到左边了还没被击打,右边分数加一
{
P2score++;
show_w7=duanxuan[P2score/10];
show_w8=duanxuan[P2score%10];
}
}
if(P1score-P2score>=2&&P1score>=11)//这一局左边赢了
{
P1score=P2score=0;
v++;//左边赢了一局
show_w1=duanxuan[P1score/10];
show_w2=duanxuan[P1score%10];
show_w4=duanxuan[v];
show_w5=duanxuan[s];
show_w7=duanxuan[P2score/10];
show_w8=duanxuan[P2score%10];
}
else if(P2score-P1score>=2&&P2score>=11)//这一局右边赢了
{
P1score=P2score=0;
s++;//右边赢了一局
show_w1=duanxuan[P1score/10];
show_w2=duanxuan[P1score%10];
show_w4=duanxuan[v];
show_w5=duanxuan[s];
show_w7=duanxuan[P2score/10];
show_w8=duanxuan[P2score%10];
}
else if(v>=2)//左边先赢两局,表明比赛胜利,中间显示两个11,LED闪烁
{
v=s=0;
P1score=P2score=0;
i=3;
show_w1=0x62;
show_w2=0x62;
show_w3=0x62;
show_w4=duanxuan[1];
show_w5=duanxuan[1];
show_w6=0x62;
show_w7=0x62;
show_w8=0x62;
}
else if(s>=2) //右边先赢两局,表明比赛胜利,中间显示两个22,LED闪烁
{
v=s=0;
P1score=P2score=0;
i=3;
show_w1=0x62;
show_w2=0x62;
show_w3=0x62;
show_w4=duanxuan[2];
show_w5=duanxuan[2];
show_w6=0x62;
show_w7=0x62;
show_w8=0x62;
}
}
}
void main()
{
Init();
while(1)
{
if(i==2)//i=2表示等待开球状态
{
if(Key3==0)//KEY3按下,左边开球
{
i=0;
G_value=0x80;
}
else if(Key2==0)//KEY2按下,右边开球
{
i=1;
G_value=0x01;
}
}
if(i==0)
{
if(G_value==0x00)
{
i=2;
G_value=0x18;
}
if(Key2==0&&G_value==0x01) i=1;//球在最右边时按下KEY2,表示回击球
}
else if(i==1)
{
if(G_value==0x00)
{
i=2;
G_value=0x18;
}
if(Key3==0&&G_value==0x80) i=0;//球在最左边时按下KEY3,表示回击球
}
else if(i==3) //i=3是比赛结束状态,进行闪烁
{
G_value=0xFF;
Delay_1ms(500);
G_value=0x00;
Delay_1ms(500);
G_value=0xFF;
}
Delay_1ms(100);
}
}