基于51单片机的打地鼠游戏机1602和led显示模拟(源码齐全)
- 格式:doc
- 大小:1.69 MB
- 文档页数:45
.《现代通信技术》课程设计基于51单片机的模拟打地鼠游戏设计院系:工学院专业班级:通信工程10秋2班姓名:钟丽薇学号:10032202小组成员:陆韵指导教师:徐振、赵兰完成日期2013年10月目录1 设计任务 (1)1.1设计题目及材料 (1)1.2设计要求 (1)1.3设计进度安排 (2)2 总体方案 (3)2.1硬件设计 (3)2.1.1 主控芯片 (3)2.1.2 数码管模块 (4)2.1.3 LED模块 (5)2.1.4 独立按键模块 (5)2.2软件设计 (6)3 功能调试 (7)3.1调试过程 (7)3.2调试中遇到的问题 (7)4 设计总结 (8)5 致谢 (9)1 设计任务通过本次课程设计,运用已学的课程知识,自主设定题目及要求,进行软硬件系统的设计和调试,对《现代通信技术》课程中涉及的芯片结构、控制原理、硬件和编程等方面有一定的感性认识和实践操作能力,从而加深对本课程知识点的理解,使应用知识能力、设计能力、调试能力以及报告撰写能力等方面有显著提高。
1.1 设计题目及材料我们的课程设计选题定为《基于51单片机的模拟打地鼠游戏设计》。
将所掌握的的元器件组合在一起,设计出具有可玩性的实用小制作,不仅巩固了已学习的知识,更能拓展自己的思维能力。
所用到的材料:表1.1 材料列表STC89C52单片机开发板1块4位8段数码管(共阳)1个LED灯5个轻触按键5个100Ω电阻5个0.5kΩ电阻4个9013三极管4个杜邦线若干1.2 设计要求要求作品完成后,可以实现简易打地鼠游戏的功能。
具体如下:接通电源后,游戏开始,数码管显示“0”,同时随意点亮一个LED,在2秒时间内按下对应的按键,则数码管示数加一,游戏继续;反之,则示数归零,游戏结束1.3 设计进度安排表1.2 设计进度安排10月21日(周一) 收集资料,确定选题,大致设计方案10月22日(周二) 设计电路图,采购所需材料10月23日(周三) 完成具体设计,组装电路板10月24日(周四) 完成硬件部分,完成部分论文编写程序;软硬件调试10月28日(周一) 至10月29日(周二)10月30日(周三) 最终调试,完成论文2 总体方案2.1 硬件设计采用AT89S52为主控芯片的单片机开发板,选取共阳四位八段数码管作为计分显示,以及5个LED和5个独立按键分别制作模块,通过杜邦线连接到单片机上,使其成为一个为简易的游戏机。
基于51单片机的红外遥控+液晶LCD1602显示程序源代码/*******************红外遥控+液晶LCD1602测试程序源代码******************** 单片机型号:STC15W4K56S4,内部晶振:22.1184M。
功能:红外遥控+液晶LCD1602显示功能测试。
操作说明:按下红外遥控器上的“CH-”键,液晶LCD1602上显示“CH-”。
按下红外遥控器上的“CH”键,液晶LCD1602上显示“CH”。
按下红外遥控器上的“CH+”键,液晶LCD1602上显示“CH+”。
按下红外遥控器上的“|<<”键,液晶LCD1602上显示“|<<”。
按下红外遥控器上的“>>|”键,液晶LCD1602上显示“>>|”。
按下红外遥控器上的“>||”键,液晶LCD1602上显示“>||”。
按下红外遥控器上的“-”键,液晶LCD1602上显示“-”。
按下红外遥控器上的“+”键,液晶LCD1602上显示“+”。
按下红外遥控器上的“EQ”键,液晶LCD1602上显示“EQ”。
按下红外遥控器上的“0”键,液晶LCD1602上显示“0”。
按下红外遥控器上的“100+”键,液晶LCD1602上显示“100+”。
按下红外遥控器上的“200+”键,液晶LCD1602上显示“200+”。
按下红外遥控器上的“1”键,液晶LCD1602上显示“1”。
按下红外遥控器上的“2”键,液晶LCD1602上显示“2”。
按下红外遥控器上的“3”键,液晶LCD1602上显示“3”。
按下红外遥控器上的“4”键,液晶LCD1602上显示“4”。
按下红外遥控器上的“5”键,液晶LCD1602上显示“5”。
按下红外遥控器上的“6”键,液晶LCD1602上显示“6”。
按下红外遥控器上的“7”键,液晶LCD1602上显示“7”。
按下红外遥控器上的“8”键,液晶LCD1602上显示“8”。
51单片机驱动1602液晶显示器c程序/*程序效果:单片机控制液晶显示器1602 显示字母数字,用户自行更改io程序原创安全:51hei*/#includereg52.h //头文件#define uchar unsigned char //宏定义#define uint unsigned intuchar code table[]=“51HEI XING XING “ ; //显示的字母uchar code table1[]=“51HEI MCUXUE YUAU” ;sbit lcdrs=P1; //寄存器选择引脚sbit lcdwr=P1;//读写引脚sbit lcde=P1 ; //片选引脚void delay(uchar x) //延时子函数{uchar i,j;for(i=x;i0;i--) for(j=110;j0;j--);}void write_com(uchar com) //写指令子函数{ //根据1602 液晶显示器协议编写P2=com; lcdrs=0;lcdwr=0;delay(5);lcde=0; delay(5);lcde=1; }void write_dat(uchar dat) //写数据子函数{P2=dat; lcdrs=1;lcdwr=0;delay(5);lcde=0;delay(5);lcde=1;}void init() //初始化子函数{write_com(0x01); //清屏write_com(0x3f); //功能设置write_com(0x0d); //显示控制write_com(0x06); //输入方式设置}void main(){ uchar i; //定义局部变量init();write_com(0x80+0x02+0x10); //指针的位置for(i=0;i15;i++) //显示{ write_dat(table[i]); delay(50); //延时,用于调节速度不匹配}write_com(0x80+0x40+0x10);for(i=0;i16;i++){ write_dat(table1[i]); delay(50);}for(i=0;i16;i++){ write_com(0x18); delay(50);} while(1);}tips:感谢大家的阅读,本文由我司收集整编。
LCD显示电路#include<reg51.h>sbit RS=P3^7; //寄存器选择位,将RS位定义为P2.0引脚sbit RW=P3^6; //读写选择位,将RW位定义为P2.1引脚sbit E=P2^7; //使能信号位,将E位定义为P2.2引脚sbit BF=P0^7; //忙碌标志位,将BF位定义为P0.7引脚#define Lcd_Data P0#include <string.h>#include<intrins.h> //包含_nop_()函数定义的头文件unsigned char code string1[ ]={0x77,0x75,0x20,0x79,0x61,0x6E,0x67,0x20,0x79,0x61,0x6E,0x67,0x20,0x20,0x20,0x20}; //第一行显示的字符void Lcd_delay1ms() // 函数功能:延时1ms//注:不同单片机不同晶振需要对此函数进行修改{ unsigned char i,j;for(i=0;i<90;i++)for(j=0;j<33;j++);}void Lcd_delay(unsigned int n) // 函数功能:延时若干毫秒,入口参数:n{ unsigned int i;for(i=0;i<n;i++)Lcd_delay1ms();}/*****************************************************函数功能:判断液晶模块的忙碌状态返回值:result。
result=1,忙碌;result=0,不忙***************************************************/bit Lcd_BusyTest(void)bit result;RS=0; //根据规定,RS为低电平,RW为高电平时,可以读状态RW=1;E=1; //E=1,才允许读写_nop_(); //空操作_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间result=BF; //将忙碌标志电平赋给resultE=0;return result;}/*****************************************************函数功能:将模式设置指令或显示地址写入液晶模块入口参数:dictate***************************************************/void Lcd_WriteCom (unsigned char dictate){ while(Lcd_BusyTest()==1); //如果忙就等待RS=0; //根据规定,RS和R/W同时为低电平时,可以写入指令RW=0;E=0; //E置低电平(写指令时就是让E从0到1发生正跳变,所以应先置ぜ? _nop_();_nop_(); //空操作两个机器周期,给硬件反应时间Lcd_Data=dictate; //将数据送入P0口,即写入指令或地址_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间E=1; //E置高电平_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令}/*****************************************************函数功能:指定字符显示的实际地址x入口参数:注:此函数已经加上了0x80,故只需写上实际地址就行***************************************************/void Lcd_WriteAddress(unsigned char x){ Lcd_WriteCom(x|0x80); //显示位置的确定方法规定为80H+地址码x/*****************************************************函数功能:将数据(字符的标准ASCII码)写入液晶模块入口参数:y(为字符常量)***************************************************/void Lcd_WriteData(unsigned char y){while(Lcd_BusyTest()==1);RS=1; //RS为高电平,RW为低电平时,可以写入数据RW=0;E=0; //E置低电平(写指令时就是让E从0到1发生正跳变所以应先置ぜ?Lcd_Data=y; //将数据送入P0口,即将数据写入液晶模块_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间E=1; //E置高电平_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令}/*****************************************************函数功能:对LCD的显示模式进行初始化设置***************************************************/void Lcd_Int(void){Lcd_delay(15); //延时15ms,首次写指令时应给LCD一段较长的反应时间Lcd_WriteCom(0x38); //显示模式设置:16×2显示,5×7点阵,8位数据接口Lcd_delay(5); //延时5msLcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);设置模式次写9// Lcd_WriteCom(0x38);Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x0C); //显示模式设置:显示开,有光标,光标闪烁Lcd_delay(5);Lcd_WriteCom(0x06); //显示模式设置:光标右移,字符不移Lcd_delay(5);Lcd_WriteCom(0x01); //清屏幕指令,将以前的显示内容清零Lcd_delay(5); }void hanying_show(void){unsigned char Lcd_i;Lcd_WriteCom(0x01);//清显示:清屏幕指令Lcd_delay(2);Lcd_WriteAddress(0x00); // 设置显示位置为最左侧Lcd_delay(2);Lcd_i=0;while(string1[Lcd_i]!='\0') //'\0'是数组结束标志需先将字符存入{Lcd_WriteData(string1[Lcd_i]); // 显示字符Lcd_i++;Lcd_delay(4);}}void main(){Lcd_Int(); //1602初始化while(1){hanying_show();}}。
51单片机好学1602全过程C语言编程显示很全的哦阿拉教你轻松学51系列〔就抽精品〕发布: 2021-2-05 16:03 | 作者: tiankai | 来源: 电子园51单片机学习网阿拉1602液晶的正面(绿色背光,黑色字体)1602液晶反面(绿色背光,黑色字体)另一种1602液晶模块,显示屏是蓝色背光白色字体字符型LCD1602通常有14条引脚线或16条引脚线的LCD,多出来的2条线是背光电源线VCC(15脚)和地线GND(16脚),其控制原理与14脚的LCD完全一样,引脚定义如下表所示:HD44780内置了DDRAM、CGROM 和CGRAM。
DDRAM就是显示数据RAM,用来存放待显示的字符代码。
共80个字节,其地址和屏幕的对应关系如下表:也就是说想要在LCD1602屏幕的第一行第一列显示一个"A"字,就要向DDRAM的00H地址写入“A〞字的代码就行了。
但具体的写入是要按LCD模块的指令格式来进行的,后面我会说到的。
那么一行可有40个地址呀?是的,在1602中我们就用前16个就行了。
第二行也一样用前16个地址。
对应如下:DDRAM地址与显示位置的对应关系〔事实上我们往DDRAM里的00H地址处送一个数据,譬如0x31(数字1的代码)并不能显示1出来。
这是一个令初学者很容易出错的地方,原因就是如果你要想在DDRAM 的00H地址处显示数据,那么必须将00H加上80H,即80H,假设要在DDRAM的01H 处显示数据,那么必须将01H加上80H即81H。
依次类推。
大家看一下控制指令的的8条:DDRAM地址的设定,即可以明白是怎么样的一回事了〕1602液晶模块内部的字符发生存储器〔CGROM)已经存储了160个不同的点阵字符图形,如下表所示,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,比方大写的英文字母“A〞的代码是01000001B〔41H〕,显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A〞上表中的字符代码与我们PC中的字符代码是根本一致的。
C语言源代码//======================================================依次可以从键盘输入0-f,在1602LCD上显示出来(此程序在所买开发板上验证通过)//======================================================//******** 小波电子工作室All rights reserved******//******** 个人主页:/niejinbo **//******** 文件名:lcd_key.1.c ************//******** 功能概要:4*4矩阵键盘扫描***********//******** MCU: STC89C52 晶振:11.0592Mhz **********//******** 设计者:聂金波************//******** 完成日期:2008-07-14 ************//******** 当前版本:0714.1 ************//******** 改进说明:暂无************//******** 补充说明: 从键盘输入0-F,在LCD上显示出来//*********头文件区*******************#include<reg52.h>#include<math.h>#include<absacc.h>#define uchar unsigned char#define uint unsigned int//*********定义变量区*******************sbitdula=P2^6; //关闭数码管显示之用sbitwela=P2^7;sbitlcden=P3^4; //LCD使能信号sbitlcdrs=P3^5; //LCD数据/命令选择信号uchartab_key[50];uchar code tab[]="0123456789abcdef";uchar n=0,temp,key;//*********函数声明区********************void lcd_disp(); //LCD显示函数void lcd_init(); //LCD初始化函数void write_com(uchar); //写命令函数void write_data(uchar); //写数据函数void delay(uint); //延迟函数void key_scan(); //键盘扫描函数void key_manage1(); //键盘功能分配函数void key_manage2();void key_manage3();void key_manage4();void key_manage5();void key_manage6();void key_manage7();void key_manage8();void key_manage9();void key_manage10();void key_manage11();void key_manage12();void key_manage13();void key_manage14();void key_manage15();void key_manage16();//**********主函数开始**********void main(){lcd_init();write_com(1);while(1){key_scan();lcd_disp();}}//**********LCD显示函数开始***********voidlcd_disp(){uchara,i=0;write_com(0x80);for(i=0;i<n;i++){a=tab_key[i];write_data(tab[a]);}}//**********LCD初始化函数开始*********voidlcd_init(){dula=0;wela=0; // 关闭数码管显示lcden=0;write_com(0x38); //设置显示模式:16X2,5X7,8位数据接口write_com(0x0c); //开显示,显示光标,光标闪烁write_com(0x06); //读写一个字符后,地址指针及光标加一,且光标加一整屏显示不移动write_com(0x80); //设置光标指针}//**********写命令函数开始************voidwrite_com(uchar com){lcdrs=0; //低电平写命令P0=com; //写入命令delay(3); //延时约3mslcden=1; //LCD使能端置高电平delay(5); //延时约5mslcden=0; //LCD使能端拉低电平}//**********写数据函数开始************voidwrite_data(uchardat){lcdrs=1; //低电平写数据P0=dat; //写入命令delay(3); //延时约3mslcden=1; //LCD使能端置高电平delay(5); //延时约5mslcden=0; //LCD使能端拉低电平}//**********键盘扫描函数开始****voidkey_scan()//**********扫描第一行********* P3=0xfe;temp=P3;temp=temp&0xf0;if(temp!=0xf0){delay(100);if(temp!=0xf0){temp=P3;switch(temp){case 0xee:key_manage1();break;case 0xde:key_manage2();break;case 0xbe:key_manage3();break;case 0x7e:key_manage4();break;}while(temp!=0xf0){temp=P3;temp=temp&0xf0;}}}//**********扫描第二行********* P3=0xfd;temp=P3;temp=temp&0xf0;if(temp!=0xf0){delay(100);if(temp!=0xf0)temp=P3;switch(temp){case 0xed:key_manage5();break;case 0xdd:key_manage6();break;case 0xbd:key_manage7();break;case 0x7d:key_manage8();break;}while(temp!=0xf0){temp=P3;temp=temp&0xf0;}}}//**********扫描第三行********* P3=0xfb;temp=P3;temp=temp&0xf0;if(temp!=0xf0){delay(100);if(temp!=0xf0){temp=P3;switch(temp){case 0xeb:key_manage9();break;case 0xdb:break;case 0xbb:key_manage11();break;case 0x7b:key_manage12();break;}while(temp!=0xf0){temp=P3;temp=temp&0xf0;}}}//**********扫描第四行********* P3=0xf7;temp=P3;temp=temp&0xf0;if(temp!=0xf0){delay(100);if(temp!=0xf0){temp=P3;switch(temp){case 0xe7:key_manage13();break;case 0xd7:key_manage14();break;case 0xb7:key_manage15();break;case 0x77:break;}while(temp!=0xf0){temp=P3;temp=temp&0xf0;}}}}//*********延时函数开始************** void delay(uint k){uinti,j;for(i=k;i>0;i--)for(j=50;j>0;j--);}//******键盘功能分配函数群开始******** // 键盘功能示意图// 设计者:聂金波//** 1 ** 2 ** 3 ** 4 **//** 5 ** 6 ** 7 ** 8 **//** 9 ** 0 ** s ** c **//** M1** M2** M3** M4**void key_manage1(){tab_key[n]=0;n++;}void key_manage2(){tab_key[n]=1;n++;}void key_manage3() {tab_key[n]=2;n++;}void key_manage4() {tab_key[n]=3;n++;}void key_manage5() {tab_key[n]=4;n++;}void key_manage6() {tab_key[n]=5;n++;}void key_manage7() {tab_key[n]=6;n++;}void key_manage8() {tab_key[n]=7;n++;}void key_manage9() {tab_key[n]=8;n++;}void key_manage10()tab_key[n]=9;n++;}void key_manage11(){tab_key[n]=10;n++;}void key_manage12(){tab_key[n]=11;n++;}void key_manage13(){tab_key[n]=12;n++;}void key_manage14(){tab_key[n]=13;n++;}void key_manage15(){tab_key[n]=14;n++;}void key_manage16(){tab_key[n]=15;n++;}Proteus仿真图依次从键盘输入:abcd 277817639 (本人QQ号)4X4矩阵键盘-Proteus截图。
编号:桂林电子科技大学信息科技学院单片机原理及串口技术实训论文说明书题目:打地鼠游戏机系别:机电工程系专业:机械电子工程学生姓名:朱子任学号:1453200122指导教师:莫荣职称:教授题目类型:理论研究实验研究软件开发应用研究2015 年6月20 日独创性声明本人郑重声明:所呈交的学位论文,是本人在导师的指导下,独立进行研究工作所取得的成果。
除文中已经注明引用的内容外,本论文不含任何其他个人或集体已经发表或撰写过的作品成果。
对本文的研究做出重要贡献的个人和集体,均已在文中以明确方式标明。
本人完全意识到本声明的法律结果由本人承担。
学位论文作者签名:日期:关于学位论文版权使用授权的说明本人完全了解桂林电子科技大学信息科技学院关于收集、保存、使用学位论文的以下规定:学院有权采用影印、缩印、扫描、数字化或其它手段保存论文;学院有权提供本学位论文全文或者部分内容的阅览服务;学院有权将学位论文的全部或部分内容编入有关数据库进行检索、交流;学院有权向国家有关部门或者机构送交论文的复印件和电子版。
学位论文作者签名:日期:导师签名:日期:摘要随着电子科技的飞速发展,单片机在电子及自动控制领域均得到了广泛的应用。
MCS-51单片机经历了几十年的发展之后,目前在技术、配套教材及资料上均已十分成熟。
通过对51单片机进行系统设计,同学们可以更好的掌握单片机的基本原理与设计开发过程。
本次实训的内容为打地鼠游戏机的设计与制作,来实现:利用led灯亮灭表示“地鼠”进出地鼠洞,通过光敏元件代表锤子实现信号的转化,并由单片机控制led的亮灭,数码管的显示。
实训设计制作共耗时一周,实训作品可实现“地鼠”随机出现,数码管显示,光敏原件检测是否“击中”,单片机自行判断与通关等功能,作品运行稳定,完全达到了实训要求。
通过实训,本人已对C51单片机基本了解,并有了较深刻的认识。
关键词:led随机显示;光敏原件;数码管显示;单片机;目录引言 (2)1方案设计 (2)1.1软件设计方案 (2)1.2硬件设计方案 (2)2总设计 (2)2.1软件设计 (2)2.2硬件设计 (3)3.硬件设计 (2)3.1单片机系统设计 (2)3.1.1单片机的选择 (2)3.1.2单片机引脚功能 (4)3.1.3单片机最小系统 (5)3.2数码管显示模块设计 (6)3.3“地鼠洞”模块电路 (7)3.4信号转换模块电路 (7)3.4.1L M358电压比较器 (7)3.4.2光敏电阻 (7)3.4.3光电信号转换 (7)4.软件设计 (8)4.1主程序设计 (8)4.2程序展示 (9)5.总结 (11)辞谢...........................................................................1 1 参考文献 (11)引言随着电子科技的飞速发展,单片机在电子及自动控制领域均得到了广泛的应用。
基于51单片机24小时可调时钟1602液晶显示程序#include<reg52.h>#define uchar unsigned char#define uint unsigned intsbit key1=P1^0;sbit key2=P1^1;sbit key3=P1^2;sbit key4=P1^3;sbit key5=P1^4;sbit key6=P1^5;sbit rs=P0^0; //液晶的第4端RS由开关独立s2 p3^5控制高电平写数据,低电平写命令。
sbit lecdn=P0^1; //使能端需控制LECDN,p3^6控制。
根据硬件电路而定uchar miao ,fen ,shi,num;uchar miao1,miao2,shi1,shi2,fen1,fen2;uchar table[]="0123456789";void delay(uint x){uint i,j;for(i=x;i>0;i--)for(j=10;j>0;j--);}void write_com(uchar com )//写指令{P2=com;//RW=0;写指令位定义一个io口控制lecdn=0; //起初为低电平时序图rs=0; //写指令rs为低delay(10); //简短延时lecdn=1; //给以高脉冲delay(5);lecdn=0;}void write_data(uchar shu ) //写数据{P2=shu; //将数据送给控制数据位的io口//RW=0;写指令位定义一个io口控制lecdn=0;rs=1; //写数据rs为低区别delay(10);lecdn=1;delay(5);lecdn=0;}void init() //初始化{write_com(0x38); //显示模式设置delay(20);write_com(0x0f); // 显示开关,和光标设置,开关必开,光标不开ox0c,开并闪烁0x0fdelay(20);write_com(0x06); //写完一个数据,数据地址指针自动往后移动一位delay(20);write_com(0x01); //清屏指令,按下复位键上次的结果变清掉。
作品名称:基于AT89S52以LCD1602为显示屏的打地鼠游戏作品简介:采用AT89S52单片机为主控芯片,选取LCD1602作为显示屏,通过一个拨动开关控制液晶屏的开启与关闭。
带有红外接收头,同时可用红外遥控器进行控制。
选取了基于I2C-BUS 的串行EEPROM存储器件24C02作为游戏数据存储器,可以掉电保存游戏记录。
配有无源蜂鸣器,可播放开场音乐及提示音。
本游戏硬件部分的电路原理图均是自行设计,全部为手工布线与焊接;软件部分为原创的基于1602液晶屏的打地鼠(Whac-A-Mole)游戏。
操作说明:1.插上电源后,打开作品左下角的拨动开关启动(左边为“关”,右边为“开”)。
如在光线差且电池电量充足的情况下,可打开上方液晶屏下的背光控制开关(左边为“开”,右边为“关”)。
2.系统启动后,会出现一个过场动画,随后显示游戏等待画面:液晶屏第一排前8位随机显示地鼠(Ö)或地雷(*),右边显示最高分;液晶屏第二排显示游戏的英文名称——Whac A Mole(打地鼠)。
3.按下遥控器上的“开/关”键进入游戏(此时独立键盘无效)。
4.在开场音乐伴随下显示“Ready Go!!!”之后正式进入游戏。
游戏从Level 01开始,共20关。
5.进入游戏界面后,随机产生地鼠和地雷(地雷产生的概率为10%),上下两行四列分别对应独立键盘的8个按键。
按下某个键即代表击打相应位置。
6.游戏界面的右侧上下两行分别显示分数($XXX)和生命数(L XX)。
游戏初始的生命数为3。
7.若击中地鼠:正常情况下分数加1,播放提示音1;若在较短时间(实际为地鼠产生到消失的前一半时间内)击中,则“快速反应,双倍加分”,即分数加2,播放提示音2,但与正常得分的提示音1不同。
8.若击中地雷,则生命数减1,分数不变,播放提示音3。
9.当地雷出现时,若未按下相应键,则分数加1,播放提示音1。
10.当地鼠出现时,若未按下相应键,则生命数减1,分数不变,播放提示音3。
基于单片机的打地鼠游戏设计作者:覃丽姗李宁王恬灏来源:《山东工业技术》2018年第16期摘要:打地鼠游戏是人们生活中常见的一种休闲小游戏,尤其受儿童的喜爱。
打地鼠游戏玩法简单,考验人们的反应速度,能够充分的锻炼孩子的手眼协调能力。
本文设计一种基于单片机的打地鼠游戏,采用STC89C51单片机为主控芯片,以LED发光二极管亮灭模拟地鼠的出现,用独立按键模块打地鼠。
同时该设计具有计分功能,用LCD1602液晶显示屏来计分。
关键词:打地鼠;STC89C51;LCD1602;设计DOI:10.16640/ki.37-1222/t.2018.16.110单片机是一种新型微处理器,具有有抗干扰能力,成本低的特点。
打地鼠游戏是人们生活中常见的一种休闲小游戏,尤其受2-5岁儿童的喜爱。
打地鼠游戏玩法简单,考验人们的反应速度,能够充分的锻炼孩子的手眼协调能力,开发者可以根据儿童兴趣开发出具有多功能的打地鼠游戏,比如升级、道具、过关等,增加游戏的趣味性。
1 设计思想基于单片机的打地鼠游戏主要是采用STC89C51为主控芯片的单片机,控制9个LED和9个独立按键分别制作模块,用LED发光二极管模拟地鼠,LED亮表示地鼠出现,按下相应的按键即表示打地鼠成功,LCD1602液晶显示屏就会相应的显示计数;如果没按下相应的按键,则打地鼠失败,LCD1602液晶显示屏不会计数。
计分功能为打掉一个地鼠会加1分,没打中地鼠显示屏不计分。
本设计有两种转换功能,一种是只随机点亮1个LED灯,表示出现1只地鼠;另一种功能是随机点亮9个LED灯,表示出现9只地鼠。
2 硬件设计(1)单片机最小系统。
单片机具有体积小、功耗低、控制能力强的特点,在整个系统中相当于人体的大脑,控制产生随机数或按照规定让LED灯依次亮,来模拟出两种打地鼠的模式。
同时控制整个系统的逻辑加分,最后让得分在LCD1602上显示。
整个单片机控制系统主要由复位按键和晶振电路组成。
学习51单片机与PS2鼠标程序简介:PS2鼠标,LCD1602显示坐标,有LED指示灯,等等~~~~~~其实发现学起来也很简单。
第一步:PS/2接口和协议简介1 PS/2接口和协议1.1 接口的物理特性PS/2接口用于许多现代的鼠标和键盘,由IBM最初开发和使用。物理上的PS/2接口有两种类型的连接器:5脚的DIN和6脚的mini-DIN。图1就是两种连接器的引脚定义。使用中,主机提供+5V 电源给鼠标,鼠标的地连接到主机电源地上。1.2 接口协议原理PS/2鼠标接口采用一种双向同步串行协议。即每在时钟线上发一个脉冲,就在数据线上发送一位数据。在相互传输中,主机拥有总线控制权,即它可以在任何时候抑制鼠标的发送。方法是把时钟线一直拉低,鼠标就不能产生时钟信号和发送数据。在两个方向的传输中,时钟信号都是由鼠标产生,即主机不产生通信时钟信号。如果主机要发送数据,它必须控制鼠标产生时钟信号。方法如下:主机首先下拉时钟线至少100μs抑制通信,然后再下拉数据线,最后释放时钟线。通过这一时序控制鼠标产生时钟信号。当鼠标检测到这个时序状态,会在10ms内产生时钟信号。如图3中 A 时序段。主机和鼠标之间,传输数据帧的时序如图2、图3所示。2.2 数据包结构在主机程序中,利用每个数据位的时钟脉冲触发中断,在中断例程中实现数据位的判断和接收。在实验过程中,通过合适的编程,能够正确控制并接收鼠标数据。但该方案有一点不足,由于每个CLOCK都要产生一次中断,中断频繁,需要耗用大量的主机资源。2 PS/2鼠标的工作模式和协议数据包格式2.1 PS/2鼠标的四种工作模式PS/2鼠标的四种工作模式是:Reset模式,当鼠标上电或主机发复位命令 0xFF给它时进入这种模式;Stream模式鼠标的默认模式,当鼠标上电或复位完成后,自动进入此模式,鼠标基本上以此模式工作;Remote模式,只有在主机发送了模式设置命令 0xF0后,鼠标才进入这种模式;Wrap 模式,这种模式只用于测试鼠标与主机连接是否正确。PS/2鼠标在工作过程中,会及时把它的状态数据发送给主机。发送的数据包格式如表1所示。Byte1中的Bit0、Bit1、Bit2分别表示左、右、中键的状态,状态值0表示释放,1表示按下。Byte2和Byte3分别表示X轴和Y轴方向的移动计量值,是二进制补码值。Byte4的低四位表示滚轮的移动计量值,也是二进制补码值,高四位作为扩展符号位。这种数据包由带滚轮的三键三维鼠标产生。若是不带滚轮的三键鼠标,产生的数据包没有Byte4 其余的相同。第二步:/********************** XXXX.C部分*********************/#include<reg52.h>#include"mouse.h"#include"LCD1602_4.h"#include"DELAY52.h"sbit beep=P3^7;void main(){LCD1602_Init();//初始化液晶1602Init_mouse();mouse_send_data(0xf4);//向鼠标发送0xF4命令发其开始工作//mouse_send_data(0xc8);//mouse_send_data(0x64);//mouse_send_data(0x50);EX1=0;//关掉外部中断以避开鼠标发回的应答delayms(100);EX1=1;//重开外部中断while(1){ led=1;CLEARSCREEN;//清屏LCD1602_write_string(0,0,"x:");num(0,2,move_x);//x坐标值LCD1602_write_string(0,8,"y:");num(0,10,move_y);//y坐标值// LCD1602_write_string(1,8,"z:");// num(1,10,move_z);//y坐标值if(mouse_data[0]&0x01)//如果点下左键{beep=0;LCD1602_write_string(1,0,"left");}else if(mouse_data[0]&0x02)//如果点下右键{beep=0;LCD1602_write_string(1,0,"right");}else if(mouse_data[0]&0x04)//如果点下中键{beep=0;LCD1602_write_string(1,0,"middle");}else{beep=1;LCD1602_write_string(1,0,"nothing");}delayms(50);}}/********************XXX.H文件部分**********************/#ifndef MOUSE_H#define MOUSE_H#include"DELAY52.h"//Set sample rate 200;//Set sample rate 200;//Set sample rate 80;sbit mouse_SDA=P3^4;//数据线P3_5sbit mouse_CLK=P3^3;//时钟线P3_3sbit led=P3^6;//sbit led1=P1^3;uchar bdata mouse_byte; //接收字节bdata-->可寻址的片内RAMsbit mouse_byte_bit0=mouse_byte^0;//mouse_byte第0位sbit mouse_byte_bit1=mouse_byte^1;//mouse_byte第1位sbit mouse_byte_bit2=mouse_byte^2;//mouse_byte第2位sbit mouse_byte_bit3=mouse_byte^3;//mouse_byte第3位sbit mouse_byte_bit4=mouse_byte^4;//mouse_byte第4位sbit mouse_byte_bit5=mouse_byte^5;//mouse_byte第5位sbit mouse_byte_bit6=mouse_byte^6;//mouse_byte第6位sbit mouse_byte_bit7=mouse_byte^7;//mouse_byte第7位uchar bdata mouse_fuction;//功能信息字节uchar mouse_buffer[11];//接收位数据缓冲区uchar mouse_buffer_bit=0;//mouse_buffer[mouse_buffer_bit]uchar mouse_data[3];//接收鼠标数据缓冲区,分别存放:功能信息字节,x位移量,y位移量uchar mouse_data_bit=0;//mouse_data[mouse_data_bit]uint move_x=10000;//存放横坐标uint move_y=10000;//存放纵坐标void Init_mouse(void){TCON=0x00; // //中断触发方式0EA=1; //开放中断EX1=1;//允许外部中断1ET0=0x01;//允许全局中断,允许设定时器/计数器0溢出中断开定时器中断0 PX1=1;//设置中断优先级设外部中断1为最高优先级别}/*********************************************************************** 发送数据************************************************************************/ void mouse_send_data(uchar dat){uchar i;EX1=0; /*关闭外部中断1*/ACC=dat; /*将要发送的数据放入A寄存器*/mouse_CLK=0; /*拉低时钟线*/delay10us(200); /*延时100us以上*/mouse_SDA=0; /*拉低数据线*/delay10us(40);mouse_CLK=1; /*释放时钟线*/for(i=0;i<=7;i++) /*低位在前,一次发送8个数据位*/{while(mouse_CLK==1); /*等待设备拉低时钟线*/mouse_SDA=(dat>>i)&0x01; /*发送数据位*/while(mouse_CLK==0); /*等待设备释放时钟线*/ }while(mouse_CLK==1);mouse_SDA=~P; /*发送校验位,奇校验*/while(mouse_CLK==0);while(mouse_CLK==1);mouse_SDA=1; /*发送停止位*/while(mouse_CLK==0);while(mouse_CLK==1); /*应答位*/while(mouse_CLK==0);EX1=1; /*打开外部中断1*/}/*********************************************奇校检**********************************************/uchar Checkout(void){ACC=mouse_byte;if(~P==mouse_buffer[9])return 1;elsereturn 0;}/*********************************************************数据分析及处理**********************************************************/void data_analyse(void){//将收到的11位信号中截取8位数据放进mouse_bytemouse_byte_bit0=mouse_buffer[1];mouse_byte_bit1=mouse_buffer[2];mouse_byte_bit2=mouse_buffer[3];mouse_byte_bit3=mouse_buffer[4];mouse_byte_bit4=mouse_buffer[5];mouse_byte_bit5=mouse_buffer[6];mouse_byte_bit6=mouse_buffer[7];mouse_byte_bit7=mouse_buffer[8];if(Checkout())//如果校验正确{if(mouse_data_bit<3)mouse_data[mouse_data_bit++]=mouse_byte;if(mouse_data_bit==3){mouse_data_bit=0;if(mouse_data[0]&0x10)//如果"X sign bit"为1,表示鼠标向左移{move_x-=(256-mouse_data[1]);//x坐标减}else{move_x+=mouse_data[1];//x坐标加}if(mouse_data[0]&0x20){move_y-=(256-mouse_data[2]);//y坐标减}else{move_y+=mouse_data[2];//y坐标加}}}}/**************************************************外部中断1***************************************************/void ReceiveData(void) interrupt 2{ led=0;if(mouse_buffer_bit<=10){while(mouse_CLK==0);//等待设备拉高时钟线mouse_buffer[mouse_buffer_bit++]=mouse_SDA;//接收数据}if(mouse_buffer_bit==10){data_analyse();//数据分析及处理mouse_buffer_bit=0;}}#endif/********************XXX.H文件部分**********************/#ifndef LCD1602_4_H#define LCD1602_4_H#include <intrins.h>#include"DELAY52.h"#define LCD1602_DATA P0#define CLEARSCREEN LCD1602_write_cmd(0x01)sbit LCD1602_RS=P2^5;sbit LCD1602_RW=P2^6;sbit LCD1602_EN=P2^7;//**********************************************************************void LCD1602_Init(void); //液晶void LCD1602_write_cmd(uchar command); //写命令void LCD1602_write_data(uchar temp); //写数据void LCD1602_set_xy(uchar x, uchar y); //设置坐标void LCD1602_write_char(uchar x,uchar y,uchar dat); //写一个字符到第x行y列void LCD1602_write_string(uchar x,uchar y,uchar *s);//写字符串到第x行y列void LCD1602_Read_BF(void); //读忙信号void num(uchar x,uchar y,uint n); //在第x行,第y列显示整型数字n//**********************************************************************void LCD1602_Init(void){LCD1602_write_cmd(0x28);LCD1602_write_cmd(0x28);LCD1602_write_cmd(0x28);//设置4位数据传输模式LCD1602_write_cmd(0x0C);LCD1602_write_cmd(0x80);CLEARSCREEN;}void LCD1602_Read_BF(void){LCD1602_RW=1; //RW 1LCD1602_RS=0; //RS 0LCD1602_EN=1; //EN 1 Read BFLCD1602_DATA=LCD1602_DATA&0x0F|0xf0;while(LCD1602_DA TA&0x80);LCD1602_EN=0;}void LCD_en_write(void) //EN端产生一个高电平脉冲,写LCD{LCD1602_EN=1;_nop_();LCD1602_EN=0;}//*************************************void LCD1602_write_cmd(uchar command){LCD1602_Read_BF();LCD1602_RS=0; //RS 0LCD1602_RW=0; //RW 0LCD1602_DATA&=0x0F;LCD1602_DATA=command&0xf0 | LCD1602_DATA&0x0f;LCD_en_write();command=command<<4;LCD1602_DATA&=0x0F;LCD1602_DATA=command&0xf0 | LCD1602_DATA&0x0f;LCD_en_write();}//*********************************void LCD1602_write_data(uchar dat){LCD1602_Read_BF();LCD1602_RS=1; //RS 1LCD1602_RW=0; //RW 0LCD1602_DATA &=0x0F;LCD1602_DATA=dat&0xf0 | LCD1602_DA TA&0x0f;LCD_en_write();dat=dat<<4;LCD1602_DATA &=0x0F;LCD1602_DATA=dat&0xf0 | LCD1602_DA TA&0x0f;LCD_en_write();}//**********************************************void LCD1602_set_xy(uchar x,uchar y){uchar address;y&=0x0f;if(!x)address=0x80+y;elseaddress=0xc0+y;LCD1602_write_cmd(address);}//****************************************************************void LCD1602_write_char(uchar x,uchar y,uchar dat){LCD1602_set_xy(x,y);LCD1602_write_data(dat);}//********************************************************************* void LCD1602_write_string(uchar x,uchar y,uchar *s){LCD1602_set_xy(x,y);while(*s){LCD1602_write_data(*s);s++;}}void num(uchar x,uchar y,uint n){uchar i,length,a[6]={0,0,0,0,0,0};uint nx=n;if(n==0){LCD1602_write_char(x,y,'0');return;}for(i=0;i<6;i++){if(nx>=1)length++;nx/=10;}nx=n;for(;length>0;length--){a[length-1]=nx%10+48;nx/=10;}LCD1602_write_string(x,y,a);}#endif/********************XXX.H文件部分**********************/ #ifndef DELAY52_H#define DELAY52_H#define uchar unsigned char#define uint unsigned int#include<intrins.h>//起始值delayus(1)=27us,间隔9.9usvoid delay10us(uint t){while(t--);}void delayms(uint t){uint i;uchar j;for(i=0;i<t;i++)for(j=0;j<125;j++);}#endif先按上面接口连接,然后即可编译下载,测试~~~~然后在修改成自己的代码。
基于51单片机的lcd 1602液晶显示的计算器/**************************************************************** 阿斌独家制作:计算器,1602液晶显示可计算10以下数加减乘除可连续运算,最大显示结果数值65536*****************************************************************/ 键盘设置:液晶初始显示:运算显示:主程序:#include<reg52.h>#include <intrins.h> #define uint unsigned int #define uchar unsigned char sbit lcden=P2^2;sbit lcdrw=P2^1;sbit lcdrs=P2^0;uchar num,temp,jia=0,jian=0,cheng=0,chu=0,qing=0;uint key,key1,shu;uchar fuhao,flag1,flag=0; uchar table[]={0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x0}; void delay(uint z) {uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--); }bit lcd_bz(){bit result;lcdrs=0;lcdrw=1;lcden=1;_nop_();_nop_();_nop_();_nop_();result=(bit)(P0&0x80);lcden=0;return result; }void write_com(uchar com){while(lcd_bz());lcdrs=0;lcden=0;lcdrw=0;P0=com;delay(5);lcden=1;delay(5);lcden=0; }void write_date(uchar date) {while(lcd_bz());lcdrs=1;lcden=0;lcdrw=0;P0=date;delay(5);lcden=1;delay(5);lcden=0;}void lcd_init() {lcden=0;write_com(0x38);write_com(0x0c);write_com(0x06);write_com(0x01); }void keyscan() {P3=0xfe;temp=P3;temp=temp&0xf0;while(temp!=0xf0){delay(5);temp=P3;temp=temp&0xf0;while(temp!=0xf0){temp=P3;switch(temp){case 0xee:key=1;num=0;break; case 0xde:key=2;num=0;break; case 0xbe:key=3;num=0;break; case 0x7e:num=1;break; //加号}while(temp!=0xf0){temp=P3;temp=temp&0xf0;}}}P3=0xfd;temp=P3;temp=temp&0xf0;while(temp!=0xf0){delay(5);temp=P3;temp=temp&0xf0;while(temp!=0xf0){temp=P3;switch(temp){case 0xed:key=4;num=0;break; case 0xdd:key=5;num=0;break; case 0xbd:key=6;num=0;break; case 0x7d:num=2;break; //减号}while(temp!=0xf0){temp=P3;temp=temp&0xf0;}}}P3=0xfb;temp=P3;temp=temp&0xf0;while(temp!=0xf0){delay(5);temp=P3;temp=temp&0xf0;while(temp!=0xf0){temp=P3;switch(temp){case 0xeb:key=7;num=0;break; case 0xdb:key=8;num=0;break; case 0xbb:key=9;num=0;break; case 0x7b:num=3;break; //乘号}while(temp!=0xf0){temp=P3;temp=temp&0xf0;}}}P3=0xf7;temp=P3;temp=temp&0xf0;while(temp!=0xf0){delay(5);temp=P3;temp=temp&0xf0;while(temp!=0xf0){temp=P3;switch(temp){case 0xe7:key=0;num=0;break; case 0xd7:num=6;break; //清除case 0xb7:num=5;break; //等于号case 0x77:num=4;break; //除号}while(temp!=0xf0){temp=P3;temp=temp&0xf0;}}}}void display0(uint shu) { uint ge;ge=shu;write_date(0x30+ge); } void display1(uint shu) { uint shi,ge;shi=shu/10;ge=shu%10;write_date(0x30+shi); write_date(0x30+ge); } void display2(uint shu) { uint bai,shi,ge;bai=shu/100;shi=shu%100/10;ge=shu%10;write_date(0x30+bai); write_date(0x30+shi); write_date(0x30+ge); } void display3(uint shu) {uint qian,bai,shi,ge;qian=shu/1000;bai=shu%1000/100;shi=shu%100/10;ge=shu%10;write_date(0x30+qian);write_date(0x30+bai);write_date(0x30+shi);write_date(0x30+ge); }void display4(uint shu) {uint wan,qian,bai,shi,ge;wan=shu/10000;qian=shu%10000/1000;bai=shu%1000/100;shi=shu%100/10;ge=shu%10;write_date(0x30+wan);write_date(0x30+qian);write_date(0x30+bai);write_date(0x30+shi);write_date(0x30+ge); }void display_key1(uint result) {if(flag1==1){write_com(0x01);flag1=0;}shu=result;write_com(0x80);if(result<10)display0(result);if(result>=10&&result<100) display1(result);if(result>=100&&result<1000) display2(result);if(result>=1000&&result<10000) display3(result);if(result>=10000)display4(result);}void dis_key(result){if(result<10)display0(result);if(result>=10&&result<100) display1(result);if(result>=100&&result<1000)display2(result);if(result>=1000&&result<10000) display3(result);if(result>=10000)display4(result);}void display_key(uint result) { if(shu<10){write_com(0x80+2);dis_key(result);}if(shu>=10&&shu<100){write_com(0x80+3);dis_key(result);}if(shu>=100&&shu<1000){write_com(0x80+4);dis_key(result);}if(shu>=1000&&shu<10000){write_com(0x80+5);dis_key(result);}if(shu>=10000){write_com(0x80+6);dis_key(result);}}void display_fuhao(){switch(fuhao){case 1: write_date(0x2b);break; case 2: write_date(0x2d);break; case 3: write_date(0x2a);break; case 4: write_date(0x2f);break; }fuhao=0;}void fuhao_pan(){if(flag1==1){flag1=0;write_com(0x01);write_com(0x80+1); display_fuhao();}if(shu<10)write_com(0x80+1);if(shu>=10&&shu<100) write_com(0x80+2);if(shu>=100&&shu<1000) write_com(0x80+3);if(shu>=1000&&shu<10000) write_com(0x80+4);if(shu>=10000)write_com(0x80+5); display_fuhao();flag=1;}void fuhao_deng(){write_com(0x80+0x40); write_date(0x3d);flag1=1;flag=0;}void display_result(uint result) {write_com(0x80+0x40+1);if(result<10)display0(result);if(result>=10&&result<100) display1(result);if(result>=100&&result<1000) display2(result);if(result>=1000&&result<10000) display3(result);if(result>=10000)display4(result); }void jia1(){jia=1;jian=cheng=chu=qing=0;key1=key;fuhao=1;fuhao_pan();}void jian1(){jian=1;jia=cheng=chu=qing=0; key1=key;fuhao=2;fuhao_pan(); }void cheng1() {cheng=1;jia=jian=chu=qing=0; key1=key;fuhao=3;fuhao_pan(); }void chu1() {chu=1;jia=jian=cheng=qing=0; key1=key;fuhao=4;fuhao_pan();}void qing1() {qing=1;jia=jian=cheng=chu=0; key1=key=0; }void deng1() {if(jia)key=key1+key;if(jian)key=key1-key;if(cheng)key=key1*key;if(chu)key=key1/key;fuhao_deng();display_result(key);jia=jian=cheng=chu=qing=0;}void deal(){switch(num){case 0:{switch(flag){case 0: display_key1(key);break; case 1: display_key(key);break; }} break;case 1: jia1();break;case 2: jian1();break; case 3: cheng1();break; case 4: chu1();break; case 5: deng1();break; case 6: qing1();break; }}void main(){lcd_init();while(1){keyscan();deal();}}。
《电子系统设计课程设计》项目设计书项目名称打地鼠小组成员1小组成员2小组成员3专业任课教师成都理工大学信科院电子系2013年6月1项目名称,并简要说明应用背景。
项目名称:打地鼠应用背景:打地鼠游戏是人们生活中常见的一种休闲小游戏。
此游戏玩法简单,考验人们的反应速度。
开发者可以根据人们兴趣开发出具有多功能的打地鼠游戏,比如升级、道具、过关等,增加游戏的趣味性。
2项目设计需求(包括功能描述和性能设计指标)功能描述:1.启动系统,液晶屏第一排随机显示一个1-9的数字,显示地鼠(Ö)或地雷(*),中间显示剩余时间,右边显示分数;液晶屏第二排显示游戏的英文名称——打地鼠。
2.开始游戏后,在背景音乐伴随下显示“Ready Go”,之后正式进入游戏游戏历时2min,随着时间的增加,数字显示速度加快,游戏中课随时按K10键暂停,再次按则恢复游戏。
3.进入游戏界面后,随机产生地鼠和地雷(地雷产生的概率为10%),但随着时间的增加,地雷出现的概率会增加,数字更新的速度也越快。
按键分别对应独立键盘的9个按键,按下某个键即代表击打相应位置。
4.若击中地鼠:正常情况下分数加1,若在较短时间(实际为地鼠产生到消失的前一半时间内)击中,则“快速反应,双倍加分”,即分数加2。
若击中地雷,则分数减1,若未按下相应键,则分数加1。
5.游戏结束,背景音乐停止,保留最高分,分数和时间在按复位后刷新。
性能设计指标:能通过复位,玩家可以持续玩游戏。
自动保存和人为清除游戏数据。
3设计方案3.1 系统设计框图及原理阐述设计框图:原理阐述:1)复位电路复位条件:89C52单片机复位需要一个长达24个时钟周期的高电平才能复位,复位的作用就是使程序的指针指向地址0,每个程序都是从地址0开始执行,所以复位的概念就是让程序从头开始执行。
复位原理:该复位电路具有上电复位的功能,此功能是由C3实现的。
当系统上电时C3有一个充电放电的过程,放电过程会产生一个高电平,放电的时间根据公式(RCt )计算。
基于51单片机的PS2键盘密码锁设计摘要:AT89S52是一种低功耗、高性能CMOS 8位微控制器,具有8K在系统可编程Flash 存储器,被广泛应用于各个领域。
LCD1602液晶显示器以其微功耗、体积小、超薄轻巧等诸多优点而备受人们喜爱。
本作品是以AT89S52作为主控芯片,LCD1602作为显示器,以PS2键盘作为输入设备的密码锁。
PS2键盘与AT89S52通过PS2接口协议进行通信,可以完成密码设置,密码重置及显示等诸多功能。
本作品还使用了24C02存储器来实现密码锁的掉电保存功能。
关键词:AT89S52;LCD1602;24C02;PS2键盘Abstract:AT89S52 is a low power,high performance CMOS 8 bit microcontroller, with 8K flash memory, is widely applied in various fields. LCD1602 liquid crystalDisplay with its low power consumption, small size, thin lightweight and many other advantages, is liked by people.This work is based on the AT89S52 as the main chip, the LCD1602 as display, PS2 keyboard as an input device of the cipher lock. PS2 keyboard and AT89S52 through PS2 interface protocolFor communication, can complete password, password reset and display and other functions. This work we also used the 24C02 memory to realize the password lock the power-down save function.Keywork: A T89C52; LCD1602; 24C02;PS/2 keyboard1 实验目的及意义在单片机系统中,经常使用的键盘都是专用键盘.此类键盘为单独设计制作的,成本高、使用硬件连接线多,且可靠性不高,这一状况在那些要求键盘按键较多的应用系统中更为突出.与此相比,在PC系统中广泛使用PS/2键盘具有价格低、通用可靠,且使用连接线少(仅使用2根信号线)的特点,并可满足多种系统的要求.因此在单片机系统中应用PS/2键盘是一种很好的选择.对于单片机初学者的我而言,AT89S52简单易学,非常适合我学习。
用LCD1602 显示的时钟2012-04-30 15:04有这样一个题目:求一个为51 单片机编写的LCD 电子时钟的设计,简单就好!希望说一下怎么设计这个时钟,都需要些什么东西,最重要的——把这个设计需要的程序写出来。
设计的任务:以单片机控制的时钟,在LCD 显示器上显示当前的时间。
设计的基本要求:1.使用文字型LCD 显示器显示当前时间。
2.显示格式为“时时:分分:秒秒”。
3.用4个功能键操作来设置当前时间。
各个功能键的功能如下:K1:进入设置现在的时间。
K2:设置小时。
K3:设置分钟。
K4:确认完成设置。
4. 程序执行后工作指示灯LED 闪烁,表示程序开始执行,LCD 显示“00:00:00”,然后开始计时。
题目链接:/question/416705477.html//==================================================提到设计时钟,很多人都想到了时钟芯片DS1302,都说它简单、准确。
其实,这是个误区。
仅仅使用一般的单片机,简单的编程,达到相同DS1302 的准确度,并不是难事。
如果不要求计算平闰年、不要求分清大小月、不要求计算星期几,只是要求一个简单的时钟(及日历),用DS1302,就是自寻烦恼。
大家可以打开题目链接,看看其中的一些答案,就可以看出使用DS1302 是多么的繁琐了,简直就是一场噩梦。
做而论道以前就使用普通的单片机和LCD1602 设计过《时钟与日历》,程序设计的非常合理,时间精度就完全取决于晶振的精度。
设计出来的时钟,几个月都差不上一秒。
针对这个题目,做而论道翻出了以前的设计,删节了一些不需要的功能,设计出了符合题目要求的时钟,用PROTEUS 仿真截图如下:程序用C 语言编写,全部代码如下://---------------------------------------------------#include<reg52.h>#define uchar unsigned char#define uint unsigned int#define KEY_IO P3#define LCD_IO P0sbit LCD_RS = P2^0;sbit LCD_RW = P2^1;sbit LCD_EN = P2^2;sbit SPK = P1^2;sbit LED = P2^4;bit new_s, modify = 0;char t0, sec = 50, min = 59, hour = 23;char code LCD_line1[] = "Designed by ZELD"; char code LCD_line2[] = "Timer: 00:00:00 "; char Timer_buf[] = "23:59:50";//---------------------------------------------------void delay(uint z){uint x, y;for(x = z; x > 0; x--) for(y = 100; y > 0; y--);//---------------------------------------------------void W_LCD_Com(uchar com) //写指令{LCD_RS = 0; LCD_IO = com; // LCD_RS和R/W都为低电平时,写入指令LCD_EN = 1; delay(5); LCD_EN = 0; //用EN输入一个高脉冲}//---------------------------------------------------void W_LCD_Dat(uchar dat) //写数据{LCD_RS = 1; LCD_IO = dat; // LCD_RS为高、R/W为低时,写入数据LCD_EN = 1; delay(5); LCD_EN = 0; //用EN输入一个高脉冲}//---------------------------------------------------void W_LCD_STR(uchar *s) //写字符串{while(*s) W_LCD_Dat(*s++);}//---------------------------------------------------void W_BUFF(void) //填写显示缓冲区{Timer_buf[7] = sec % 10 + 48; Timer_buf[6] = sec / 10 + 48;Timer_buf[4] = min % 10 + 48; Timer_buf[3] = min / 10 + 48;Timer_buf[1] = hour % 10 + 48;Timer_buf[0] = hour / 10 + 48;W_LCD_Com(0xc0 + 7); W_LCD_STR(Timer_buf);}//---------------------------------------------------uchar read_key(void){uchar x1, x2;KEY_IO = 255;x1 = KEY_IO;if (x1 != 255) {delay(100);x2 = KEY_IO;if (x1 != x2) return 255;while(x2 != 255) x2 = KEY_IO;if (x1 == 0x7f) return 0;else if (x1 == 0xbf) return 1;else if (x1 == 0xdf) return 2;else if (x1 == 0xef) return 3;else if (x1 == 0xf7) return 4;}return 255;//---------------------------------------------------void Init(){LCD_RW = 0;W_LCD_Com(0x38); delay(50);W_LCD_Com(0x0c);W_LCD_Com(0x06);W_LCD_Com(0x01);W_LCD_Com(0x80); W_LCD_STR(LCD_line1);W_LCD_Com(0xC0); W_LCD_STR(LCD_line2);TMOD = 0x01; //T0定时方式1TH0 = 0x4c;TR0 = 1; //启动T0PT0 = 1; //高优先级, 以保证定时精度ET0 = 1;EA = 1;}//---------------------------------------------------void main(){uint i, j;uchar Key;Init();while(1) {//-------------------------------if (new_s) { //如果出现了新的一秒, 修改时间new_s = 0; sec++; sec %= 60;if(!sec) { min++; min %= 60;if(!min) { hour++; hour %= 24;}}W_BUFF(); //写显示//-------------------------------if (!sec && !min) { //整点报时for (i = 0; i < 200; i++) {SPK = 0; for (j = 0; j < 100; j++);SPK = 1; for (j = 0; j < 100; j++);} }}//-------------------------------Key = read_key(); //读出按键switch(Key) { //分别处理四个按键case 0: modify = 1; break;case 1: if(modify) {min++; min %= 60; W_BUFF(); break;}case 2: if(modify) {hour++; hour %= 24; W_BUFF(); break;}case 3: modify = 0; break;} }}//---------------------------------------------------void timer0(void) interrupt 1 //T0中断函数, 50ms执行一次{TH0 = 0x4c;t0++; t0 %= 20; //20, 一秒钟if(t0 == 0) {new_s = 1; LED = ~LED;}if(modify) LED = 0;}//===================================================呵呵,全部程序,也不过120 行左右。
目录一、摘要 (3)二、流程图 (4)三、电路原理 (5)四、操作说明 (7)五、演示图片 (8)六、程序代码 (11)一、摘要本作品采用STC89C52单片机作为主控芯片,选取LCD1602液晶作为显示屏,选用24C02芯片作为外部EEPROM存储得分等数据。
游戏程序应用C语言编译,主要使用函数为显示主界面函数,选择模式函数,随机函数,键盘扫描函数和众多界面函数。
系统配有开机音乐和led短暂特效;以及关闭游戏音乐效果。
目前配有三个难度等级,可以随时添加。
游戏中可以实时显示得分、时间等数据。
能够通过led显示和LCD1602同时显示地鼠的出现。
题目要求中所有内容均已完成,且加入了很多额外显示环节。
二、流程图三、电路原理1、主控芯片2、地鼠led和3*3键盘3、蜂鸣器和buzzer4、1602环节5、24C02芯片四、操作说明1.插上电源后,打开作品左下角的自锁开关启动。
2.系统启动后,会次显示“welcome”字样,以及本队伍的名称,并伴随着短暂的旋律,led闪烁效果。
紧接着便进入游戏选择界面,分别是:1.start 2.s core 3.exit分别对应着开始游戏,进入历史分数菜单,以及结束的功能。
通过button1 和button2键可以进行功能选择的切换和选取,button1用于切换,button2用于确认。
3.选择start选项之后会有5秒钟的准备时间,之后即可进入游戏,游戏分为3个关卡,难度依次上升,具体表现为地鼠产生的时间间隔依次减少,第一次为3秒间隔,往后依次递减。
以9个灯泡作为地鼠,每次随机亮一个灯泡,游戏者需要在另一个3*3的矩阵上在灯泡亮的时间内按下相应的按钮即代表击打相应位置,从而实现打地鼠的模拟功能。
4.游戏界面的上方有左右两行,分别对应显示剩余时间(每次游戏的时间为30秒),以及所获得的分数。
下方也有左右两行,分别对应当前所示洞的序数,5.若击中地鼠:正常情况下分数加1,播放提示音1;6.每关有(30/地鼠实现时间) 个地鼠(或地雷),击打完成后若分数大于等于level*10则进入下一关。
7.游戏失败时,显示“GAME OVER”。
8.顺利通过3关或游戏失败后均导致游戏结束,此时显示你的得分并检测,若比存储的纪录分数高,则刷新纪录并存储。
9.显示作者信息及其他相关信息后回到游戏开始的等待画面。
补充说明:1.本版本中进入游戏后只能用按键控制,在下一版本中会添加红外遥控控制。
2.液晶显示屏背光环节设置为接电即启用的状态,可以换增电池模块。
3. LCD1602显示图片上略有难度,下一环节将使用12864或者触屏板进行设计。
4. 蜂鸣器声音过于单调,下一环节将启用PM50100语音芯片进行播报。
五、演示图片仿真图片实际图片六、程序代码#include<reg52.h>#include<stdlib.h>sbit RS=P2^0;sbit EN=P2^1;sbit Speak=P2^2;sbit button1=P2^3; //选择模式键sbit button2=P2^4; //确认键、返回键、暂停键、下一关开始键sbit Buzzer=P2^6;sbit hole1=P2^7; //1号洞sbit SDA=P1^1; //24c02数据线sbit SCL=P1^0; //24c02时钟线unsigned char Count; //Play_Song使用unsigned char i,j;unsigned char temp; //随机数种子unsigned char result; //随机数临时变量unsigned char score; //保存临时分数unsigned char tempname[2];//保存临时分数的名字unsigned char time; //保存时间(30秒倒计时)unsigned char num; //1秒钟判断变量unsigned char flag1; //1标识得分,led全灭,不进行scankey操作unsigned char flag2; //1标识得分Buzzer响方式1unsigned char flag3; //1标识地鼠出洞时间到,开始下一轮地鼠出洞unsigned char flag4; //1标识关卡时间到unsigned char flag5; //1标志暂停unsigned char level; //关卡等级unsigned char holenum; //保存随机生成的洞号unsigned char topscore[3]={0}; //保存3个最高分unsigned char name[3][2]={"AA","BB","CC"}; //保存3个最高分名字unsigned char code hole[]={0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//P3口控制的洞unsigned char code str1[]={"Welcome!"}; //欢迎标语unsigned char code str2[]={"1.start 2.score"};unsigned char code str3[]={"3.exit"};unsigned char code str4[]={"See You! "}; //exit界面unsigned char code str5[]={"Ready?"};unsigned char code str6[]={"GO!"};unsigned char code str7[]={"Your Soccer: "}; //查看分数unsigned char code str8[]={"Time: Score: "};unsigned char code str9[]={" Team: SONGE "}; //队名unsigned char code str10[]={"Game Over!"};unsigned char code str11[]={"You Win! GO?"};unsigned char code str12[]={"You Lose!"};unsigned char code str13[]={"top1:"};unsigned char code str14[]={"Congratulations"};unsigned char code str15[]={"hole: level:"};unsigned char code str16[]={"top2:"};unsigned char code str17[]={"top3:"};unsigned char code str18[]={"Your Name:"}; //记录姓名//*************************1602函数声明*******************************//void displayWelcome(); //显示欢迎界面void displayPrepare(); //显示选项void Game(); //游戏真正进行void displayGame(); //开始游戏void displayExit(); //显示退出界面void displaytime();void displayChoose(); //显示选择界面void displayover();void scankey();void pause();void displayScoreNext();//***************************基础函数*****************************//void delayms(unsigned int xms) //延时xms 毫秒{unsigned int i,j;for(i=xms; i>0; i--)for(j=110; j>0; j--);}void delayus(unsigned int ums) //延时ums 个3微秒{unsigned int i,j;for(i=0; i<ums; i++)for(j=0; j<3; j++);}void Time_init() //定时器初始化,11.0592MZ晶振初始选择:定时器0用于播放音乐,定时器1关闭{ //进入游戏:定时器1用于LCD显示分数TMOD = 0x11; //16位定时器退出游戏:定时器0播放音乐,定时器1关闭TH0 = 0xDC;TL0 = 0x00;TH1=(65536-45872)/256;TL1=(65536-45872)%256;EA=1; //开总中断ET0=1; //开定时器0中断ET1=1; //开定时器1中断}void Time0() interrupt 1 //定时器0中断播放音乐{TH0 = 0xDC;TL0 = 0x00;Count++; //长度加1}void Time1() interrupt 3 //定时器1中断游戏中显示分数{TH1=(65536-45872)/256;TL1=(65536-45872)%256; //每50ms中断一次num++;if(num%20==0) //近似1秒钟{time--;}if(num==(60-20*level)) //出洞结束,level1:3s; level2:2s; level3:1s{num=0;flag3=1;}if(time==0) //一关结束{time=30;flag4=1;}}//***********************播放音乐*********************************//unsigned char code SONG[] ={ //祝你平安0x26,0x20,0x20,0x20,0x20,0x20,0x26,0x10,0x20,0x10,0x20,0x80,0x26,0x20,0x30,0x20, 0x30,0x20,0x39,0x10,0x30,0x10,0x30,0x80,0x26,0x20,0x00, //27个数字//0x20,0x20,0x20,0x20,0x1c,0x20,0x20,0x80,0x2b,0x20,0x26,0x20,0x20,0x20,//0x2b,0x10,0x26,0x10,0x2b,0x80,0x26,0x20,//0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x60,0x40,0x10,0x39,0x10,0x26,0x20, //0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x80,0x26,0x20,0x2b,0x10,0x2b,0x10, //0x2b,0x20,0x30,0x10,0x39,0x10,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x20, //0x20,0x10,0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x18,0x20,0x18,0x20,0x26,0x20, //0x20,0x20,0x20,0x40,0x26,0x20,0x2b,0x20,0x30,0x20,0x30,0x20,0x1c,0x20,0x20,0x20, //0x20,0x80,0x1c,0x20,0x1c,0x20,0x1c,0x20,0x30,0x20,0x30,0x60,0x39,0x10,0x30,0x10, //0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x10,0x26,0x10,0x26,0x10,0x2b,0x10,0x2b,0x80, //0x18,0x20,0x18,0x20,0x26,0x20,0x20,0x20,0x20,0x60,0x26,0x10,0x2b,0x20,0x30,0x20, //0x30,0x20,0x1c,0x20,0x20,0x20,0x20,0x80,0x26,0x20,0x30,0x10,0x30,0x10,0x30,0x20,//0x39,0x20,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x10,0x40,0x10,0x20,0x10, //0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,//第217个数字//路边的野花不要采//0x30,0x1C,0x10,0x20,0x40,0x1C,0x10,0x18,0x10,0x20,0x10,0x1C,0x10,0x18,0x40,0x1C, // 0x20,0x20,0x20,0x1C,0x20,0x18,0x20,0x20,0x80,0xFF,0x20,0x30,0x1C,0x10,0x18,0x20,0x15,0x20,0x1C,0x20,0x20,0x20,0x26,0x40,0x20,0x20,0x2B,0x20,0x26,0x20,0x20,0x20, 0x30,0x80,0xFF,0x20,0x20,0x00,//0x1C,0x10,0x18,0x10,0x20,0x20,0x26,0x20,0x2B,0x20,0x30, //0x20,0x2B,0x40,0x20,0x20,0x1C,0x10,0x18,0x10,0x20,0x20,0x26,0x20,0x2B,0x20,0x30, //0x20,0x2B,0x40,0x20,0x30,0x1C,0x10,0x18,0x20,0x15,0x20,0x1C,0x20,0x20,0x20,0x26, //0x40,0x20,0x20,0x2B,0x20,0x26,0x20,0x20,0x20,0x30,0x80,0x20,0x30,0x1C,0x10,0x20, //0x10,0x1C,0x10,0x20,0x20,0x26,0x20,0x2B,0x20,0x30,0x20,0x2B,0x40,0x20,0x15,0x1F, //0x05,0x20,0x10,0x1C,0x10,0x20,0x20,0x26,0x20,0x2B,0x20,0x30,0x20,0x2B,0x40,0x20, //0x30,0x1C,0x10,0x18,0x20,0x15,0x20,0x1C,0x20,0x20,0x20,0x26,0x40,0x20,0x20,0x2B,//0x20,0x26,0x20,0x20,0x20,0x30,0x30,0x20,0x30,0x1C,0x10,0x18,0x40,0x1C,0x20,0x20, //0x20,0x26,0x40,0x13,0x60,0x18,0x20,0x15,0x40,0x13,0x40,0x18,0x80,};void Play_Song(unsigned char i) //i=1 播放路边的野花不要采{ //i=0 播放祝你平安unsigned char Temp1,Temp2;unsigned int Addr;Count = 0; //中断计数器清0Addr = i * 27; //音乐地址TR0=1; //开启定时器0while(1){Temp1 = SONG[Addr++];if (Temp1 == 0xFF) //休止符{TR0 = 0; //关闭定时器0delayus(100);}else if (Temp1 == 0x00) //歌曲结束符{TR0=0; //关闭定时器0return;}else //正常播放歌曲{Temp2 = SONG[Addr++];TR0 = 1;while(1){Speak = ~Speak;delayus(Temp1);if(Temp2 == Count){Count = 0;break;}}}}}void playBuzzer(){if(flag2==1) //得分响{Buzzer=0;delayms(30);Buzzer=1;}else{}}//******************************24C02环节*************************************// void init(){SDA=1;delayms(5);SCL=1;delayms(5);}void start() //开始信号{SDA=1;delayms(5);SCL=1;delayms(5);SDA=0;delayms(5);}void stop() //停止信号{SDA=0;delayms(5);SCL=1;delayms(5);SDA=1;delayms(5);}void respons() //应答{unsigned char i;SCL=1;delayms(5);while((SDA==1)&&(i<250))i++;SCL=0;delayms(5);}void write_byte(unsigned char date)//写字节{unsigned char i,temp,j;temp=date;for(i=0; i<8; i++){j=0x80&temp;temp=temp<<1;SCL=0;delayms(5);SDA=(bit)j;delayms(5);SCL=1;delayms(5);}SCL=0;delayms(5);SDA=1;delayms(5);}unsigned char read_byte()//读字节{unsigned char i,k;SCL=0;delayms(2);SDA=1;for(i=0; i<8; i++){SCL=1;delayms(5);k=(k<<1)|SDA;SCL=0;delayms(5);}return k;}void write_add(unsigned char address,unsigned char date)//往地址写数据{start();write_byte(0xa0); //控制字写1010 000 0(写操作)respons();write_byte(address);//存储单元地址respons();write_byte(date);respons();stop();}unsigned char read_add(unsigned char address) //往地址中读数据{unsigned char date;start();write_byte(0xa0); //控制字写respons();write_byte(address); //单元地址respons();start();write_byte(0xa1); //控制字读1010 000 1(读操作)respons();date=read_byte(); //数据SDA=1; //非应答delayus(5);SCL=1;delayus(5);stop();return date;}void getRecord() //读取前三名分数{topscore[0]=read_add(0);//第一名name[0][0]=read_add(1);name[0][1]=read_add(2);topscore[1]=read_add(3);//第二名name[1][0]=read_add(4);name[1][1]=read_add(5);topscore[2]=read_add(6);//第三名name[2][0]=read_add(7);name[2][1]=read_add(8);}void Record() //更新前三并记录分数{write_add(0,topscore[0]);//第一名write_add(1,name[0][0]);write_add(2,name[0][1]);write_add(3,topscore[1]);//第二名write_add(4,name[1][0]);write_add(5,name[1][1]);write_add(6,topscore[2]);//第三名write_add(7,name[2][0]);write_add(8,name[2][1]);}void Judge() //判断分数高低{if(score>topscore[0]){topscore[2]=topscore[1];//第二名赋给第三名name[2][0]=name[1][0];name[2][1]=name[1][1];topscore[1]=topscore[0];//第一名赋给第二名name[1][0]=name[0][0];name[1][1]=name[0][1];topscore[0]=score; //临时变量赋给第一名name[0][0]=tempname[0];name[0][1]=tempname[1];}else if(score>topscore[1]){topscore[2]=topscore[1];//第二名赋给第三名name[2][0]=name[1][0];name[2][1]=name[1][1];topscore[1]=score; //临时变量赋给第二名name[1][0]=tempname[0];name[1][1]=tempname[1];}else if(score>topscore[2]){topscore[2]=score; //临时变量赋给第三名name[2][0]=tempname[0];name[2][1]=tempname[1];}}//*******************************1602环节*************************************//void wr_com(unsigned char com) //写指令{delayms(5);RS=0;EN=0;P0=com;delayms(5);EN=1;delayms(5);EN=0;}void wr_dat(unsigned char dat) //写数据{delayms(5);RS=1;EN=0;P0=dat;delayms(5);EN=1;delayms(5);EN=0;}void lcd_init() //1602初始化设置//{delayms(25);wr_com(0x38); //设置16*2显示,5*7点阵,8位数据接口wr_com(0x01); //显示清0,数据指针清0wr_com(0x06); //写一个字符后地址加一wr_com(0x0c); //设置开显示,不显示光标getRecord();}void displayWelcome() //显示欢迎界面wr_com(0x80+0x03);delayms(5);for(i=0; i<9; i++){wr_dat(str1[i]);delayus(5);}wr_com(0xc0+0x01);delayms(5);for(i=0; i<13; i++){wr_dat(str9[i]);delayus(5);}for(i=0; i<10; i++) //开关显示完成闪烁{if(j==0){wr_com(0x08); //关显示delayms(100);}else{wr_com(0x0c); //开显示delayms(100);}j=~j;}Play_Song(0);delayms(100);void displayPrepare() //显示选项{wr_com(0x01); //清屏delayms(5);wr_com(0x80);delayms(5);for(i=0; i<15; i++){wr_dat(str2[i]);delayus(5);}wr_com(0x80+0x40);delayms(5);for(i=0; i<6; i++){wr_dat(str3[i]);delayus(5);}for(i=0; i<9; i++){switch(i%3){case 0:hole1=0;P3=0x00;delayms(100);case 1:hole1=0;P3=0x55;delayms(100);case 2:hole1=1;P3=0xaa;delayms(100);}}hole1=0;P3=0x00;void displaytime() //游戏过程中刷新显示时间、分数{wr_com(0x80+0x05); //显示倒计时delayus(5);wr_dat(0x30+time/10);delayus(5);wr_dat(0x30+time%10);delayus(5);wr_com(0x80+0x0e); //显示分数delayus(5);wr_dat(0x30+score/10);delayus(5);wr_dat(0x30+score%10);delayus(5);wr_com(0xc0+0x0e); //显示关卡delayus(5);wr_dat(0x30+(level+1));delayus(5);}void recordName() //记录姓名{wr_com(0x01);delayus(5);wr_com(0x80);delayus(5);for(i=0; i<10; i++) //Your Name:{wr_dat(str18[i]);delayus(5);}i='A';wr_dat(i);delayus(5);wr_com(0x10); //光标左移delayus(5);wr_com(0x0f); //光标闪烁delayus(5);while(1) //输入第一个字母{wr_com(0x80+0x0a);delayus(5);wr_dat(i);delayus(5);if(button1==0){delayms(10);if(button1==0){while(!button1);i++;if(i>'Z')i='A';}}if(button2==0)//确认,开始输入第二个字母{tempname[0]=i;break;}}i='A'; //输入第二个字母wr_dat(i);delayus(5);while(1){wr_com(0x80+0x0b);delayus(5);wr_dat(i);delayus(5);if(button1==0){delayms(10);if(button1==0){while(!button1);i++;if(i>'Z')i='A';}}if(button2==0)//确认,输入完毕{tempname[1]=i;break;}}wr_com(0x0c); //关闭光标delayus(5);displayChoose();}void displayover() //显示一轮游戏结束画面{TR1=0; //关闭定时器1wr_com(0x01);delayms(5);wr_com(0x80);delayms(5);for(i=0; i<10; i++) //Game Over{wr_dat(str10[i]);delayus(5);}wr_com(0xc0);delayus(5);if(score>=(10*(1+level))) //不同level分数要求不同,win了{if(level==3) //通关了{level=0;wr_com(0x80);delayus(5);for(i=0; i<15; i++){wr_dat(str14[i]);delayus(5);}wr_com(0xc0);delayus(5);for(i=0; i<8; i++){wr_dat(str11[i]);delayus(5);}while(1){if(button2==0){delayms(10);if(button2==0){while(!button2);recordName();}}}}else //升级了{for(i=0; i<12; i++) //You Win!{wr_dat(str11[i]);delayus(5);}while(1){if(button2==0){delayms(10);if(button2==0){while(!button2);level++;displayGame();}}}}}else //You Lose!{for(i=0; i<9; i++){wr_dat(str12[i]);delayus(5);}}while(1) //失败了{if(button2==0){delayms(10);if(button2==0){while(!button2);if(score!=0) //0分不记录recordName();displayChoose();}}}}void scankey() //扫描按键,判断是否得分{if((hole1==0) && (P3==0x00))//打中地鼠{delayms(5);if((hole1==0) && (P3==0x00)){while(((hole1==0) && (P3==0x00)));flag1=1; //标志得分不进行scankeyflag2=1; //标识得分buzzerscore++;playBuzzer();hole1=0;P3=0x00;}}}unsigned char random() //随机数{temp++;result=rand()%9+1;return result;}void displayhole() //hole地鼠显示{holenum=random();if(holenum==0)holenum++;wr_com(0xc0+0x06);delayus(5);wr_dat(0x30+holenum);delayus(5);switch(holenum){case 0: break;case 1: //1号洞亮hole1=1;P3=hole[1];break;case 2: //2号洞亮hole1=0;P3=hole[2];break;case 3: //3号洞亮hole1=0;P3=hole[3];break;case 4: //4号洞亮hole1=0;P3=hole[4];break;case 5: //5号洞亮hole1=0;P3=hole[5];break;case 6: //6号洞亮hole1=0;P3=hole[6];break;case 7: //7号洞亮hole1=0;P3=hole[7];break;case 8: //8号洞亮hole1=0;P3=hole[8];break;case 9: //9号洞亮hole1=0;P3=hole[9];break;}}void pause() //暂停/恢复游戏{if(button2==0) //暂停键{delayms(5); //去抖动if(button2==0){while(!button2);TR1=~TR1;flag5=~flag5;return;}}}void Gameinit() //游戏开始时数据初始化{flag1=0;//scankey标识flag2=0;//蜂鸣器标志位flag3=0;//出洞结束标识flag4=0;//timeover标识time=30;if(level==0) //重新开始闯关,则清零得分score=0;wr_com(0x01); //清屏delayus(5);wr_com(0x80);delayus(5);for(i=0; i<15; i++) //固定内容显示{wr_dat(str8[i]);delayus(5);}wr_com(0xc0);delayus(5);for(i=0; i<14; i++){wr_dat(str15[i]);delayus(5);}}void Game() //游戏真正进行{Gameinit();displaytime(); //显示时间、分数、洞、关卡TR1=1; //开启定时器1while(1){displayhole(); //地鼠出洞while(!flag3)//地鼠出洞时间level:3s; level2:2s; level3:1s{if(flag5==0){if(flag1==0)scankey();displaytime();}pause(); //暂停键判断};if(flag2==0)//没有打中地鼠{playBuzzer();}if(flag4==1)//时间到,结束game{displayover();}flag1=0;//scankey标识flag2=0;//蜂鸣器标志位flag3=0;//出洞结束标识flag4=0;//timeover标识}}void displayGame() //开始游戏{wr_com(0x01); //清屏delayms(5);wr_com(0x80+0x04);delayms(5);for(i=0; i<6; i++) //显示Ready{wr_dat(str5[i]);delayus(5);}wr_com(0xc0+0x06);delayms(5);for(i=5; i>0; i--) //显示倒数5秒{wr_dat(0x30+i);for(j=0; j<10; j++)delayms(100);wr_com(0xc0+0x06);delayms(5);}wr_com(0xc0+0x06);delayms(5);for(i=0; i<3; i++) //显示GO{wr_dat(str6[i]);delayus(5);}delayms(200);Game(); //开始游戏!}void displayScore() //显示得分记录{getRecord();//从24C02中获取数据wr_com(0x01);delayms(5);wr_com(0x80);delayms(5);for(i=0; i<12; i++) //显示当前得分{wr_dat(str7[i]);delayus(5);}wr_dat(0x30+score/10);delayms(5);wr_dat(0x30+score%10);delayms(5);wr_com(0xc0);delayus(5);for(i=0; i<5; i++) //第二行显示top1{wr_dat(str13[i]);delayus(5);}wr_com(0xc0+0x06); //top1 delayus(5);wr_dat(0x30+topscore[0]/10); delayus(5);wr_dat(0x30+topscore[0]%10); delayus(5);wr_com(0xc0+0x09);delayus(5);wr_dat(name[0][0]);delayus(5);wr_dat(name[0][1]);delayus(5);while(1) //进入第二页键{if(button2==0){delayms(10); //去抖动if(button2==0){while(!button2);displayScoreNext();break;}}}}void displayScoreNext() //显示分数第二页{wr_com(0x01);delayms(5);wr_com(0x80);delayus(5);for(i=0; i<5; i++) //第一行显示top2{wr_dat(str16[i]);delayus(5);}wr_com(0x80+0x06);delayus(5);wr_dat(0x30+topscore[3]/10);delayus(5);wr_dat(0x30+topscore[3]%10);delayus(5);wr_com(0x80+0x09);delayus(5);wr_dat(name[1][0]);delayus(5);wr_dat(name[1][1]);delayus(5);wr_com(0xc0);delayus(5);for(i=0; i<5; i++) //第二行显示top3{wr_dat(str17[i]);delayus(5);}wr_com(0xc0+0x06);delayus(5);wr_dat(0x30+topscore[6]/10);delayus(5);wr_dat(0x30+topscore[6]%10);delayus(5);wr_com(0xc0+0x09);delayus(5);wr_dat(name[2][0]);delayus(5);wr_dat(name[2][1]);delayus(5);while(1) //返回键{if(button2==0){delayms(10); //去抖动if(button2==0){while(!button2);break;}}}}void displayExit() //显示退出界面{wr_com(0x01); //清屏delayms(5);wr_com(0x80+0x01);delayms(5);for(i=0; i<8; i++){wr_dat(str4[i]);delayus(5);}wr_com(0xc0+0x01);delayms(5);for(i=0; i<13; i++){wr_dat(str9[i]);delayus(5);}while(1){Play_Song(1);delayms(200);}}void displayChoose() //显示选择界面{if(score!=0)//0分不记录{Judge();//判断并重新排序Record();//记录到24C02中}displayPrepare();wr_com(0x80);delayms(5);wr_com(0x0f); //光标闪烁delayms(5);i=0;while(1){if(button1==0) //选择模式键{delayms(10); //去抖动if(button1==0){while(!button1); //松开按钮i++;if(i==3)i=0;switch(i){case 0:wr_com(0x80);delayms(5);break; //移动光标到相应位置case 1:wr_com(0x80+0x08);delayms(5);break;case 2:wr_com(0x80+0x40);delayms(5);break;}}}if(button2==0) //确认键{delayms(10); //去抖动if(button2==0){while(!button2); //松开wr_com(0x0c); //关闭光标delayus(5);switch(i){case 0:displayGame(); break;case 1:displayScore(); break;case 2:displayExit(); break;}return;}}}}void main(){lcd_init(); //lm016Time_init(); //interruptinit(); //E2PROMdisplayWelcome();while(1){displayChoose();}}。