
专业版
C51密码锁
884
0
0
2
简介
基于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),长度不等直接判定错误;
- 第二步:逐位校验:长度一致时,逐位比对
passwordtemp与password,全部相等才判定正确; - 标志位逻辑:
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单片机“密码锁”的经典入门实现,逻辑清晰、易于理解,仅需适配硬件接线和驱动函数即可直接使用。
注意事项
无
实物图


仿真与代码见附件
设计图
未生成预览图,请在编辑器重新保存一次BOM
暂无BOM
克隆工程添加到专辑
0
0
分享
侵权投诉
知识产权声明&复刻说明
本项目为开源硬件项目,其相关的知识产权归创作者所有。创作者在本平台上传该硬件项目仅供平台用户用于学习交流及研究,不包括任何商业性使用,请勿用于商业售卖或其他盈利性的用途;如您认为本项目涉嫌侵犯了您的相关权益,请点击上方“侵权投诉”按钮,我们将按照嘉立创《侵权投诉与申诉规则》进行处理。
请在进行项目复刻时自行验证电路的可行性,并自行辨别该项目是否对您适用。您对复刻项目的任何后果负责,无论何种情况,本平台将不对您在复刻项目时,遇到的任何因开源项目电路设计问题所导致的直接、间接等损害负责。









