基于单片机设计的电子柜锁

news2025/2/28 12:42:32

一、前言

随着现代社会的不断发展,电子柜锁的应用越来越广泛。传统的机械柜锁存在一些不便之处,例如钥匙容易丢失、密码容易泄露等问题。设计一款基于单片机的电子柜锁系统成为了一个有趣而有意义的项目。

该电子柜锁系统通过电磁锁作为柜锁的开关,通过继电器控制电磁锁的开关状态。用户可以通过矩阵键盘输入密码进行开锁,并且密码数据会通过LCD1602液晶显示屏进行显示。同时,系统还支持输入密码验证开锁和修改密码的功能。当用户成功输入正确的密码并开锁时,系统会通过蜂鸣器发出提示音。

这款电子柜锁系统的设计为了提高柜锁的安全性和便利性。相比传统的机械柜锁,电子柜锁具有以下优势:

【1】密码安全性:电子柜锁采用密码作为开锁方式,相比传统钥匙更加安全可靠,用户可以根据需要设置较复杂的密码,有效防止密码泄露和非法开锁。

【2】方便易用:用户只需要通过矩阵键盘输入密码即可开锁,无需携带钥匙或记忆复杂的机械操作步骤,操作简单方便。

【3】修改密码功能:用户可以根据需要随时修改密码,提高了柜锁的灵活性和可维护性。

【4】提示音提示:系统通过蜂鸣器发出提示音,让用户在输入密码和开锁成功时得到明确的反馈,提升了用户体验。

电子柜锁系统的设计不仅具有实用性,而且可以为学习嵌入式系统设计和单片机编程的初学者提供一个非常好的实践项目。通过这个项目,可以学习和掌握单片机的输入输出控制、按键扫描、LCD显示、蜂鸣器控制等相关知识和技术。还涉及到密码输入和验证的算法设计和实现,锻炼了逻辑思维和程序设计能力。

通过这个电子柜锁系统项目,可以体验到现代电子技术的魅力,提高柜锁的安全性和便利性,为用户提供更好的使用体验。image-20230823171105869

image-20230823170732930

image-20230823170655846

二、硬件选型介绍

硬件选型方面,根据需求,下面是电子柜锁的最终硬件选型:

【1】主控芯片:STC89C52单片机是一款常用的8位单片机,具有丰富的外设资源和较大的存储容量,适合作为电子柜锁的主控芯片。

【2】电磁锁:选择适合的电磁锁作为柜锁的开关,确保其能提供足够的安全性和可靠性。考虑使用12V电磁锁,满足电源和控制信号要求。

【3】继电器:使用继电器来控制电磁锁的通断,确保信号隔离和电流放大。

【4】矩阵键盘:选择适用的矩阵键盘用于输入密码。选择4x4矩阵键盘,具有16个按键,支持数字和功能键。

【5】LCD1602液晶显示屏:作为密码输入和状态显示的界面,LCD1602具有两行16列的字符显示,能够清晰显示输入的密码和相关提示信息。

【6】蜂鸣器:用于发出开锁成功、密码输入错误等提示音。

【7】电源模块:有稳定可靠的电源供应非常重要,选择使用AC/DC 5/12V适配器供电。

三、整体设计思路

软件设计逻辑和思路如下:

【1】初始化:在程序开始时,进行系统初始化设置,包括配置IO口、定时器和外设等。同时,需要初始化密码存储区、LCD1602显示屏和蜂鸣器等。

【2】密码输入和验证:通过矩阵键盘读取用户输入的密码。可以采用一个固定长度的密码,例如4位。用户每按下一个数字键,将其添加到密码缓冲区中,并在LCD1602上显示相应的“*”字符表示已输入。当输入的密码长度达到预设长度时,即可触发密码验证操作。

【3】密码验证:将密码缓冲区中的数字转换为字符串形式,与预先设置好的正确密码进行比较。如果密码输入正确,则进行开锁操作;否则,进行密码错误提示处理。

【4】开锁操作:当密码验证成功后,控制继电器通断,打开或关闭电磁锁。同时,通过蜂鸣器发出开锁成功的提示音,并在LCD1602上显示开锁成功信息。

【5】修改密码:提供修改密码的功能。在成功验证密码后,用户可以输入新密码进行修改。修改完成后,将新密码存储起来,供下次验证使用。

【6】状态显示:将相关的状态信息实时显示在LCD1602上,例如输入密码错误提示、修改密码成功提示等。

【7】系统保护:为了保护系统安全,可以设置安全策略,例如密码输入错误次数限制、锁定时间等。当达到错误次数上限或锁定时间到达时,系统会自动进行相应的保护处理。

【8】中断服务:使用定时器中断等方式进行按键检测和LCD1602刷新等操作,提高系统的实时性。

【9】循环检测:设计一个主循环函数,不断检测矩阵键盘的按键输入、执行开锁、密码验证、密码修改以及状态显示等功能。

四、项目代码

#include <reg51.h>
#include <intrins.h>

#define PASSWORD_LENGTH 4    // 密码长度
#define MAX_ATTEMPTS 3    // 最大尝试次数

sbit Buzzer = P1^0;    // 蜂鸣器控制引脚
sbit ElectromagneticLock = P1^1;    // 电磁锁控制引脚

unsigned char password[PASSWORD_LENGTH] = {1, 2, 3, 4};    // 初始密码
unsigned char enteredPassword[PASSWORD_LENGTH];    // 输入的密码
unsigned char attempts = 0;    // 尝试次数

// 延时函数
void delay(unsigned int ms) {
    unsigned int i, j;
    for (i = 0; i < ms; i++)
        for (j = 0; j < 110; j++)
            ;
}

// 初始化LCD1602
void LCD_Init() {
    LCD_WriteCommand(0x38);    // 设置8位数据总线,2行显示,5x8点阵字符
    LCD_WriteCommand(0x0c);    // 显示器开,光标关闭
    LCD_WriteCommand(0x06);    // 光标右移,字符不移动
    LCD_WriteCommand(0x01);    // 清屏
}

// 写入命令到LCD1602
void LCD_WriteCommand(unsigned char cmd) {
    LCD_RS = 0;
    LCD_RW = 0;
    LCD_EN = 1;
    P0 = cmd;
    _nop_();
    _nop_();
    LCD_EN = 0;
}

// 写入数据到LCD1602
void LCD_WriteData(unsigned char dat) {
    LCD_RS = 1;
    LCD_RW = 0;
    LCD_EN = 1;
    P0 = dat;
    _nop_();
    _nop_();
    LCD_EN = 0;
}

// 在LCD1602上显示字符串
void LCD_ShowString(unsigned char x, unsigned char y, unsigned char *str) {
    unsigned char i = 0;
    if (x < 16) {
        if (y == 0)
            LCD_WriteCommand(0x80 + x);
        else if (y == 1)
            LCD_WriteCommand(0xc0 + x);
        while (str[i] != '\0') {
            LCD_WriteData(str[i]);
            i++;
        }
    }
}

// 初始化矩阵键盘
void Keypad_Init() {
    Keypad_Row1 = 1;
    Keypad_Row2 = 1;
    Keypad_Row3 = 1;
    Keypad_Row4 = 1;
}

// 读取矩阵键盘按键值
unsigned char Keypad_Read() {
    unsigned char row, col;
    unsigned char keyVal;

    for (col = 0; col < 4; col++) {
        Keypad_Col1 = 1;
        Keypad_Col2 = 1;
        Keypad_Col3 = 1;
        Keypad_Col4 = 1;
        switch (col) {
            case 0:
                Keypad_Col1 = 0;
                break;
            case 1:
                Keypad_Col2 = 0;
                break;
            case 2:
                Keypad_Col3 = 0;
                break;
            case 3:
                Keypad_Col4 = 0;
                break;
        }
        for (row = 0; row < 4; row++) {
            if (Keypad_Row1 == 0) {
                delay(5);
                if (Keypad_Row1 == 0) {
                    while (Keypad_Row1 == 0)
                        ;
                    keyVal = row * 4 + col + 1;
                    return keyVal;
                }
            }
            if (Keypad_Row2 == 0) {
                delay(5);
                if (Keypad_Row2 == 0) {
                    while (Keypad_Row2 == 0)
                        ;
                    keyVal = row * 4 + col + 5;
                    return keyVal;
                }
            }
            if (Keypad_Row3 == 0) {
                delay(5);
                if (Keypad_Row3 == 0) {
                    while (Keypad_Row3 == 0)
                        ;
                    keyVal= row * 4 + col + 9;
                    return keyVal;
                }
            }
            if (Keypad_Row4 == 0) {
                delay(5);
                if (Keypad_Row4 == 0) {
                    while (Keypad_Row4 == 0)
                        ;
                    keyVal = row * 4 + col + 13;
                    return keyVal;
                }
            }
        }
    }

    return 0xFF;    // 返回0xFF表示没有按键按下
}

// 检查输入的密码是否与设定密码一致
bit CheckPassword() {
    unsigned char i;
    for (i = 0; i < PASSWORD_LENGTH; i++) {
        if (enteredPassword[i] != password[i])
            return 0;    // 密码不一致
    }
    return 1;    // 密码一致
}

// 输入密码
bit EnterPassword() {
    unsigned char i;
    unsigned char key;
    for (i = 0; i < PASSWORD_LENGTH; i++) {
        while ((key = Keypad_Read()) == 0xFF)
            ;
        enteredPassword[i] = key;
        LCD_WriteData('*');
        delay(300);
    }
    return CheckPassword();
}

// 修改密码
void ChangePassword() {
    unsigned char i;
    LCD_ShowString(0, 1, "Enter New Password");
    for (i = 0; i < PASSWORD_LENGTH; i++) {
        while ((enteredPassword[i] = Keypad_Read()) == 0xFF)
            ;
        LCD_WriteData('*');
        delay(300);
    }
    for (i = 0; i < PASSWORD_LENGTH; i++)
        password[i] = enteredPassword[i];
    LCD_ShowString(0, 1, "Password Changed ");
    delay(1000);
    LCD_ShowString(0, 1, "Enter Password: ");
}

// 开锁
void Unlock() {
    LCD_ShowString(0, 1, "Unlocking...");
    Buzzer = 1;    // 发出提示音
    ElectromagneticLock = 0;    // 解锁状态
    delay(2000);
    Buzzer = 0;    // 关闭提示音
    ElectromagneticLock = 1;    // 上锁状态
    LCD_ShowString(0, 1, "Enter Password: ");
}

