基于单片机设计的指纹锁(读取、录入、验证指纹)

news2025/1/23 0:18:07

一、前言

指纹识别技术是一种常见的生物识别技术,利用每个人指纹的唯一性进行身份认证。相比于传统的密码锁或者钥匙锁,指纹锁具有更高的安全性和便利性,以及防止钥匙丢失或密码泄露的优势。

基于单片机设计的指纹锁项目是利用STC89C52作为主控芯片,结合AS608光学指纹识别模块和LCD1602显示屏,实现了指纹的读取、录入和验证功能。用户可以通过按键来进行指纹的录入和删除操作,并通过LCD显示屏来查看指纹识别的状态。

在该项目中,AS608光学指纹识别模块是核心部件。它使用光学传感器采集指纹图像,然后通过算法进行特征提取和比对,最终判断指纹是否匹配。AS608模块具有高精度和高速的指纹识别能力,并且支持多种功能指令,如添加指纹、删除指纹和验证指纹等。

另外,LCD1602显示屏提供了可视化的界面,能够直观地显示指纹识别的状态信息。用户可以通过观察LCD显示屏上的提示信息,了解指纹录入、删除和验证的结果。

步进电机是用于模拟开锁操作的部件,通过正反转来实现门锁的解锁和上锁。当指纹验证成功时,步进电机会进行适当的旋转,使门锁打开,允许用户进入。

该项目的背景是为了满足人们对安全性和便利性的需求,提供一种高效且可靠的门禁系统。通过指纹识别技术,可以确保只有授权的人员才能够进入特定区域,避免了传统钥匙的遗失和密码的泄露问题。同时,单片机作为主控芯片,具有低功耗、稳定性强等特点,非常适合用于嵌入式系统的设计与开发。

这个项目的实施背景可以是家庭门禁系统、办公场所门禁系统、学校宿舍门禁系统等各种需要实现安全控制的场景。

image-20230913155040589

image-20230913154759722

二、项目整体设计思路

2.1 硬件设计思路

(1)主控芯片:选择STC89C52作为主控芯片,它是一款功能强大且广泛使用的单片机。它具有丰富的GPIO口、中断和定时器等功能,能够满足指纹锁项目的需求。

(2)光学指纹识别模块:采用AS608光学指纹识别模块作为指纹识别设备,该模块具有高精度的指纹识别能力。它通过光学传感器采集指纹图像,并通过算法进行特征提取和比对,最终实现指纹的识别和验证。

(3)显示屏:选用LCD1602液晶显示屏作为人机交互的界面,该显示屏可以直观地显示指纹识别的状态信息,提供用户友好的操作界面。

(4)按键:通过按键实现指纹的录入、删除和管理等操作。按键可以设置为添加指纹、删除指纹和确认等功能,方便用户进行指纹的管理。

(5)步进电机:使用28BYJ-48步进电机来模拟开锁操作,根据指纹识别结果控制步进电机的正反转。当指纹验证成功时,步进电机会旋转,使门锁打开。

2.2 软件设计思路:

(1)初始化:在系统启动时,进行相关硬件的初始化操作,包括主控芯片、指纹识别模块、显示屏和步进电机等。

(2)指纹录入功能:当用户选择指纹录入操作时,系统会提示用户按下指纹,然后通过光学传感器采集指纹图像,并提取特征信息。将提取的指纹特征存储在芯片的存储器中,以备后续的指纹验证使用。

(3)指纹删除功能:用户可以选择删除已录入的指纹,系统会提示用户选择要删除的指纹,并进行相应的删除操作。

(4)指纹验证功能:当用户选择指纹验证操作时,系统会提示用户按下指纹,然后通过光学传感器采集指纹图像,并提取特征信息。将提取的特征信息与存储在芯片存储器中的指纹特征进行比对,判断指纹是否匹配。如果匹配成功,则触发步进电机旋转,打开门锁;否则,提示验证失败。

(5)显示功能:通过LCD1602显示屏展示指纹验证的状态信息,包括录入、删除和验证等操作的结果。例如,显示指纹录入成功、删除成功或验证成功等信息。

