微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 用51单片机设计一款记忆力测试小游戏

用51单片机设计一款记忆力测试小游戏

时间:10-02 整理:3721RD 点击:
另一个蓝牙遥控的帖子请看这里:http://bbs.elecfans.com/jishu_273193_1_1.html

有一种常见的益智小游戏:
游戏中,屏幕会显示一组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=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=addr>>1;    //接收一位数据
            if(k>=8)
                addr=addr|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;
            }

好了,编译通过就开始游戏吧:


哈哈哈,谢谢分享!

很有意思的东东

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top