// 主函数
void main() {
    LCD_Init();    // 初始化LCD1602
    Keypad_Init();    // 初始化矩阵键盘

    LCD_ShowString(0, 0, "Electronic Lock");
    LCD_ShowString(0, 1, "Enter Password: ");

    while (1) {
        if (EnterPassword()) {
            Unlock();    // 密码正确,开锁
            attempts = 0;    // 尝试次数清零
        } else {
            attempts++;    // 尝试次数加一
            if (attempts >= MAX_ATTEMPTS) {
                LCD_ShowString(0, 1, "Max Attempts Exceeded");
                Buzzer = 1;    // 发出警报音
                delay(2000);
                Buzzer = 0;    // 关闭警报音
                attempts = 0;    // 尝试次数清零
            } else {
                LCD_ShowString(0, 1, "Wrong Password     ");
                delay(1000);
                LCD_ShowString(0, 1, "Enter Password: ");
            }
        }

        while ((Keypad_Read()) != 0xFF)
            ;    // 等待按键释放

        if (Keypad_Read() == '#') {
            ChangePassword();    // 输入'#'进入修改密码模式
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1158219.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

esp32 WiFi连接失败后,可打印错误码分析连接失败的原因

esp32 WiFi连接失败后,可打印错误码分析连接失败的原因; 在事件中添加红色选框中的代码: WiFi连接失败错误码如下所示: REASON_UNSPECIFIED = 1,REASON_AUTH_EXPIRE = 2,REASON_AUTH_LEAVE = 3,REASON_ASSOC_EXPIRE …

基于uniapp与uview做一个按拼音首字母排序的通讯录页面

效果图&#xff1a; 第一步导入pinyin库并应用&#xff0c;用于区分汉字的拼音首字母 npm i pinyin import pinyin from "pinyin" 完整算法&#xff1a; function getListByPinyinFirstLetter(data) {const newList {};for (const item of data) {let firstLett…

AI全栈大模型工程师(十四)数据连接封装

文章目录 二、数据连接封装2.1 文档加载器:Document Loaders2.2 文档处理器2.3 文档向量化:Text Embeddings2.4 向量的存储(与索引):Vectorstores2.5 向量检索:Retrievers后记二、数据连接封装 2.1 文档加载器:Document Loaders !pip install pypdffrom langchain.docu…

MICCAI2023论文多模态论文速读-1

文章目录 1.Attentive Deep Canonical Correlation Analysis for Diagnosing Alzheimer’s Disease Using Multimodal Imaging Genetics2.Bidirectional Mapping with Contrastive Learning on Multimodal Neuroimaging Data3.CoLa-Diff: Conditional Latent Diffusion Model f…

ruoyi系统改造

前端启动报错&#xff1a;Error: error:0308010C:digital envelope routines::unsupported 修改ruoyi-ui/package.json&#xff0c;添加export NODE_OPTIONS–openssl-legacy-provider && "scripts": {"dev": "export NODE_OPTIONS--openssl…

C#Onnx模型信息查看工具

效果 Netron效果 项目 代码 using Microsoft.ML.OnnxRuntime; using System; using System.Collections.Generic; using System.Text; using System.Windows.Forms;namespace Onnx_Demo {public partial class frmMain : Form{public frmMain(){InitializeComponent();}string…

性能测试怎么入门?一文7个知识点带你成功入门

一、相关概念 1、性能测试相关&#xff1a;负载测试&#xff0c;性能测试&#xff0c;压力测试&#xff0c;稳定性测试&#xff0c;全链路测试等 2、性能指标&#xff1a;吞吐率&#xff0c;tps&#xff0c;并发用户数&#xff0c;吞吐量&#xff0c;响应时间等 二、性能测试…

colly库的爬虫程序

使用colly库的爬虫程序&#xff0c;该程序将使用Go语言爬取内容。 package main ​ import ("fmt""log" ​"github.com/gocolly/colly" ) ​ func main() {// 创建一个Colly爬虫实例c : colly.NewCrawler() ​// 设置服务器c.OnRequest(func(r …

我做云原生的那几年

背景介绍 在2020年6月&#xff0c;我加入了一家拥有超过500人的企业。彼时&#xff0c;前端团队人数众多&#xff0c;有二三十名成员。在这样的大团队中&#xff0c;每个人都要寻找自己的独特之处和核心竞争力。否则&#xff0c;你可能会沉没于常规的增删改查工作中&#xff0…

Redis配置多个端口记录

一、背景&#xff1a; 使用Redis做WEB系统缓存&#xff0c;如登录信息、数据字典 等 键值对信息&#xff1b;存在多个测试环境及开发连接使用默认的6379端口&#xff0c;易造成Key重复&#xff0c;缓存紊乱&#xff0c;网络堵塞&#xff1b; 额外增开6380、6381端口&#xff0c…

翻页电子版照片书如何制作?

在漫长的生命长河里&#xff0c;经常会拍很多漂亮的照片&#xff0c;这些照片可以收集起来做成相册&#xff0c;也可以制作成照片书&#xff0c;无论是当作礼物送给家人朋友&#xff0c;还是留着自己细细品味欣赏&#xff0c;都非常的有意义。 如今市面上制作翻页照片书的线上平…

ruoyi框架前端修改message消失时间

修改教程 打开modal.js文件&#xff0c;找到Message.success&#xff0c;然后把参数设置进去就行。单位是10001秒。 // 可以设置的参数如下export interface ElMessageOptions {/** Message text */message: string | VNode/** Message type */type?: MessageType/** Custom …

《C Primer Plus(第6版)》中文版PDF电子版下载(免费)

作者&#xff1a;史蒂芬普拉达&#xff08;Stephen Prata&#xff09;[美]译者&#xff1a;姜佑出版社&#xff1a;人民邮电出版社出版时间&#xff1a;2019年11月01日页码&#xff1a;541总字数&#xff1a;107.6W 这是一本经典的 C 语言书籍&#xff0c;至今已经迭代了 6 个…

java基础复习篇

目录 java 1、Java语言特点 2、JVM vs JDK vs JRE 3、基本数据类型 8种 4、重载和重写区别 5、构造方法有哪些特点&#xff1f;是否可以override 6、 接口和抽象类共同点和区别 7、 和 equals 区别 8、 String、StringBuffer、StringBuilder区别 9、字符串常量池 10、…

图傅里叶变换

目录 什么是图信号&#xff1f; 如何理解图信号的”谱“&#xff1f; 图傅里叶变换是什么&#xff1f; 图傅里叶变换中特征值和图信号的总变差有什么关系&#xff1f; 让我们先总结一下&#xff0c;我们想要把图信号 正交分解到一组基 上&#xff1b; 那么怎么得到&#x…

希亦T800 Pro双滚刷双活水洗地机发布:颠覆纯水洗,水汽混动技术的旗舰新杰作

11月1日&#xff0c;CEYEE希亦正式发布首款双滚刷双活水洗地机&#xff0c;集吸尘、洗拖、烘干于一体&#xff0c;双刷双喷淋一分钟洗地机1000次&#xff0c;可达10倍洁净效果&#xff01;该产品已正式在各大平台上开售&#xff0c;首发价2399元。 近年来&#xff0c;洗地机市…

优思学院|RCA(根本原因分析)四大步骤

在现代的制造业或者甚至是商业环境中&#xff0c;问题和突发事件不可避免地出现。 为了有效地解决这些问题并防止它们再次发生&#xff0c;根本原因分析&#xff08;RCA&#xff09;成为了至关重要的工具。 RCA是一种系统性的方法&#xff0c;涉及数据采集、因果图、根本原因…

5分+肿瘤预后模型生信分析如何做?单细胞分析+干湿结合

今天给同学们分享一篇单细胞分析干湿结合的生信文章“Tumor-associated endothelial cell prognostic risk model and tumor immune environment modulation in liver cancer based on single-cell and bulk RNA sequencing: Experimental verification”&#xff0c;这篇文章于…

139.单词拆分 多重背包理论 打家劫舍 I II III

139.单词拆分 题目 给一个非空字符串s&#xff0c;和一个非空单词集 wordDict&#xff0c;判断可不可以用空格把s分为wordDict里的一个或多个单词&#xff08;必须全部拆成单词才返回ture&#xff09;。 &#xff08;可以重复拆分为单词集的同个单词&#xff0c;默认单词集没…

天线测试解决方案-毫米波片上天线测量系统

毫米波片上天线测量系统 方案概述&#xff1a; 毫米波片上天线测量系统频率范围覆盖8GHz&#xff5e;110GHz&#xff08;可扩展至500GHz&#xff09;&#xff0c;具有频率覆盖范围宽、动态范围大、馈电形式灵活、结构紧凑、测试参数全面等特点。系统采用通用化、模块化设计思想…