
简介基于单片机的电子密码锁1602液晶显示系统设计包面向单片机初学者、电子设计爱好者以及课程设计参考人群解决了从硬件搭建、软件编程到系统验证的完整学习需求。资源以单片机为控制核心搭配1602液晶屏、矩阵键盘和电源模块实现密码输入、正确校验、错误次数限制及超时锁定等常见安全逻辑。压缩包共25个文件既有完整设计报告Word文档也有Proteus仿真工程、Keil源码与十六进制烧录文件还附带1602液晶芯片的数据手册与项目截图整体大小仅399KB便于快速下载与打开。目前已有124人学习适合需要短时间理解电子密码锁原理并完成作品的人群。通过阅读报告和对照仿真源码可以掌握单片机IO配置、LCD1602显示时序、按键扫描方法、密码比对流程以及相关安全策略仿真文件与程序可直接运行也可在此基础上二次开发或制作实物达到学以致用的目的。1. 单片机电子密码锁1602 显示版型为什么是课程设计的“标准答案”电子密码锁是单片机课程的“钉子户”从 51 单片机课程设计到毕业设计都绕不开。它同时覆盖按键输入、状态判断、液晶显示、掉电存储四条主线单看每一环都不难串起来就是一套完整产品的骨架。压缩包里的“设计报告 仿真文件 程序”三件套交付标准就是Proteus 能跑通、Keil 能编译、报告对得上仿真截图。1602 液晶是这套方案里最值得较真的部分不用段选也不走串口靠 8 位并行总线逐字节刷屏RS、RW、E 三根控制线的时序差一点就花屏。下面从硬件选型、程序实现、仿真排错、报告撰写四层拆开讲照着能复现改着能答辩。2. 硬件方案与器件选型51单片机、矩阵键盘、EEPROM 与 1602 液晶的分工拿到压缩包后第一件事是打开仿真文件看原理图里用了哪些器件。这套题最常见的做法是四片式方案AT89C52 做核心、4×4 矩阵键盘做输入、LM016LProteus 里的 1602 模型做显示、AT24C02 做密码掉电存储。器件不多但每个模块的引脚接法直接决定程序里寄存器怎么配先把这张硬件分工图定下来再写代码。2.1 单片机选型AT89C52 与 STC89C52 的仿真/实物差异仿真原理图里的单片机几乎都是 AT89C52因为 Proteus 内置模型成熟不需要仿真下载电路。AT89C52 有 8KB Flash、256B RAM、3 个定时器、32 个 I/O密码锁这个负载绰绰有余。实物搭建时普遍换 STC89C52串口 ISP 下载不用编程器价格也更低和《单片机原理及应用》里讲的外设结构基本一致。换型号有两点注意STC 的 I/O 是准双向口、复位后默认高电平与 AT89C52 行为一致程序不用改但 STC 内部有独立的数据 Flash能用 ISP 软件划分成 EEPROM 区Proteus 仿真没有对应模型仿真代码统一按“AT89C52 外置 AT24C02”写实物里也不冲突。时钟方面仿真和实物都习惯用 12MHz 晶振配两个 33pF 电容。AT89C52 在这个配置下是 12T 模式一个机器周期正好 1us后面所有软件延时都按这个基准估算。复位电路用经典的 10uF 电容加 10kΩ 电阻接 RST仿真里自带复位实物必须画全。2.2 4×4 矩阵键盘的扫描原理与 1602 液晶的引脚分配矩阵键盘用 P1 口的 8 根线实现 16 个键P1.0~P1.3 做行线输出P1.4~P1.7 做列线输入。P1 口内部带上拉列线不按键时为高电平。扫描分两步先四行全部拉低读列线只要有一列为低说明有键按下再逐行拉低读列线用“哪一行为低 哪一列为低”定位按键。16 个键只占一个 P 口这是矩阵键盘省 I/O 的根本原因。1602 的数据线 D0~D7 接 P0.0~P0.7控制线 RS、RW、E 接 P2 口任意三根。P0 是开漏输出必须外接上拉电阻否则屏幕上会出现“有背光但一个字都不出”。本方案只写不读RW 固定接地能省一根 I/O。模块引脚接单片机说明1602D0~D7P0.0~P0.78 位数据总线10kΩ 排阻上拉1602RS / RW / EP2.6 / GND / P2.7指令数据选择 / 只写接地 / 下降沿锁存1602V010kΩ 电位器动臂对比度调节矩阵键盘行线P1.0~P1.3输出扫描低电平矩阵键盘列线P1.4~P1.7读入内部上拉AT24C02SCL / SDAP3.6 / P3.7I2C 时钟 / 数据SDA 需 4.7kΩ 上拉AT24C02A0~A2GND地址线接地写地址 0xA0提示P0 上拉在 Proteus 里用 RESPACK-8 排阻最省事公共端接 VCC8 个引脚按顺序接 P0.0~P0.7公共端接反会导致整个 P0 电平异常。2.3 AT24C02 掉电存储密码为什么要放在 EEPROM 里密码放在 51 的片内 RAM 里掉电就清零每次开机都要重设这在产品上不可接受。AT89C52 没有片内 EEPROMFlash 又不能在运行时随意改写所以外挂 AT24C02 是这套方案的标准动作。AT24C02 容量 256 字节I2C 接口写地址 0xA0、读地址 0xA1支持页写一次最多 8 字节。密码锁只存 6 位密码加一个标志字节空间绰绰有余。存储布局建议地址 0x00~0x05 存密码 ASCII 码0x06 存初始化标志。开机读 0x06不是固定值 0x5A 就先写默认密码“123456”并置标志是 0x5A 就直接读密码区。这样首次上电、用户改密、再次上电三种状态自洽报告里也好解释。void eeprom_load_pwd(void) { unsigned char i; if (at24c02_read(0x06) ! 0x5A) { // 首次上电无标志 for (i 0; i 6; i) at24c02_write(0x00 i, 123456[i]); // 默认密码 at24c02_write(0x06, 0x5A); // 置初始化标志 } for (i 0; i 6; i) pwd_saved[i] at24c02_read(0x00 i); // 载入 RAM }标志字节选 0x5A 而不是 0x00因为 EEPROM 出厂擦除态是全 0xFF新片读出来是 0xFF用 0x5A 才能区分“空白芯片”和“已初始化”。pwd_saved 放在 RAM 里供比对避免按键输入过程中反复走 I2C 总线干扰 1602 刷新。I2C 有两个仿真里必踩的坑SCL、SDA 必须接上拉电阻不接时电平不确定读写结果时对时错AT24C02 写完数据后有约 5ms 内部写周期 tWR期间不响应命令写完要延时 10ms 左右。3. Keil 程序实现1602 驱动、矩阵键盘扫描与密码校验的代码写法Keil 工程建议按模块拆文件lcd1602.c 管液晶、key.c 管键盘、i2c.c 和 eeprom.c 管 AT24C02、main.c 管流程。拆开的好处是每个文件都很短出问题能单独编译设计报告里的“软件模块划分”顺带有了素材。下面代码以 12MHz 晶振、AT89C52 十二T 模式为基准软件延时绝对值随 Keil 优化等级浮动同一工程内保持一致即可。3.1 1602 液晶驱动初始化为什么要连发三次 0x381602 的控制器是 HD44780上电后 VDD 升到 4.5V 约需 15ms期间不收指令。稳妥的初始化延时 15ms 后连发三次 0x38第一次可能被电源爬升吃掉第二次可能被内部复位吃掉第三次才保证进入“8 位总线、两行、5×8 字符”模式。#include reg52.h #include intrins.h #define LCD_DATA P0 sbit RS P2^6; // 0 指令1 数据 sbit RW P2^5; // 本方案只写可接地 sbit E P2^7; // 使能脉冲下降沿锁存 void delay_us(unsigned int t) { while (t--) _nop_(); } void delay_ms(unsigned int n) { unsigned int i, j; for (i 0; i n; i) for (j 0; j 120; j); // 12MHz 12T 下约 1ms } void lcd_cmd(unsigned char c) { RS 0; RW 0; LCD_DATA c; E 1; delay_us(10); E 0; // 采样窗口后拉低 delay_us(50); } void lcd_dat(unsigned char d) { RS 1; RW 0; LCD_DATA d; E 1; delay_us(10); E 0; delay_us(50); } void lcd_init(void) { delay_ms(15); lcd_cmd(0x38); delay_ms(5); // 8 位模式冗余三次 lcd_cmd(0x38); delay_us(100); lcd_cmd(0x38); lcd_cmd(0x08); // 关显示 lcd_cmd(0x01); delay_ms(2); // 清屏约 1.5ms lcd_cmd(0x06); // 地址自增 lcd_cmd(0x0C); // 开显示、关光标 }lcd_cmd 和 lcd_dat 的差别只在 RS 一位时序完全一致先放好 RS、RW 和 8 位数据再拉高 E 保持 10us最后拉低 E指令在下降沿被锁存执行。E 高电平是采样窗口要比数据建立时间约 200ns宽得多10us 在这个频率下很安全。参数里最值得记的是 0x01 清屏它是 1602 指令里执行最慢的约 1.5ms所以初始化结尾单独补了 2ms。固定延时替代了读忙标志 BF代价是每次写指令多等几十微秒对密码锁这种低速交互完全够用。指令功能说明0x388 位总线、两行、5×8 字符初始化首选其余两条指令都依赖它0x0C开显示、关光标、关闪烁正常显示态0x01清屏执行约 1.5ms之后要补延时3.2 矩阵键盘扫描消抖、逐行定位、等待松开矩阵键盘不能像独立按键那样直接读一个引脚必须分时扫描。键值表按 4×4 键盘常规排布前三行 1~9第四行 *、0、#、DA 做确认键、D 做修改密码入口这是课程设计里最常见的功能分配。unsigned char code key_map[16] { 1,2,3,A, // 第 0 行 4,5,6,B, // 第 1 行 7,8,9,C, // 第 2 行 *,0,#,D // 第 3 行 }; unsigned char keyscan(void) { unsigned char row, col, t; P1 0x0F; // 行全低列输入 if ((P1 0xF0) 0xF0) return 0xFF; // 无键 delay_ms(10); // 消抖 if ((P1 0xF0) 0xF0) return 0xFF; // 抖动误触 for (row 0; row 4; row) { P1 ~(0x01 row); // 只拉低第 row 行 t P1 0xF0; if (t 0xF0) continue; // 这行没键 if (t 0xE0) col 0; // P1.4 被拉低 else if (t 0xD0) col 1; // P1.5 else if (t 0xB0) col 2; // P1.6 else col 3; // P1.7 while ((P1 0xF0) ! 0xF0); // 等松开防连发 return key_map[row * 4 col]; } return 0xFF; }消抖延时取 10ms 不是拍脑袋机械按键簧片抖动一般在 5~10ms短于 5ms 消不干净长于 20ms 手感发粘。逐行定位时 P1 ~(0x01 row) 把非扫描行拉回高电平只有目标行为低列线上被拉低的必然是对应按键。等松开循环是这个函数最容易被删的部分——删掉后一次按键会被主循环读成多次密码框里会多出一串星号。3.3 主流程密码输入、校验与三次错误锁定交互按课程设计常见要求设计开机显示 PASSWORD:输入 6 位回显星号输完自动比对正确显示 OPEN 并驱动继电器开锁 3 秒错误显示 WRONG PWD 并累计连续错 3 次锁定 30 秒。main 里用到的 lcd_pos(row, col)、lcd_str(s)、lcd_clr() 是对 3.1 节函数的薄封装lcd_pos 发 0x80col第一行或 0xC0col第二行定位光标lcd_str 循环调 lcd_dat 输出字符串lcd_clr 发 0x01 清屏并延时 2ms每个函数三行代码放在 lcd1602.c 里。unsigned char pwd_saved[6], buf[6]; // 正确密码、输入缓冲 unsigned char err_cnt 0; sbit RELAY P2^0; // 低电平吸合继电器 unsigned char pwd_ok(void) { unsigned char i; for (i 0; i 6; i) if (buf[i] ! pwd_saved[i]) return 0; return 1; } void main(void) { unsigned char i, key; lcd_init(); eeprom_load_pwd(); // 读 EEPROM 密码 while (1) { lcd_clr(); lcd_str(PASSWORD:); for (i 0; i 6; i) { key keyscan(); if (key 0xFF) { i--; continue; } // 等键 buf[i] key; lcd_dat(*); // 星号回显 } if (pwd_ok()) { lcd_clr(); lcd_str(OPEN OK); RELAY 0; delay_ms(3000); RELAY 1; } else { err_cnt; lcd_clr(); lcd_str(WRONG PWD); if (err_cnt 3) { lcd_pos(1, 0); lcd_str(LOCK 30S); delay_ms(30000); err_cnt 0; } } } }输入回显用星号是密码系统的习惯错误计数在锁定结束后清零更严谨的做法是把计数也存进 EEPROM断电重启不清零这点在第 5 章讲。RELAY 低电平吸合对应最常见的 NPN 三极管驱动继电器电路线圈两端并续流二极管。for 循环里 i-- 配合 continue 是阻塞式等键适合这个单任务场景想加“10 秒无操作清空”就要把这里改成带超时的状态判断。3.4 AT24C02 的 I2C 读写起始、应答、写周期一个都不能少I2C 时序的骨架是三件事SCL 高电平期间 SDA 下降沿是起始条件、上升沿是停止条件数据在 SCL 低电平时变化、高电平时必须保持不变从机收到每字节后拉低 SDA 应答。AT24C02 器件地址是 1010A2A1A0R/WA0~A2 接地后写地址 0xA0、读地址 0xA1。sbit SCL P3^6; sbit SDA P3^7; void i2c_start(void){ SDA1; SCL1; delay_us(5); SDA0; delay_us(5); SCL0; } void i2c_stop(void){ SCL0; SDA0; delay_us(5); SCL1; delay_us(5); SDA1; } void i2c_wbyte(unsigned char d) { unsigned char i; for (i 0; i 8; i) { SCL 0; SDA (d 0x80) ? 1 : 0; // 先发最高位 d 1; delay_us(2); SCL 1; delay_us(2); } SCL 0; } void at24c02_write(unsigned char addr, unsigned char dat) { i2c_start(); i2c_wbyte(0xA0); // 器件地址 写 SDA 1; SCL 1; while (SDA); // 等从机应答 i2c_wbyte(addr); // 字地址 SDA 1; SCL 1; while (SDA); i2c_wbyte(dat); SDA 1; SCL 1; while (SDA); i2c_stop(); delay_ms(10); // tWR 约 5ms保守 10ms }写函数末尾的 delay_ms(10) 不能省写周期 tWR 约 5ms期间芯片不响应总线仿真里“写入成功但重启后密码回默认”就是因为掉电瞬间写周期没走完。应答等待用 while (SDA) 死等加一个计数上限更严谨仿真里不加也能跑。读函数 at24c02_read 的骨架是写完字地址后多发一次 i2c_start重复起始条件把器件地址换成 0xA1再 8 次 {SCL1; 读 SDA; SCL0;} 从最高位收数据最后 i2c_stop 结束和写函数完全对称。4. Proteus 仿真搭建与联调原理图、HEX 加载与三种典型故障压缩包里的仿真文件打开后先看后缀老工程是 .DSNProteus 8 兼容打开新格式是 .pdsprj。打开后对照原理图自查元件和连线再运行。Proteus 的仿真模型对“没接上拉”“引脚悬空”容忍度很高故障很少报错而是行为诡异比如花屏、按键时灵时不灵。4.1 元件清单与接线顺序Proteus 搜索关键词和关键参数如下表照着放不会漏件。元件Proteus 关键词数量关键参数/接法单片机AT89C52112MHz 晶振 2×33pF1602 液晶LM016L1D0~D7 接 P0EEPROMAT24C021A0~A2 接 GND矩阵按键BUTTON164×4 排布排阻RESPACK-81公共端 VCC接 P0 上拉电位器POT-LIN110kΩ动臂接 V0上拉电阻RES24.7kΩSDA/SCL 上拉接线按“最小系统→显示→键盘→存储”四组画每组连完标一个网络标签后续查错和报告插图都方便。HEX 加载路径是双击 AT89C52 → Program File 选 Keil Output 下的 .hexCrystal Frequency 填 12MHz。Keil 工程路径不要带中文Proteus 对中文路径支持不理想轻则加载失败重则直接报错。加载完先跑最小系统液晶能正常出字再往下调键盘和存储。4.2 三种典型故障现象、根因与处理对照仿真跑不通时按对照表筛一遍多数问题集中在下面几类。现象根因处理液晶有背光无字或满屏黑块P0 没上拉V0 悬空补 RESPACK-8用电位器调对比度按键按下无反应行列接法和代码不一致HEX 未加载核对 P1 定义重新加载 .hex密码重启后回默认AT24C02 写周期延时不足写完加 10ms 延时一运行就反复复位RST 悬空或复位电路错误RST 接 10uF 到 VCC、10kΩ 到 GND排错顺序“先看电平再看代码”点击 Proteus 里的按键观察附近连线有无电平颜色变化。按下时连线状态不变说明按键没接到 P1 口或行列接反电平有变化而程序没反应问题才在代码的引脚定义和扫描逻辑。液晶同理用 LOGICPROBE 探针挂 E 脚运行后持续高或持续低说明程序根本没执行到写液晶的代码优先检查 main 是否卡在 eeprom_load_pwd 的 I2C 等待里。4.3 用逻辑探针验证执行流与 E 脉冲宽度LOGICPROBE 是排查“程序到底跑没跑”的利器。在代码里留一个调试引脚关键函数前后翻转它探针就能显示执行流。sbit DEBUG_PIN P3^5; // 空置引脚作调试输出 void debug_toggle(void){ DEBUG_PIN ~DEBUG_PIN; }调用位置建议放三处lcd_init 完成后翻转一次确认初始化执行完keyscan 检测到有效按键后翻转一次确认扫描逻辑正常at24c02_write 写完翻转一次确认 I2C 流程走完。运行中哪个探针不翻转就查哪个模块——这是把黑盒仿真变白盒调试的最快路径。实测中等松开循环卡死是探针静止的最常见原因按键模型没松开时 P1 列电平一直为低while 永远出不来。E 脉冲宽度用虚拟示波器接 P2.7 验证每个脉冲对应一次写操作脉冲完全消失除了代码没执行还有一种可能是 Keil 优化等级太高把延时循环优化掉了把延时计数变量声明成 volatile 或把优化等级锁到 0~1 再重新生成 HEX。5. 设计报告的撰写与答辩验证技巧让仿真截图替你说话5.1 报告结构与截图对应关系设计报告按“需求分析→硬件设计→软件设计→仿真测试→总结”五段走每段至少一张图。仿真测试别只贴一张全亮图要贴三个功能终态输入满 6 位显示星号的中间态、开锁成功显示 OPEN 的终态、连续三次错误显示 LOCK 30S 的终态。三张图分别对应键盘扫描、密码比对、错误锁定三个模块答辩讲到哪就切到哪比口头描述管用。功能点截图内容文字说明要点键盘输入与消抖屏幕出现 6 个星号矩阵扫描流程 10ms 消抖密码正确开锁OPEN OK继电器灯亮比对算法 继电器驱动掉电记忆密码重启后直接可用旧密码AT24C02 地址布局 tWR5.2 答辩追问四个必被问到的点第一问密码存哪里掉电为什么还在回答落到 AT24C02 器件地址 0xA0 和写周期 tWR能现场画出 SCL/SDA 的起始、停止、应答波形基本满分。第二问消抖为什么取 10ms把机械抖动 5~10ms 的物理依据讲清楚比背代码有说服力。第三问三次错误锁定怎么防暴力破解说明错误计数也存 EEPROM、断电重启不清零在 2.3 节标志字节后面加一个地址存 err_cnt 即可。第四问最有区分度改成 4 位或 8 位密码怎么改正确答法是把密码长度抽成宏 PWD_LENEEPROM 密码区预留 8 字节而不写死 6 字节界面循环和比对函数全部引用这个宏改位数只动一个数系统的扩展性就落到了实处。本文还有配套的精品资源点击获取