(6)错误处理:在系统运行过程中,需要对各种可能出现的错误进行处理,如指纹录入失败、删除失败或验证失败等情况。系统需要及时给出相应的提示信息,以便用户了解具体的错误原因。

硬件设计上,主要选用适合的单片机、指纹识别模块、显示屏和步进电机等组件,搭建起指纹锁的硬件平台;软件设计上,利用主控芯片进行指纹录入、删除和验证的功能实现,并通过显示屏展示相关信息,实现一个完整的指纹锁系统。

三、硬件连线说明

以下是指纹识别模块、显示屏、按键和步进电机的引脚连接:

模块引脚连接到单片机的IO口
指纹识别模块 AS608VCC5V
GNDGND
TXDP1.0 (串口发送)
RXDP1.1 (串口接收)
液晶显示屏 LCD1602VCC5V
GNDGND
SDAP2.0 (I2C总线数据)
SCLP2.1 (I2C总线时钟)
RSP3.0
RWP3.1
EP3.2
D4-D7P4.0-P4.3
按键添加指纹P0.0
删除指纹P0.1
确认P0.2
步进电机 28BYJ-48IN1P5.0
IN2P5.1
IN3P5.2
IN4P5.3

四、项目代码设计

#include <reg52.h>
#include <stdio.h>
#include <intrins.h>
#include "lcd1602.h"

#define uchar unsigned char
#define uint unsigned int

// 指纹识别相关定义
#define FINGERPRINT_ADD    0x01   // 添加指纹命令
#define FINGERPRINT_DEL    0x02   // 删除指纹命令
#define FINGERPRINT_VERIFY 0x03   // 验证指纹命令
#define FINGERPRINT_SUCCESS 0x00  // 指纹验证成功返回值
#define FINGERPRINT_FAIL 0x01     // 指纹验证失败返回值

// 步进电机相关定义
sbit IN1 = P2^0;
sbit IN2 = P2^1;
sbit IN3 = P2^2;
sbit IN4 = P2^3;

// 按键相关定义
sbit Key1 = P1^0;  // 录入指纹按键
sbit Key2 = P1^1;  // 删除指纹按键

uchar comdata[19] = {0};   // 串口接收数据缓冲区
uchar fingerStatus = 0;   // 指纹识别状态,0:未识别,1:已识别
uchar fingerprintIndex = 1;  // 指纹索引

void delay(uint ms) {
    while(ms--) {
        uint xms = 120;  // 延时大概1ms
        while(xms--);
    }
}

void uartInit() {
    TMOD = 0x20;   // 设置T1工作在方式2,8位定时/计数器
    SCON = 0x50;  // 设置串口工作在模式1,波特率9600
    TH1 = 0xFD;   // 波特率为9600时的T1重装值
    TL1 = 0xFD;
    TR1 = 1;      // 启动T1
}

void uartSendByte(uchar dat) {
    SBUF = dat;   // 将数据送入UART发送缓冲区
    while(!TI);   // 等待UART发送完毕
    TI = 0;       // 清除发送完成标志位
}

void uartSendString(uchar *str) {
    while(*str) {
        uartSendByte(*str);
        str++;
    }
}

void uartInterrupt() interrupt 4 using 1 {
    uchar c;
    if (RI) {  // 接收到了数据
        RI = 0;  // 清除接收中断标志位
        c = SBUF;  // 读取接收到的数据

        if (c == 0xEF && comdata[0] != 0xEF) {  // 接收到帧头
            comdata[0] = 0xEF;
            comdata[1] = c;
        } 
        else if (comdata[1] == 0x01 && comdata[2] == 0xF5) {  // 接收到返回数据长度
            comdata[2] = c;
        }
        else if (comdata[2] != 0) {  // 接收到数据
            comdata[comdata[2]] = c;
            if (comdata[2] == 18) {  // 数据接收完毕
                fingerStatus = comdata[9];
            }
        }
    }
}

void fingerPrintAdd(uchar index) {
    uchar temp[] = {0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x07, 0x09, index, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x1E, 0x00, 0x2C};
    uchar checkSum = 0;
    
    for (uint i = 2; i < 19; i++) {
        checkSum += temp[i];
        uartSendByte(temp[i]);
    }
    
    temp[19] = (~checkSum) + 1;
    uartSendByte(temp[19]);
}

