找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 574|回复: 9
收起左侧

只用按键和灯做一个便携式保险箱

[复制链接]
ID:1080265 发表于 2023-5-27 15:46 | 显示全部楼层 |阅读模式
按键随机对应一个灯,按下按键亮起的灯的位置必须在前一个亮起的灯下面,否则密码输入错误,所有灯灭,重新输入。当所有灯按顺序正确亮起后,成功解锁!灵感源于生化危机2重制版里的便携式保险箱,有玩过的好兄弟会很好理解。

大致演示流程是这个视频:
https://www.bilibili.com/video/BV1xY4y1y7N6/

流程图

流程图

按键对应灯

按键对应灯

依次按下按键顺序正确即将完成解锁

依次按下按键顺序正确即将完成解锁
回复

使用道具 举报

ID:1080265 发表于 2023-5-27 15:48 | 显示全部楼层
本帖最后由 violet233 于 2023-5-28 11:09 编辑

主要就是我不熟悉指针,变量的关系,无法实现想要的逻辑效果,望各位大佬指点!
八个按键八个灯,按键就是正常数字键盘类排序,灯可以是从上到下排成一列,解锁顺序是从上到下一盏盏依次亮起,不一定从第一盏灯开始,但是每下一盏得在前一盏亮起位置的下面一位。按键随机对应灯,但是每次完整解锁过程都是对应同一盏灯,按该按键就对应亮这盏灯,直至解锁成功,进行下一次解锁按键和灯的顺序从新编排。
回复

使用道具 举报

ID:213173 发表于 2023-5-27 17:20 | 显示全部楼层
violet233 发表于 2023-5-27 15:48
主要就是我不熟悉指针,变量的关系,无法实现想要的逻辑效果,望各位大佬指点!

《按键随机对应一个灯,按下按键亮起的灯的位置必须在前一个亮起的灯下面》怎么理解?几个按键几个灯?按键与灯的排列布局如何?
回复

使用道具 举报

ID:1080331 发表于 2023-5-27 21:20 | 显示全部楼层
随机对应:首先,我们需要将LED灯和按键一一对应,并将它们的位置随机排列。在单片机中定义一个变量表示当前亮起的灯的位置,初始值为-1(即没有任何灯亮起),每按下一个按键,就将当前亮起的灯的位置加1。如果该位置大于等于最后一个灯的位置,说明密码正确,解锁成功。否则,所有灯都会熄灭,并重新开始输入密码。

按顺序正确亮起:为了确保按键与LED灯按顺序正确亮起,我们可以在按下按键后使用逻辑运算比较当前灯的位置和上一个亮起的灯的位置,如果当前灯的位置大于上一个亮起的灯的位置,则将当前灯的位置设置为上一个灯的位置加1。

使用计时器:为了避免机械化攻击或无限制地尝试密码,我们可以使用计时器在一定时间内限制密码输入的次数,如果超过了设置的次数,系统将锁定一段时间,防止不正常的尝试。

状态显示:我们可以使用LED灯来显示当前系统的状态,例如借助三个LED灯来表示解锁成功、解锁失败和输入密码中等状态,方便用户进行操作。

电源管理:在系统设计中需要考虑供电问题,可以使用电池等不间断电源以确保该系统的长期稳定运行。
以下是实例代码:
#include <reg51.h>

sbit key1 = P1^0; //按键引脚定义
sbit key2 = P1^1;
sbit key3 = P1^2;
sbit led1 = P2^0; //LED引脚定义
sbit led2 = P2^1;
sbit led3 = P2^2;
int current_led = -1; //当前亮起的灯位置
int last_led = -1; //上一个亮起的灯位置

void init() {
    key1 = 1; //按键初始化为高电平
    key2 = 1;
    key3 = 1;
    led1 = 0; //LED初始化为低电平熄灭状态
    led2 = 0;
    led3 = 0;
}

void delay(int t) { //延时函数
    for(int i=0; i<t; i++) {
        for(int j=0; j<120; j++);
    }
}

void main() {
    init();
    while(1) {
        if(!key1) { //按键1被按下
            if(current_led == -1 || current_led == last_led + 1) { //密码正确
                current_led++;
                last_led = current_led;
                switch(current_led) { //根据当前亮起的LED位置控制LED灯亮灭
                    case 0:
                        led1 = 1;
                        break;
                    case 1:
                        led2 = 1;
                        break;
                    case 2:
                        led3 = 1;
                        break;
                }
                if(current_led == 2) { //所有LED灯都亮起,解锁成功
                    delay(500);
                    led1 = 0;
                    led2 = 0;
                    led3 = 0;
                    current_led = -1;
                    last_led = -1;
                }
            } else { //密码错误
                delay(500);
                led1 = 0;
                led2 = 0;
                led3 = 0;
                current_led = -1;
                last_led = -1;
            }
        }
        if(!key2) { //按键2被按下
            if(current_led == -1 || current_led == last_led + 1) { //密码正确
                current_led++;
                last_led = current_led;
                switch(current_led) {
                    case 0:
                        led1 = 1;
                        break;
                    case 1:
                        led2 = 1;
                        break;
                    case 2:
                        led3 = 1;
                        break;
                }
                if(current_led == 2) {
                    delay(500);
                    led1 = 0;
                    led2 = 0;
                    led3 = 0;
                    current_led = -1;
                    last_led = -1;
                }
            } else { //密码错误
                delay(500);
                led1 = 0;
                led2 = 0;
                led3 = 0;
                current_led = -1;
                last_led = -1;
            }
        }
        if(!key3) { //按键3被按下
            if(current_led == -1 || current_led == last_led + 1) { //密码正确
                current_led++;
                last_led = current_led;
                switch(current_led) {
                    case 0:
                        led1 = 1;
                        break;
                    case 1:
                        led2 = 1;
                        break;
                    case 2:
                        led3 = 1;
                        break;
                }
                if(current_led == 2) {
                    delay(500);
                    led1 = 0;
                    led2 = 0;
                    led3 = 0;
                    current_led = -1;
                    last_led = -1;
                }
            } else { //密码错误
                delay(500);
                led1 = 0;
                led2 = 0;
                led3 = 0;
                current_led = -1;
                last_led = -1;
            }
        }
    }
}

评分

参与人数 1黑币 +40 收起 理由
admin + 40 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:73992 发表于 2023-5-27 23:59 | 显示全部楼层
画逻辑框图
回复

使用道具 举报

ID:86450 发表于 2023-5-28 00:00 | 显示全部楼层
那是 几个按键 几个灯
回复

使用道具 举报

ID:1080265 发表于 2023-5-28 10:46 | 显示全部楼层
wulin 发表于 2023-5-27 17:20
《按键随机对应一个灯,按下按键亮起的灯的位置必须在前一个亮起的灯下面》怎么理解?几个按键几个灯?按 ...

八个按键八个灯,按键就是正常数字键盘类排序,灯是从上到下排成一列,解锁顺序从上到下,不一定从第一盏灯开始,但是每下一盏得在前一盏亮起位置的下面。
回复

使用道具 举报

ID:1080265 发表于 2023-5-28 10:58 | 显示全部楼层

大致逻辑图
51hei图片_20230528105727.jpg
回复

使用道具 举报

ID:1080265 发表于 2023-5-28 11:00 | 显示全部楼层
violet233 发表于 2023-5-27 15:48
主要就是我不熟悉指针,变量的关系,无法实现想要的逻辑效果,望各位大佬指点!

附上各类说明

大致逻辑图

大致逻辑图

类似动画效果

类似动画效果

按正确顺序即将完成

按正确顺序即将完成
回复

使用道具 举报

ID:1080265 发表于 2023-5-28 12:12 | 显示全部楼层
597329015 发表于 2023-5-27 21:20
随机对应:首先,我们需要将LED灯和按键一一对应,并将它们的位置随机排列。在单片机中定义一个变量表示当 ...

首先感谢你的回答。
你的逻辑清晰,给我提供了一定的新思路。以你的效果灯必然是固定顺序亮起的,按键排列是随机的,就是已经设置好乱序键盘再来输入密码,像苹果手机解锁界面,但是键盘是乱序的,上面一排灯是用来提示密码总共位数和已输入位数,因此是必然一盏盏亮起表示依次被填满,与我所设计的不同。
此外密码输入次数是不受限制的,严格来讲这不是密码锁,只是一个训练短时记忆的小游戏。
如果可以,我想再问一个问题:灯和按键已经按顺序集成在了电路板上,不可再调序,如何按下按键亮起固定随机对应的灯?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表