站内搜索
更多
C51密码锁
专业版

C51密码锁

简介

基于C52的密码锁系统

简介:基于C52的密码锁系统

开源协议

GPL 3.0

创建时间:2025-11-09 18:56:36更新时间:2025-11-20 09:31:49

描述

项目简介

本项目是基于基于C52的密码锁系统

项目功能

密码三次错误锁定

项目参数

  • 本设计采用STC89C52
  • 本设计采用LCD1602液晶显示

原理解析

代码详细解析

这份代码是基于51单片机的密码锁系统实现,核心功能是通过键盘输入密码,与预设密码比对,正确则点亮LED并提示开锁成功;错误次数达3次则锁定系统。以下从代码结构、硬件定义、核心逻辑、关键函数四个维度逐行解析:


一、代码整体结构

├── 头文件引入          // 51寄存器、延时、键盘扫描、LCD1602驱动
├── 宏定义 & 全局变量   // 数据类型、预设密码、引脚定义
├── 函数声明            // 预留函数声明位置
├── 主函数(程序入口)  // 初始化→死循环键盘扫描→密码输入→比对→结果处理

二、逐模块详细解析

1. 头文件引入

#include "reg51.h"       // 51单片机寄存器定义(如P0~P3、中断寄存器等)
#include "intrins.h"     // 51内置函数(如_nop_(),本代码未直接使用)
#include "keyscan.h"     // 键盘扫描驱动(KeyPro()函数所在,需配套实现)
#include "lcd1602.h"     // LCD1602液晶驱动(初始化、写指令/数据等函数)
  • 核心依赖:
    • keyscan.h:需包含KeyPro()函数(返回按键值,无按键返回0xFF);
    • lcd1602.h:需包含LCD_initial()/write_command()/string()/LCD_Write_Char()等函数;
    • reg51.h:51单片机必备,定义了所有寄存器(如P3、定时器等)。

2. 宏定义 & 全局变量

#define uchar unsigned char  // 简化数据类型书写(等价于unsigned char)
#define uint unsigned int    // 简化数据类型书写(等价于unsigned int)

// 预设密码:数组元素为按键值(1/2/3/4/'A'/1/2/3/4/5),共10位
uchar code password[]={1,2,3,4,'A',1,2,3,4,5}; 

/*********************引脚定义********************/
sbit led=P3^0;  // LED指示灯引脚:P3.0(低电平点亮,高电平熄灭)

/*********************函数声明*********************/
// 预留函数声明位置(本代码未自定义函数,仅用头文件中的驱动函数)
  • 关键说明:
    • code关键字:将password数组存储到程序存储器(ROM),而非RAM,节省单片机内存;
    • 预设密码中的'A':对应键盘扫描函数的按键值(需确保键盘扫描返回的'A'键值与此处一致);
    • sbit:51单片机特有的位定义,led=P3^0表示P3端口的第0位。

3. 主函数 main()(程序核心逻辑)

void main(void)
 {
  uchar num,i=0,j;                  
  uchar passwordtemp[10];        // 存储用户输入的密码(最大10位)
  uchar inputtimes;              // 密码输入错误次数(初始值隐含为0)
  uchar passwordlength,PLEN;     // passwordlength:用户输入密码长度;PLEN:预设密码长度
  bit flag;                      // 密码比对标志(1=正确,0=错误)
 
  // PLEN=sizeof(password)/sizeof(password[0]);// 自动计算预设密码长度(被注释,手动设为9)
  PLEN=9;  // 手动指定预设密码长度为9(实际password数组有10个元素,此处疑似笔误)
  
  LCD_initial();         // 初始化LCD1602(设置显示模式、端口等)
  delayms2(10);        // 延时10ms,确保LCD初始化稳定(可省略)
  write_command(0x01);       // 发送LCD清屏指令(0x01=清屏)
  string(0x80,"  Welcome! ");    // 第一行起始地址0x80,显示"  Welcome! "
  string(0xc0,"Input password!");    // 第二行起始地址0xc0,显示"Input password!"

  while(1)  // 死循环:持续扫描键盘、处理密码输入
		{
			num=KeyPro();  // 调用键盘扫描函数,返回按键值(无按键返回0xFF)
			if(num!=0xff)  // 检测到有效按键
			{ 
				if(i==0)    // 首次输入密码时,清空第二行原有提示
          string(0xc0,"                ");// 第二行写16个空格,清空显示
				
        if(i<16)  // LCD1602第二行最多显示16个字符,限制输入长度
				{
					passwordtemp[i]=num;  // 存储当前按键值到输入密码缓冲区
					LCD_Write_Char(0xc0+i,'*');// 第二行第i位显示"*",隐藏实际密码
				}
				i++;   // 输入计数+1(记录已输入位数)
				
        // 触发密码比对条件:按下结束键(num=15) 或 输入满10位(i=10)
				if(15==num||i==10)
				{
					passwordlength=i-1;  // 计算实际输入长度(i是计数+1,需减1)
					i=0;  // 输入计数器复位,准备下次输入
					
          // 第一步:先判断输入长度是否与预设密码长度一致
					if(passwordlength==PLEN)
					{	
						flag=1;  // 先假设密码正确,置标志位为1
						// 第二步:逐位比对输入密码与预设密码
						for(j=0;j>>>");// 显示"密码正确,开锁成功"
						led=0;  // P3.0置低,点亮LED(开锁指示)
						delayms2(30000);  // 延时约30秒(实际时长取决于delayms2实现)
						led=1;  // P3.0置高,熄灭LED
						inputtimes=0;// 错误次数清零
						flag=0;      // 比对标志复位
					}
					else  // 密码长度不等 或 逐位比对不匹配
					{
						string(0xc0,"                      ");// 清空第二行
						string(0xc0,"Wrong! Retry!");// 显示"密码错误,重试"
						inputtimes++;// 错误次数+1
						if(inputtimes==3)// 连续3次错误
						{
							string(0xc0,"                      ");// 清空第二行
							string(0xc0,"Wrong 3 times!");// 显示"连续3次错误"
							while(1);// 死循环锁定系统(需重启才能恢复)
						}
					}
				}
			}	
		}
 }

三、核心逻辑拆解

1. 初始化阶段

代码段功能说明
LCD_initial()初始化LCD1602:设置8位数据接口、显示行数(2行)、字符大小(5×8)、开显示
write_command(0x01)清屏:清除LCD所有显示内容,光标归位
string(0x80," Welcome! ")第一行显示欢迎语(固定不变)
string(0xc0,"Input password!")第二行显示密码输入提示

2. 键盘扫描与密码输入

  • KeyPro():键盘扫描函数(需配套实现),返回值规则:
    • 无按键:返回0xFF
    • 数字键/功能键:返回对应值(如1/2/3/'A'/15等);
  • 输入隐藏:输入的密码用*显示,避免密码泄露;
  • 输入限制:最多输入10位(i==10触发比对),或按下结束键(num=15)提前触发比对。

3. 密码比对规则

  • 第一步:长度校验:输入密码长度必须等于预设密码长度(PLEN=9),长度不等直接判定错误;
  • 第二步:逐位校验:长度一致时,逐位比对passwordtemppassword,全部相等才判定正确;
  • 标志位逻辑flag=flag&&(...)是嵌入式中高效的比对方式,只要有一位不等,flag立即变为0,后续循环无需判断。

4. 结果处理

场景处理逻辑
密码正确显示"Right Open!>>>>" → 点亮LED 30秒 → 熄灭LED → 错误次数清零
密码错误(<3次)显示"Wrong! Retry!" → 错误次数+1 → 等待重新输入
密码错误(=3次)显示"Wrong 3 times!" → 死循环锁定系统(需重启单片机)

四、关键注意事项

1. 潜在问题

  • PLEN赋值异常
    预设密码数组password有10个元素({1,2,3,4,'A',1,2,3,4,5}),但代码中PLEN=9(注释中自动计算应为10),会导致长度校验时,输入10位密码直接判定错误,属于明显笔误;
  • 结束键值硬编码
    15==num中的15是结束键的按键值,需确保keyscan.h中该键返回值为15,否则无法触发提前比对;
  • 延时函数精度
    delayms2(30000)的实际延时取决于delayms2的实现(51单片机1ms延时需约1000个机器周期),30000次调用可能远超过30秒;
  • 无按键去抖
    KeyPro()需内置按键去抖逻辑(如延时10ms再扫描),否则易出现误触发。

2. 硬件适配说明

  • LCD1602接线
    代码未显示LCD的数据线/控制线定义,需确保lcd1602.h中引脚定义与硬件一致(如RS接P2.0、EN接P2.1、D0~D7接P0口);
  • 键盘接线
    keyscan.h需匹配实际键盘(如4×4矩阵键盘),按键值(1/2/3/'A'/15)需与扫描逻辑对应;
  • LED驱动
    led=P3^0为共阳LED(低电平点亮),若为共阴LED需改为led=1点亮。

3. 优化方向

  • 恢复PLEN自动计算:PLEN=sizeof(password)/sizeof(password[0]);,避免手动赋值错误;
  • 增加输入回退功能:支持删除最后一位输入的密码;
  • 优化锁定逻辑:将死循环改为“延时锁定”(如锁定60秒后自动解锁);
  • 增加密码修改功能:通过管理员密码进入修改模式,更新预设密码。

五、功能总结

模块核心功能
LCD1602显示欢迎语、密码输入提示、比对结果
键盘扫描采集用户输入的密码(数字/功能键)
密码比对先校验长度,再逐位校验,确保密码一致性
结果输出正确则点亮LED,错误累计3次锁定系统

该代码是51单片机“密码锁”的经典入门实现,逻辑清晰、易于理解,仅需适配硬件接线和驱动函数即可直接使用。

注意事项

实物图

13511c85653bcde9a977bcbaa312b802.jpg

4bedef49c66c9935e6f3325b1f966f5c.jpg
仿真与代码见附件

设计图

未生成预览图,请在编辑器重新保存一次

BOM

暂无BOM

3D模型

序号文件名称下载次数
暂无数据

附件

序号文件名称下载次数
暂无数据
克隆工程
添加到专辑
0
0
分享
侵权投诉
知识产权声明&复刻说明

本项目为开源硬件项目,其相关的知识产权归创作者所有。创作者在本平台上传该硬件项目仅供平台用户用于学习交流及研究,不包括任何商业性使用,请勿用于商业售卖或其他盈利性的用途;如您认为本项目涉嫌侵犯了您的相关权益,请点击上方“侵权投诉”按钮,我们将按照嘉立创《侵权投诉与申诉规则》进行处理。

请在进行项目复刻时自行验证电路的可行性,并自行辨别该项目是否对您适用。您对复刻项目的任何后果负责,无论何种情况,本平台将不对您在复刻项目时,遇到的任何因开源项目电路设计问题所导致的直接、间接等损害负责。

底部导航