void fingerPrintDelete(uchar index) {
    uchar temp[] = {0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x03, 0x0C, index, 0x00, 0x10};
    uchar checkSum = 0;
    
    for (uint i = 2; i < 13; i++) {
        checkSum += temp[i];
        uartSendByte(temp[i]);
    }
    
    temp[13] = (~checkSum) + 1;
    uartSendByte(temp[13]);
}

void fingerPrintVerify() {
    uchar temp[] = {0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x03, 0x03, 0x00, 0x07};
    uchar checkSum = 0;
    
    for (uint i = 2; i < 12; i++) {
        checkSum += temp[i];
        uartSendByte(temp[i]);
    }
    
    temp[12] = (~checkSum) + 1;
    uartSendByte(temp[12]);
}

void stepperMotorRotate(uint steps, uchar direction) {
    uint i;

    for (i = 0; i < steps; i++) {
        IN1 = 1;
        delay(1);
        IN1 = 0;
        IN2 = 1;
        delay(1);
        IN2 = 0;
        IN3 = 1;
        delay(1);
        IN3 = 0;
        IN4 = 1;
        delay(1);
        IN4 = 0;
    }

    delay(1000);

    if (direction == 1) {  // 正转
        for (i = 0; i < 512; i++) {
            IN4 = 1;
            delay(1);
            IN4 = 0;
            IN3 = 1;
            delay(1);
            IN3 = 0;
            IN2 = 1;
            delay(1);
            IN2 = 0;
            IN1 = 1;
            delay(1);
            IN1 = 0;
        }
    } else {  // 反转
        for (i = 0; i < 512; i++) {
            IN1 = 1;
            delay(1);
            IN1 = 0;
            IN2 = 1;
            delay(1);
            IN2 = 0;
            IN3 = 1;
            delay(1);
            IN3 = 0;
            IN4 = 1;
            delay(1);
            IN4 = 0;
        }
    }
}

void main() {
    lcdInit();
    uartInit();

    EA = 1;   // 开启总中断
    ES = 1;   // 开启串口中断

    while (1) {
        if (Key1 == 0) {  // 录入指纹按键按下
            fingerPrintAdd(fingerprintIndex);
            lcdClear();
            lcdSetCursor(0, 0);
            lcdPrint("Add Finger");
            delay(1000);
            if (fingerStatus == FINGERPRINT_SUCCESS) {  // 指纹录入成功
                lcdClear();
                lcdSetCursor(0, 0);
                lcdPrint("Add Success");
                delay(1000);
                fingerprintIndex++;
            } else {  // 指纹录入失败
                lcdClear();
                lcdSetCursor(0, 0);
                lcdPrint("Add Fail");
                delay(1000);
            }
            while (Key1 == 0);  // 等待按键释放
        }

        if (Key2 == 0) {  // 删除指纹按键按下
            fingerPrintDelete(fingerprintIndex - 1);
            lcdClear();
            lcdSetCursor(0, 0);
            lcdPrint("Del Finger");
            delay(1000);
            if (fingerStatus == FINGERPRINT_SUCCESS) {  // 指纹删除成功
                lcdClear();
                lcdSetCursor(0, 0);
                lcdPrint("Del Success");
                delay(1000);
                if (fingerprintIndex > 1) {
                    fingerprintIndex--;
                }
            } else {  // 指纹删除失败
                lcdClear();
                lcdSetCursor(0, 0);
                lcdPrint("Del Fail");
                delay(1000);
            }
            while (Key2 == 0);  // 等待按键释放
        }

        fingerPrintVerify();
        if (fingerStatus == FINGERPRINT_SUCCESS) {  // 指纹验证成功
            lcdClear();
            lcdSetCursor(0, 0);
            lcdPrint("Success");
            delay(500);
            stepperMotorRotate(64, 1);  // 正转开锁
        } else if (fingerStatus == FINGERPRINT_FAIL) {  // 指纹验证失败
            lcdClear();
            lcdSetCursor(0, 0);
            lcdPrint("Fail");
            delay(500);
        }
    }
}

五、总结

