有一种常见的益智小游戏:
游戏中,屏幕会显示一组10位数字,并很快消失,
玩家通过瞬时记忆,输入相同的内容,如正确,进入下一关;错误,将重新开始
随着关卡后移,屏幕显示数组的时间会越来越短,以提高难度
51虽然是一款最基础的单片机,但这次,我想实现上面的游戏功能。
需要的外设:(如图)51开发板 ,集成一体的红外接收头 遥控器 LCD1602
先预想好按键功能:
分析几个问题:
1、产生随机数的方法:rand函数,种子则通过定时器的TH 和TL读取
2、红外遥控数据的读取:好在开发板接到的是单片机的外部中断1引脚 P3.3 通过外部中断,读取按键数据按照红外协议即可
3、存储游戏记录:好不容易玩到成绩很高的记录,一定要存储下来,这里利用开发板上的AT24C02可实现,通过单片机IO口模拟IIC的存取,记录游戏最高记录
4、游戏中原本该按确认键(或其他),结果按错了:做一个按键过滤机制,当前游戏处于某一状态下,其他按键按下无效。
有了上面的几条分析,在写程序的时候就会顺利很多。下面贴出来主要函数的代码:
获取随机数:
void getrand()
{
uchar i=0;
uchar t; //随机种子,通过定时器1读取
for(i=0;i<10;i++)
{
if(i%2==0)
t= TL1;
else
t= TH1;
srand(t);
cnum[i]=ASCII[(char)(rand()%10)]; //取随机数('0'~'9')
}
}
外部中断的红外遥控数据读取:
void exint1()interrupt 2
{
uchar i=0,j=0,k=0,us=0;
uchar addr[4]={0};
EX1=0;
for(i=0;i<255;i++) //9ms内有高电平认为是干扰
{
if(P3&0x08) //255的值实际时间为800us
{
EX1=1;
return;
}
}
while(!(P3&0x08)); //等待9ms低电平过去
for(i=0;i<4;i++)
{
for(j=0;j<8;j++)
{
while(P3&0x08); //等待4.5ms高电平过去
while(!(P3&0x08)); //等待0.56ms低电平后面的高电平
while(P3&0x08) //计算这个高电平的时间
{
for(us=0;us<=64;us++); //100us的延时语句
if((k++)>=30) //高电平时间过长退出程序
{
EX1=1;
return;
}
}
addr[i]=addr[i]>>1; //接收一位数据
if(k>=8)
addr[i]=addr[i]|0x80; //高电平大于0.56ms,则为1
k=0;
}
}
flag_r = 1;
revd = addr[2];
EX1=1;
}
IIC模拟:
bit WriteNByte(unsigned int sla,unsigned int suba,unsigned int *s,unsigned int n)
{
unsigned int i;
I2C_Start();//启动I2C
SendData(sla);//发送器件地址
Test_Ack();
if(i2c_flag==0)
return(0);
SendData(suba);
Test_Ack();
if(i2c_flag==0)
return(0);
for(i=0;i<n;i++)//写入8字节数据
{
SendData(*(s+i));
Test_Ack();
if(i2c_flag==0)
return(0);
}
I2C_Stop();
return(1);
}
bit ReadNByte(unsigned int sla,unsigned int suba,unsigned int *p,unsigned int n)
{
unsigned int i;
I2C_Start();//启动I2C
SendData(sla);//发送器件地址
Test_Ack();
//if(i2c_flag==0) return(0);
SendData(suba);//发送器件内部地址
Test_Ack();
//if(i2c_flag==0) return(0);
I2C_Start();
SendData(sla+1);
Test_Ack();
if(i2c_flag==0) return(0);
for(i=0;i<n-1;i++)//读取字节数据
{
*(p+i)=ReceiveData();//读取数据
Ack();
}
*(p+n-1)=ReceiveData();
NoAck();
I2C_Stop();
return(1);
}
简单的过滤机制:
if(status == 0) //状态过滤机制 0
{
if(revd !=0x45) revd = 0;
}
if(status == 1) //状态过滤机制 1
{
if(revd !=0x45 && revd !=0x43) revd = 0;
}
好了,编译通过就开始游戏吧: