要在德飞莱51单片机上实现这个密码输入和倒计时的程序,我们需要正确地连接硬件,包括LCD1602显示器、矩阵键盘、蜂鸣器和定时器。以下是完整的代码和硬件连接说明。
硬件连接说明
LCD1602显示器:
RS -> P2.0RW -> P2.1E -> P2.2D4 -> P2.4D5 -> P2.5D6 -> P2.6D7 -> P2.7
矩阵键盘:
矩阵键盘的行和列分别连接到P1口的相应引脚(P1.0-P1.3作为行,P1.4-P1.7作为列)
蜂鸣器:
蜂鸣器连接到P2.5
独立按键:
按键1-4分别连接到P3.0 - P3.3
程序代码
main.c
#include
#include "Delay.h"
#include "LCD1602.h"
#include "matrixkey.h"
#include "Timer0.h"
#include "KEY.h"
#define len_pd 7
sbit Buzzer = P2^5; //定义蜂鸣器为P2.5
unsigned char KeyNum, Sec = 40, flag, cai = 0; //定义字节,keyNum为矩阵按键、Sec为爆炸倒计时秒数、flag为判断字符、cai为拆弹密码计数
unsigned int j, i; //定义整数j、i
int Count = 0; //定义输入密码计数
unsigned char Password[len_pd] = {'7','3','5','5','6','0','8'}; //密码
unsigned char Temp_Password[len_pd]; //中间变量
void Buzzer_Time(unsigned int ms) { //蜂鸣器配置
unsigned int i;
for (i = 0; i < ms; i++) {
Buzzer = ~Buzzer;
Delay(1);
}
}
void main() {
for(i = 0; i < len_pd; i++) {
Temp_Password[i] = '*'; //密码清零
}
LCD_Init();
Timer0Init(); //定时器初始化
TR0 = 0; //关定时器
LCD_ShowString(1, 1, "BOOM");
LCD_ShowCharlist(2, 17 - len_pd, Temp_Password, len_pd); //更新显示
while(1) {
KeyNum = MatrixKey(); //矩阵键盘使用
if(KeyNum) {
if(KeyNum == 10) //S10代表0
{
KeyNum = 0;
}
if(KeyNum <= 10) { //如果按键S1~S10按键按下,输入密码
for(i = 0; i < 100; i++) { //按键提示音
Buzzer = !Buzzer;
Delay(1);
}
if(Count < len_pd) { //如果输入次数小于7
Temp_Password[Count] = KeyNum + 48; //获取一位密码
Count++; //计次加一
}
LCD_ShowCharlist(2, 17 - len_pd, Temp_Password, len_pd); //更新显示
}
if(KeyNum == 16 && Count == 7) { //如果S16按下且输入位数等于7位,确认
flag = 1; //密码判断正确标志
for(i = 0; i < len_pd; i++) {
if(Temp_Password[i] != Password[i]) { //如果不等于正确密码
LCD_ShowString(1, 14, "ERR"); //显示ERR
flag = 0;
}
}
if(flag == 1) {
LCD_ShowString(1, 14, "OK "); //显示OK
Delay(300);
for(i = 0; i < len_pd; i++) {
Temp_Password[i] = '*'; //密码清零
}
Count = 0; //计数清零
LCD_ShowCharlist(2, 17 - len_pd, Temp_Password, len_pd); //更新显示
flag = 0; //密码判段标志清零
Timer0Init(); //定时器初始化
TR0 = 1; //开定时器
while(1) {
LCD_ShowString(1, 1, "Protect Bomb ");
LCD_ShowNum(2, 1, Sec, 2); //更新显示,进入引爆倒计时
if(KEY1 == 0 || KEY2 == 0 || KEY3 == 0 || KEY4 == 0) {
cai++;
Delay(500); //若独立按键按下,拆弹密码计数加一,每0.5秒输入一个密码
LCD_ShowCharlist(2, 17 - len_pd, Temp_Password, len_pd);
LCD_ShowCharlist(2, 17 - len_pd, Password, cai); //更新显示
if(cai == len_pd) { //若拆弹计数等于密码,拆弹成功
LCD_ShowCharlist(2, 17 - len_pd, Password, len_pd); //更新显示
LCD_Init(); //用1602初始化清屏
TR0 = 0; //关定时器
P2 = 0x00;
Buzzer_Time(300);
P2 = 0xFF;
Delay(100);
P2 = 0x00;
Buzzer_Time(300);
P2 = 0xFF;
LCD_ShowString(1, 5, "You Win");
LCD_ShowString(2, 1, "Press S14 restart"); //显示胜利,按下S14重新开始
break;
}
} else {
cai = 0; //拆弹计数清零
}
if(Sec == 0) { //引爆!!!!!!
for(i = 0; i < 100; i++) {
P2 = 0x00;
Buzzer_Time(100);
P2 = 0xFF;
}
TR0 = 0;
LCD_Init(); //1602初始化清屏
LCD_ShowString(1, 5, "You Lost");
LCD_ShowString(2, 1, "Press S14 restart"); //显示失败,按下S14重新开始
break;
}
}
} else {
LCD_ShowString(1, 14, "ERR"); //显示ERR
for(i = 0; i < len_pd; i++) {
Temp_Password[i] = '*'; //密码清零
}
Count = 0; //计次清零
LCD_ShowCharlist(2, 17 - len_pd, Temp_Password, len_pd); //更新显示
}
}
if(KeyNum == 15) { //如果S15被按下,清零
for(i = 0; i < len_pd; i++) {
Temp_Password[i] = '*'; //密码清零
}
Count = 0; //计次清零
LCD_ShowString(1, 14, " "); //清除显示
LCD_ShowCharlist(2, 17 - len_pd, Temp_Password, len_pd); //更新显示
}
if(KeyNum == 14) { //重置游戏,炸弹启动时无法重置(没有回头路)
return;
}
}
}
}
//定时器中断
void Timer0_Routine() interrupt 1 {
static unsigned int count = 0;
TH0 = 0x3C;
TL0 = 0xB0;
count++;
if(count >= 1000) { //每1秒计数一次
count = 0;
if(Sec > 0) {
Sec--;
}
}
}
LCD1602.h
#ifndef __LCD1602_H__
#define __LCD1602_H__
void LCD_Init();
void LCD_ShowChar(unsigned char Line, unsigned char Column, char Char);
void LCD_ShowNum(unsigned char Line, unsigned char Column, unsigned int Num, unsigned char Length);
void LCD_ShowString(unsigned char Line, unsigned char Column, char *String);
void LCD_ShowCharlist(unsigned char Line, unsigned char Column, char *Charlist, unsigned char Length);
#endif
LCD1602.c
#include
#include "LCD1602.h"
#include "Delay.h"
// ... LCD初始化和显示函数的实现
Timer0.h
#ifndef __TIMER0_H__
#define __TIMER0_H__
void Timer0Init();
#endif
Timer0.c
#include
#include "Timer0.h"
void Timer0Init() {
TMOD &= 0xF0; //清除定时器0的设置
TMOD |= 0x01; //设置定时器0为模式1(16位定时器)
TH0 = 0x3C; //设置定时器初始值
TL0 = 0xB0; //设置定时器初始值
ET0 = 1; //使能定时器0中断
EA = 1; //使能总中断
TR0 = 1; //启动定时器0
}
void Timer0_Routine() interrupt 1 {
static unsigned int count = 0;
TH0 = 0x3C;
TL0 = 0xB0;
count++;
if (count >= 1000) { //每1秒计数一次
count = 0;
if (Sec > 0) {
Sec--;
}
}
}
Delay.h
#ifndef __DELAY_H__
#define __DELAY_H__
void Delay(unsigned int xms);
#endif
Delay.c
#include
#include "Delay.h"
void Delay(unsigned int xms) {
unsigned char i, j;
while (xms--) {
i = 2;
j = 239;
do {
while (--j);
} while (--i);
}
}
MatrixKey.h
#ifndef __MATRIXKEY_H__
#define __MATRIXKEY_H__
unsigned char MatrixKey();
#endif
MatrixKey.c
#include
#include "MatrixKey.h"
#include "Delay.h"
unsigned char MatrixKey() {
unsigned char KeyNumber = 0;
P1 = 0xF0; //列输出,行输入
if (P1 != 0xF0) {
Delay(20); //去抖动
if (P1 != 0xF0) {
switch (P1) {
case 0xE0: KeyNumber = 1; break;
case 0xD0: KeyNumber = 2; break;
case 0xB0: KeyNumber = 3; break;
case 0x70: KeyNumber = 4; break;
}
P1 = 0x0F; //行输出,列输入
switch (P1) {
case 0x0E: KeyNumber += 0; break;
case 0x0D: KeyNumber += 4; break;
case 0x0B: KeyNumber += 8; break;
case 0x07: KeyNumber += 12; break;
}
while (P1 != 0x0F); //等待释放
}
}
return KeyNumber;
}
KEY.h
#ifndef __KEY_H__
#define __KEY_H__
sbit KEY1 = P3^0;
sbit KEY2 = P3^1;
sbit KEY3 = P3^2;
sbit KEY4 = P3^3;
#endif
连接硬件
LCD1602:
RS -> P2.0RW -> P2.1E -> P2.2D4 -> P2.4D5 -> P2.5D6 -> P2.6D7 -> P2.7
矩阵键盘:
行连接到P1.0 - P1.3列连接到P1.4 - P1.7
蜂鸣器:
蜂鸣器连接到P2.5
独立按键:
按键1 -> P3.0按键2 -> P3.1按键3 -> P3.2按键4 -> P3.3
确保以上连接和代码都正确后,编译和烧录到德飞莱51单片机上,代码应能正确运行,显示密码输入和倒计时,并且实现蜂鸣器报警功能。