项目基于STC89C52单片机设计了一款指纹锁,能够实现指纹的读取、录入和验证等功能。AS608光学指纹识别模块提供了高精度的指纹识别能力,而LCD1602显示屏和按键配合完成了人机交互的功能设计。门锁则通过28BYJ-48步进电机实现正反转模拟开锁的操作。该项目完全自主设计制造,具有较高的实用性和创新性。

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

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

相关文章

基于Java Web的“萌宠小知识”网站设计与实现论文

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统萌宠小知识信息管理难度大&#xff0c;容错率低&#xff…

java: -source 7 中不支持 lambda 表达式 (请使用 -source 8 或更高版本以启用 lambda 表达式)

目录 1、检查项目中 JDK 的设置&#xff1a; 2、检查模块中 JDK 的设置&#xff1a; 3、检查Idea 中的SDK设置 4、检查 IDEA 中 JDK 的设置&#xff08;我出现的问题在这&#xff09;&#xff1a; 今天遇见了一个报错&#xff1a; 问题产生的原因是 JDK 版本太低&#xf…

1215. 小朋友排队(权值树状数组求逆序数)

题目&#xff1a; 1215. 小朋友排队 - AcWing题库 思路&#xff1a;权值树状数组 1.权值树状数组的模板与树状数组一样没有变化&#xff0c;但树状数组tr[]中存储的内容以及add和query的含义发生了变化。 2.tr[]~ 树状数组&#xff1a;存储的是区间和&#xff1b;权值树状数…

tcp 的限制 (TCP_WRAPPERS)

#江南的江 #每日鸡汤&#xff1a;青春是打开了就合不上的书&#xff0c;人生是踏上了就回不了头的路&#xff0c;爱情是扔出了就收不回的赌注。 #初心和目标&#xff1a;拿到高级网络工程师 TCP_WRAPPERs Tcp_wrappers 对于七层模型中是位于第四层的安全工具&#xff0c;他…

Redis数据一致解决方案

文章目录 前言技术积累查询缓存业务流程更新缓存业务流程 更新缓存问题解决方案写在最后 前言 当前的应用服务很多都有着高并发的业务场景&#xff0c;对于高并发的解决方案一般会用到缓存来降低数据库压力&#xff0c;并且还能够提高系统性能减少请求耗时&#xff0c;比如我们…

西南交通大学【数电实验之modelsim的使用】

由于后面的实验和考试时的仿真全部用modelsim&#xff0c;所以出一期modelsim的使用。 一、准备工作 1.找到modelsim 可以将其拖到桌面上。 2.Quartus的准备 这里以笔者考试时的代码为例&#xff0c;代码如下图所示 是产生一个周期性的110100序列。 在编写好代码后&#x…

【redis笔记】

Redis简介 安装步骤 Redis存储的是key-value结构的数据&#xff0c;其中key是字符串类型&#xff0c;value有5种常用的数据类型&#xff1a; 字符串string ​ 哈希hash 适合存储对象 列表list 按照插入顺序排序&#xff0c;可以有重复元素 集合set 无序集合&#xff0c;没…

Gartner2023数据库魔力象限发布 阿里云依旧领导者 腾讯退出 EDB/Yugabyte进入

这是一个跨越数年的系列&#xff0c;历史文章参考&#xff1a; * 数据库魔力象限2022&#xff1a;阿里领先、腾讯再次进入 * 2021 藏在魔力象限中的数据库江湖 * Gartner云计算魔力象限2018 概述 Gartner云数据库魔力象限&#xff08;后简称“象限”或“MQ”&#xff09;一…

力扣日记12.23-【二叉树篇】501. 二叉搜索树中的众数

力扣日记&#xff1a;【二叉树篇】501. 二叉搜索树中的众数 日期&#xff1a;2023.12.23 参考&#xff1a;代码随想录、力扣 501. 二叉搜索树中的众数 题目描述 难度&#xff1a;简单 给你一个含重复值的二叉搜索树&#xff08;BST&#xff09;的根节点 root &#xff0c;找出…

设计模式(4)--对象行为(2)--命令

1. 意图 将一个请求封装为一个对象&#xff0c;从而使你可用不同的请求对客户进行参数化&#xff1b;对请求排队或记录请 求日志&#xff0c;以及支持可撤销的操作。 2. 四种角色 接收者(Receiver)、抽象命令(Command)、具体命令(Concrete Command)、请求者(Invoker) 3. 优点…

TCP_滑动窗口介绍

简介 TCP协议中有两个窗口&#xff0c;滑动窗口和拥塞窗口&#xff0c;两者均是一种流控机制&#xff1b;滑动窗口是接收方的流控机制&#xff0c;拥塞窗口是发送方的流控机制。 本文介绍滑动窗口&#xff0c;接收方为TCP连接设置了接收缓存。当TCP连接接收到正确、按序的字节…

idea运行tocmat报错

1.检查环境变量是否配置正确。 网上有许多配置tomcat环境变量的方法&#xff0c;这里不再赘述。 2.判断是否有该情况&#xff1a; 在tomcat的bin目录下有三个bat文件(startup.bat,shutdown.bat,catalina.bat)&#xff0c;随意双击一个&#xff0c;会报出上述错误。但是右键使…

JavaScript高级 函数进阶篇

函数进阶 1、函数的定义和调用 函数声明方式function关键字&#xff08;命名函数&#xff09;&#xff1b;函数表达式&#xff08;匿名函数&#xff09;&#xff1b;new Function()&#xff08;此处的Function()是一个构造函数&#xff09;&#xff1b;var fn new Function(参…

华为鸿蒙(HarmonyOS):连接一切,智慧无限

华为鸿蒙是一款全场景、分布式操作系统&#xff0c;旨在构建一个真正统一的硬件生态系统。该操作系统于2019年8月首次发布&#xff0c;并被设计为可以应用于各种设备&#xff0c;包括智能手机、智能手表、智能电视、车载系统等多种智能设备。 推荐一套最新版的鸿蒙4.0开发教程 …

【即插即用篇】YOLOv8改进实战 | 引入 Involution(内卷),用于视觉识别的新一代神经网络!涨点神器!

YOLOv8专栏导航:点击此处跳转 前言 YOLOv8 是由 YOLOv5 的发布者 Ultralytics 发布的最新版本的 YOLO。它可用于对象检测、分割、分类任务以及大型数据集的学习,并且可以在包括 CPU 和 GPU 在内的各种硬件上执行。 YOLOv8是一种尖端的、最先进的 (SOTA) 模型,它建立在以前成…

antdv中的slider组件会默认将min值传递给value

如果是使用响应式变量&#xff0c;会将min的值传递到v-model对应的变量里

with torch.no_grad()在Pytorch中的应用

with torch.no_grad()在Pytorch中的应用 参考&#xff1a; https://blog.csdn.net/qq_24761287/article/details/129773333 https://blog.csdn.net/sazass/article/details/116668755 在学习Pytorch时&#xff0c;老遇到 with torch.no_grad()&#xff0c;搞不清其作用&#…

Deployment Controller详解(下)

上一篇在《Deployment Controller详解&#xff08;上&#xff09;》中介绍了Deployment Controller 的创建、更新和回滚。了解了这三个功能&#xff0c;基本上也就懂得了大厂PaaS平台中服务的灰度升级、失败回滚等操作是如何实现的了。 接下来本文会介绍Deployment Controller…

在Windows11下安装完Ubuntu20.04双系统后配置环境的过程

1.NVIDIA驱动检测及安装 1.1 查看显卡信息 # 显示系统中所有通过PCI总线连接的VGA兼容控制器信息。包括集成显卡即与CPU内置在同一块芯片上的显卡&#xff09;以及独立显卡。 lspci | grep VGA # 将显示有关系统中所有NVIDIA显卡的信息。 lspci | grep NVIDIA 解释&#xf…

【数据结构之顺序表】

数据结构学习笔记---002 数据结构之顺序表1、介绍线性表1.1、什么是线性表? 2、什么是顺序表?2.1、概念及结构2.2、顺序表的分类 3、顺序表接口的实现3.1、顺序表动态存储结构的Seqlist.h3.1.1、定义顺序表的动态存储结构3.1.2、声明顺序表各个接口的函数 3.2、顺序表动态存储…