单片机制作“电子炸弹”(可实现安放与拆除功能) 您所在的位置:网站首页 csgo怎么显示c4倒计时 单片机制作“电子炸弹”(可实现安放与拆除功能)

单片机制作“电子炸弹”(可实现安放与拆除功能)

2023-10-18 17:36| 来源: 网络整理| 查看: 265

灵感来源: 一位室友非常喜欢打"CS GO",经常因残局对炸弹的安放或拆除成功而高兴地大喊大叫(手动滑稽),于是我萌生了一个有趣的想法,用单片机来模拟出一个没有伤害的电子炸弹。 电子炸弹的具体功能: 首先用LCD1602来模拟电子炸弹的显示屏,在刚开始时,上边显示“Dismantle Bomb!”、“remote 6!”的字样,然后安放炸弹的人在输入“0748”后炸弹开始倒计时,允许输入错误无数次,直到输入成功为止。炸弹最多坚持30s,1s减一次,剩余的时间显示在屏幕的右下角。30s到20s之间,每2s响一次;20s到10s之间,每1s响一次;最后10s,每1s响2次。并且当响声的频率变快时,屏幕上会显示“COME ON!”的字样,然后再次恢复初始的显示。输入“0487”可以拆除炸弹,拆除成功后响两声,然后出现“Good job!”的字样。如果到时间未拆除或者连续三次密码输入失败,则拆除炸弹失败,会有5s中的长响,并且屏幕上有“LOSER!”的字样出现。 源代码:

#include #include #include typedef unsigned char uchar; typedef unsigned int uint; sbit DU=P2^6; sbit WE=P2^7;//锁存器IO口位定义 sbit BEEP=P2^3;//蜂鸣器位定义 sbit RS=P3^5; sbit RW=P3^6; sbit EN=P3^4;//LCD1602对应管脚位定义 uchar code SMGwei[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//1-8位数码管 uchar code SMGduan[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};//0-9数字 uchar zifu1[]="Dismantle Bomb!"; uchar zifu2[]="remote 6!"; uchar zifu3[]="COME ON!"; uchar zifu4[]="LOSER!"; uchar zifu5[]="Good job!";//表示五个要显示的字符串 uchar key,wei,flag,flbg,ms,s=30,T,F,x;//flag、flbg、T、F为标志位,s为炸弹总倒计时30s,x来记录密码错误的次数 uchar tabel1[4],tabel2[4];//1用来储存输入的开炸弹密码,2用来储存输入的拆炸弹密码 uchar tabel3[16]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};//LCD1602第一行可见地址 uchar tabel4[16]={0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f};//LCD1602第二行可见地址 /******矩阵键盘输入模块******/ void delay(uint z) { uint x,y; for(x=z;x>0;x--) for(y=114;y>0;y--); } void keyscan1()//矩阵键盘 { uchar temp; P3=0XFF; P3=0XFE; temp=P3&0XF0; if(temp!=0xf0) { delay(20); P3=0XFE; temp=P3&0XF0; if(temp!=0xf0) { temp=P3; switch(temp) { case 0xee:key=0;wei++;break; case 0xde:key=1;wei++;break; case 0xbe:key=2;wei++;break; case 0x7e:key=3;wei++;break; } while(temp!=0xf0) { temp=P3&0XF0; } } } P3=0XFF; P3=0XFD; temp=P3&0XF0; if(temp!=0xf0) { delay(20); P3=0XFD; temp=P3&0XF0; if(temp!=0xf0) { temp=P3; switch(temp) { case 0xed:key=4;wei++;break; case 0xdd:key=5;wei++;break; case 0xbd:key=6;wei++;break; case 0x7d:key=7;wei++;break; } while(temp!=0xf0) { temp=P3&0XF0; } } } P3=0XFF; P3=0XFB; temp=P3&0XF0; if(temp!=0xf0) { delay(20); P3=0XFB; temp=P3&0XF0; if(temp!=0xf0) { temp=P3; switch(temp) { case 0xeb:key=8;wei++;break; case 0xdb:key=9;wei++;break; case 0xbb:break; case 0x7b:break; } while(temp!=0xf0) { temp=P3&0XF0; } } } P3=0XFF; P3=0XF7; temp=P3&0XF0; if(temp!=0xf0) { delay(20); P3=0XF7; temp=P3&0XF0; if(temp!=0xf0) { temp=P3; switch(temp) { case 0xe7:break; case 0xd7:break; case 0xb7:break; case 0x77:break; } while(temp!=0xf0) { temp=P3&0XF0; } } } } /******储存打开炸弹的密码******/ void c1() { if(wei==1) tabel1[0]=key; if(wei==2) tabel1[1]=key; if(wei==3) tabel1[2]=key; if(wei==4) { tabel1[3]=key; T=1; } } /******储存拆除炸弹的密码******/ void c2() { if(wei==1) tabel2[0]=key; if(wei==2) tabel2[1]=key; if(wei==3) tabel2[2]=key; if(wei==4) { tabel2[3]=key; F=1; } } /******秒表计时******/ void Timer0Init()//50ms中断一次 { TMOD|=0X01; TH0=(65536-46082)/256; TL0=(65536-46082)%256; TR0=1; ET0=1; } /******模拟炸弹“滴滴”的响声******/ void didi() { if((s20)&&(s%2!=0))//炸弹30s倒计时,在20s之前2s响一次 { BEEP=0; delay(50); BEEP=1; } if(s10)//20s到10s之间1s响一次 { BEEP=0; delay(50); BEEP=1; } if(s0)//最后10s时1s响两次 { BEEP=0; delay(25); BEEP=1; delay(100); BEEP=0; delay(25); BEEP=1; } } /********LCD1602********/ void Read_Busy() { uchar busy; P0=0XFF; RS=0; RW=1; do { EN=1; busy=P0; EN=0; }while(busy&0x80); } void Write_cmd(uchar cmd) { Read_Busy(); RS=0; RW=0; P0=cmd; EN=1; EN=0; } void Write_dat(uchar dat) { Read_Busy(); RS=1; RW=0; P0=dat; EN=1; EN=0; } void LCD1602Init() { Write_cmd(0x38); Write_cmd(0x0c); Write_cmd(0x01); } void LCDWrite1(uchar dat[])//在第一行写数据的函数 { uchar i=0; while(i uchar i=0; while(i Timer0Init(); LCD1602Init(); LCDWrite1(zifu1); LCDWrite2(zifu2);//一系列的初始化 while(1) { if(flag==0)//炸弹未打开时 { keyscan1(); c1(); if(T==1)//输入密码满四位后 { if(tabel1[0]==0&&tabel1[1]==7&&tabel1[2]==4&&tabel1[3]==8)//判断开启密码是否正确 { flag=1;//正确的标志位,表示炸弹开始倒计时 wei=0;//数组地址归零 T=0;//输入密码完成标志位归零 EA=1;//打开总中断,表示倒计时开始 } else { wei=0; T=0; } } } if(flag==1)//炸弹开始倒计时后 { Write_cmd(0x4e|0x80); Write_dat((s/10+'0')); Write_cmd(0x4f|0x80); Write_dat((s%10+'0'));//在LCD1602右下角显示剩余秒数 if(s==20||s==10)//当蜂鸣器发声频率改变时,屏幕上显示“COME ON!”字样 { Write_cmd(0x01); LCDWrite1(zifu3); delay(50); } if((s!=0)&&(s!=20&&s!=10))//显示完“COME ON!”后再次换回原来的显示 { LCDWrite1(zifu1); LCDWrite2(zifu2); } keyscan1(); c2(); if(F==1)//拆弹密码是否输入完成 { if(tabel2[0]==0&&tabel2[1]==4&&tabel2[2]==8&&tabel2[3]==7)//判断拆弹密码是否正确 { flbg=1;//正确的标志位 wei=0; F=0; EA=0;//关闭中断 Write_cmd(0x01); LCDWrite1(zifu5); BEEP=0; delay(25); BEEP=1; delay(150); BEEP=0; delay(25); BEEP=1;//蜂鸣器连响两次表示拆弹成功 delay(1000); } else { wei=0; x++; F=0; } } if((s==0&&flag==1)||x==3)//判断是否拆弹失败 { EA=0; Write_cmd(0x01); LCDWrite1(zifu4); delay(50); BEEP=0; delay(5000); BEEP=1;//蜂鸣器长鸣5s表示失败 flag=2;//标志位置2 delay(1000); } } if(flag==2||flbg==1)//结束后清屏 { Write_cmd(0x01); } } } void Timer0() interrupt 1 { TH0=(65536-46082)/256; TL0=(65536-46082)%256; ms++; if(ms==20)//计时1s后改变数码管中要显示的数据 { s--; ms=0; if(s==0) { EA=0;//关闭中断 } didi(); } }

写在后边: 运用的模块一般的单片机上都有,没有什么特别的。LCD1602的显示个人习惯问题吧,还是更喜欢这样写。还有更加精简的LCD1602显示方式可以使代码长度进一步缩短,各位感兴趣的话可以查一查(提示:指针)。 如果觉得博主写的不错的话,各位小伙伴记得点一个赞哈~



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有