基于STC单片机的电子密码锁设计
一、系统总体设计
1.1 系统架构
┌─────────────────────────────────────────────────────────┐
│ 电子密码锁系统架构 │
├─────────────────────────────────────────────────────────┤
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 矩阵键盘 │ │ LCD1602 │ │ EEPROM │ │
│ │ 4×4按键 │◄──┤ 显示模块 │◄──┤ AT24C02 │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ ┌────▼────────────────▼────────────────▼─────┐ │
│ │ STC89C52RC 主控 │ │
│ │ • 键盘扫描处理 • 密码验证算法 │ │
│ │ • EEPROM读写管理 • 开锁/报警控制 │ │
│ │ • 输入状态机管理 • 防暴力破解机制 │ │
│ └────┬────────────────┬────────────────┬─────┘ │
│ │ │ │ │
│ ┌────▼─────┐ ┌──▼──┐ ┌──▼──┐ │
│ │ 继电器/ │ │ LED │ │ 蜂鸣 │ │
│ │ 电磁锁 │ │ 指示 │ │ 报警 │ │
│ └──────────┘ └─────┘ └─────┘ │
└─────────────────────────────────────────────────────────┘
1.2 技术指标
| 参数 | 规格 | 说明 |
|---|---|---|
| 主控芯片 | STC89C52RC | 8位单片机,11.0592MHz晶振 |
| 密码长度 | 6位 | 可扩展至8位 |
| 存储方式 | EEPROM | AT24C02,断电不丢失 |
| 输入方式 | 4×4矩阵键盘 | 0-9数字键+F1-F4功能键 |
| 显示方式 | LCD1602 | 16×2字符液晶 |
| 开锁方式 | 继电器/电磁锁 | 5V/12V驱动 |
| 报警功能 | 蜂鸣器+LED | 连续输错3次锁定 |
| 工作电压 | 5V DC | USB供电或电源适配器 |
二、硬件设计
2.1 核心元件选型
| 模块 | 型号 | 数量 | 说明 |
|---|---|---|---|
| 主控 | STC89C52RC | 1 | 8位单片机,8KB Flash |
| 显示 | LCD1602 | 1 | 16×2字符液晶 |
| 存储 | AT24C02 | 1 | I²C EEPROM,256字节 |
| 键盘 | 4×4薄膜键盘 | 1 | 16键矩阵键盘 |
| 锁具 | 12V电磁锁 | 1 | 断电开锁/通电开锁 |
| 驱动 | 继电器模块 | 1 | 5V控制12V |
| 指示 | LED+蜂鸣器 | 若干 | 状态指示和报警 |
| 电源 | 5V/2A适配器 | 1 | 系统供电 |
2.2 硬件连接表
/* STC89C52引脚定义 */
#include <reg52.h>
#include <intrins.h>
// 系统时钟定义
#define FOSC 11059200L // 晶振频率11.0592MHz
#define BAUD 9600 // 串口波特率
// GPIO端口定义
#define KEY_PORT P1 // P1口接4×4键盘
#define LED_PORT P2 // P2口接LED指示
#define LCD_PORT P0 // P0口接LCD1602数据线
// 控制信号引脚
sbit LCD_RS = P3^5; // LCD寄存器选择
sbit LCD_RW = P3^6; // LCD读写控制
sbit LCD_EN = P3^7; // LCD使能信号
sbit BEEP = P3^4; // 蜂鸣器控制
sbit LOCK = P3^3; // 继电器控制(开锁)
sbit LED_GREEN = P2^0; // 绿灯:系统正常
sbit LED_RED = P2^1; // 红灯:报警/错误
sbit LED_BLUE = P2^2; // 蓝灯:输入状态
// I²C引脚(AT24C02)
sbit I2C_SCL = P3^0; // I²C时钟线
sbit I2C_SDA = P3^1; // I²C数据线
// 键盘行列定义
#define ROW_MASK 0x0F // 行掩码(P1.0-P1.3)
#define COL_MASK 0xF0 // 列掩码(P1.4-P1.7)
// 系统参数
#define PASSWORD_LEN 6 // 密码长度
#define MAX_TRY_TIMES 3 // 最大尝试次数
#define LOCK_TIME 30000 // 锁定时间(30秒)
三、软件系统设计
3.1 数据结构定义
/* 系统数据结构 */
#include <string.h>
// 系统状态枚举
typedef enum {
SYS_INIT = 0, // 系统初始化
SYS_IDLE = 1, // 待机状态
SYS_INPUT = 2, // 密码输入状态
SYS_VERIFY = 3, // 密码验证状态
SYS_UNLOCK = 4, // 开锁状态
SYS_LOCKED = 5, // 系统锁定状态
SYS_SETTING = 6, // 密码设置状态
SYS_ERROR = 7 // 系统错误状态
} SystemState;
// 键盘键值定义
typedef enum {
KEY_0 = 0x00, KEY_1, KEY_2, KEY_3,
KEY_4, KEY_5, KEY_6, KEY_7,
KEY_8, KEY_9, KEY_A, KEY_B,
KEY_C, KEY_D, KEY_E, KEY_F,
KEY_ENTER = 0x0E, // #键确认
KEY_CLEAR = 0x0F, // *键清除
KEY_FUNC1 = 0x0A, // A键功能1
KEY_FUNC2 = 0x0B, // B键功能2
KEY_FUNC3 = 0x0C, // C键功能3
KEY_FUNC4 = 0x0D, // D键功能4
KEY_NONE = 0xFF // 无按键
} KeyValue;
// 系统数据结构
typedef struct {
SystemState state; // 当前系统状态
unsigned char password[PASSWORD_LEN]; // 存储的密码
unsigned char input_buf[PASSWORD_LEN]; // 输入缓冲区
unsigned char input_len; // 已输入长度
unsigned char try_times; // 尝试次数
unsigned long lock_timer; // 锁定计时器
unsigned char setting_mode; // 设置模式标志
unsigned char beep_count; // 蜂鸣器计数
unsigned char led_count; // LED闪烁计数
} SystemData;
// 全局变量
SystemData sys_data;
unsigned char display_buf[17]; // 显示缓冲区
unsigned long system_tick = 0; // 系统节拍
3.2 延时函数
/* 延时函数 */
void DelayMs(unsigned int ms) {
unsigned int i, j;
for(i = 0; i < ms; i++)
for(j = 0; j < 110; j++);
}
void DelayUs(unsigned int us) {
while(us--) {
_nop_(); _nop_(); _nop_(); _nop_();
}
}
/* 定时器0初始化(1ms中断) */
void Timer0_Init(void) {
TMOD &= 0xF0; // 清除T0控制位
TMOD |= 0x01; // 设置T0为模式1(16位定时器)
TH0 = 0xFC; // 装载初值(1ms@11.0592MHz)
TL0 = 0x66;
ET0 = 1; // 允许T0中断
EA = 1; // 允许总中断
TR0 = 1; // 启动T0
}
/* 定时器0中断服务函数 */
void Timer0_ISR(void) interrupt 1 {
TH0 = 0xFC; // 重装初值
TL0 = 0x66;
system_tick++; // 系统节拍递增
// 蜂鸣器计时
if(sys_data.beep_count > 0) {
sys_data.beep_count--;
if(sys_data.beep_count == 0) {
BEEP = 1; // 关闭蜂鸣器
}
}
// LED闪烁计时
if(sys_data.led_count > 0) {
sys_data.led_count--;
if(sys_data.led_count == 0) {
LED_BLUE = !LED_BLUE; // 蓝灯闪烁
sys_data.led_count = 500; // 500ms闪烁一次
}
}
// 锁定计时
if(sys_data.state == SYS_LOCKED && sys_data.lock_timer > 0) {
sys_data.lock_timer--;
if(sys_data.lock_timer == 0) {
sys_data.state = SYS_IDLE; // 解除锁定
sys_data.try_times = 0; // 重置尝试次数
LED_RED = 1; // 关闭红灯
}
}
}
3.3 键盘扫描程序
/* 4×4矩阵键盘扫描 */
unsigned char KeyScan(void) {
unsigned char key_value = KEY_NONE;
unsigned char temp;
// 扫描第1列(P1.4)
KEY_PORT = 0xEF; // 11101111
temp = KEY_PORT & 0x0F;
if(temp != 0x0F) {
DelayMs(10); // 消抖
temp = KEY_PORT & 0x0F;
if(temp != 0x0F) {
switch(temp) {
case 0x0E: key_value = KEY_1; break; // 第1行
case 0x0D: key_value = KEY_4; break; // 第2行
case 0x0B: key_value = KEY_7; break; // 第3行
case 0x07: key_value = KEY_FUNC1; break; // 第4行
}
while((KEY_PORT & 0x0F) != 0x0F); // 等待按键释放
return key_value;
}
}
// 扫描第2列(P1.5)
KEY_PORT = 0xDF; // 11011111
temp = KEY_PORT & 0x0F;
if(temp != 0x0F) {
DelayMs(10);
temp = KEY_PORT & 0x0F;
if(temp != 0x0F) {
switch(temp) {
case 0x0E: key_value = KEY_2; break;
case 0x0D: key_value = KEY_5; break;
case 0x0B: key_value = KEY_8; break;
case 0x07: key_value = KEY_0; break;
}
while((KEY_PORT & 0x0F) != 0x0F);
return key_value;
}
}
// 扫描第3列(P1.6)
KEY_PORT = 0xBF; // 10111111
temp = KEY_PORT & 0x0F;
if(temp != 0x0F) {
DelayMs(10);
temp = KEY_PORT & 0x0F;
if(temp != 0x0F) {
switch(temp) {
case 0x0E: key_value = KEY_3; break;
case 0x0D: key_value = KEY_6; break;
case 0x0B: key_value = KEY_9; break;
case 0x07: key_value = KEY_CLEAR; break;
}
while((KEY_PORT & 0x0F) != 0x0F);
return key_value;
}
}
// 扫描第4列(P1.7)
KEY_PORT = 0x7F; // 01111111
temp = KEY_PORT & 0x0F;
if(temp != 0x0F) {
DelayMs(10);
temp = KEY_PORT & 0x0F;
if(temp != 0x0F) {
switch(temp) {
case 0x0E: key_value = KEY_FUNC2; break;
case 0x0D: key_value = KEY_FUNC3; break;
case 0x0B: key_value = KEY_FUNC4; break;
case 0x07: key_value = KEY_ENTER; break;
}
while((KEY_PORT & 0x0F) != 0x0F);
return key_value;
}
}
return KEY_NONE;
}
3.4 LCD1602驱动
/* LCD1602驱动程序 */
void LCD_WriteCmd(unsigned char cmd) {
LCD_RS = 0; // 命令模式
LCD_RW = 0; // 写操作
LCD_PORT = cmd; // 输出命令
LCD_EN = 1; // 使能脉冲
DelayUs(10);
LCD_EN = 0;
DelayMs(2); // 等待命令执行
}
void LCD_WriteData(unsigned char dat) {
LCD_RS = 1; // 数据模式
LCD_RW = 0; // 写操作
LCD_PORT = dat; // 输出数据
LCD_EN = 1; // 使能脉冲
DelayUs(10);
LCD_EN = 0;
DelayUs(100);
}
void LCD_Init(void) {
DelayMs(15); // 等待LCD稳定
LCD_WriteCmd(0x38); // 8位数据接口,2行显示,5×7点阵
LCD_WriteCmd(0x0C); // 显示开,光标关,闪烁关
LCD_WriteCmd(0x06); // 光标右移,显示不移位
LCD_WriteCmd(0x01); // 清屏
DelayMs(2);
}
void LCD_SetCursor(unsigned char row, unsigned char col) {
unsigned char addr;
if(row == 0) {
addr = 0x80 + col; // 第一行起始地址0x80
} else {
addr = 0xC0 + col; // 第二行起始地址0xC0
}
LCD_WriteCmd(addr);
}
void LCD_ShowString(unsigned char row, unsigned char col, char *str) {
LCD_SetCursor(row, col);
while(*str) {
LCD_WriteData(*str++);
}
}
void LCD_ClearLine(unsigned char row) {
unsigned char i;
LCD_SetCursor(row, 0);
for(i = 0; i < 16; i++) {
LCD_WriteData(' ');
}
}
void LCD_ShowPassword(unsigned char row, unsigned char len) {
unsigned char i;
LCD_SetCursor(row, 0);
for(i = 0; i < len; i++) {
LCD_WriteData('*'); // 显示星号隐藏密码
}
}
3.5 I²C EEPROM驱动(AT24C02)
/* I²C总线驱动 */
void I2C_Delay(void) {
unsigned char i;
for(i = 0; i < 5; i++) {
_nop_();
}
}
void I2C_Start(void) {
I2C_SDA = 1;
I2C_SCL = 1;
I2C_Delay();
I2C_SDA = 0;
I2C_Delay();
I2C_SCL = 0;
}
void I2C_Stop(void) {
I2C_SDA = 0;
I2C_SCL = 1;
I2C_Delay();
I2C_SDA = 1;
I2C_Delay();
}
unsigned char I2C_WaitAck(void) {
unsigned char ack;
I2C_SDA = 1; // 释放SDA线
I2C_SCL = 1;
I2C_Delay();
ack = I2C_SDA;
I2C_SCL = 0;
return ack;
}
void I2C_SendByte(unsigned char dat) {
unsigned char i;
for(i = 0; i < 8; i++) {
I2C_SDA = (dat & 0x80) ? 1 : 0;
I2C_SCL = 1;
I2C_Delay();
I2C_SCL = 0;
dat <<= 1;
}
}
unsigned char I2C_ReadByte(void) {
unsigned char i, dat = 0;
I2C_SDA = 1; // 释放SDA线
for(i = 0; i < 8; i++) {
I2C_SCL = 1;
I2C_Delay();
dat <<= 1;
if(I2C_SDA) dat |= 0x01;
I2C_SCL = 0;
}
return dat;
}
void I2C_SendAck(unsigned char ack) {
I2C_SDA = ack ? 0 : 1; // ack=0表示应答
I2C_SCL = 1;
I2C_Delay();
I2C_SCL = 0;
}
/* AT24C02驱动 */
void AT24C02_WriteByte(unsigned char addr, unsigned char dat) {
I2C_Start();
I2C_SendByte(0xA0); // 器件地址+写命令
I2C_WaitAck();
I2C_SendByte(addr); // 存储地址
I2C_WaitAck();
I2C_SendByte(dat); // 写入数据
I2C_WaitAck();
I2C_Stop();
DelayMs(10); // 等待写入完成
}
unsigned char AT24C02_ReadByte(unsigned char addr) {
unsigned char dat;
I2C_Start();
I2C_SendByte(0xA0); // 器件地址+写命令
I2C_WaitAck();
I2C_SendByte(addr); // 存储地址
I2C_WaitAck();
I2C_Start();
I2C_SendByte(0xA1); // 器件地址+读命令
I2C_WaitAck();
dat = I2C_ReadByte();
I2C_SendAck(1); // 非应答
I2C_Stop();
return dat;
}
3.6 密码管理
/* 密码管理函数 */
void Password_Init(void) {
unsigned char i;
// 从EEPROM读取密码
for(i = 0; i < PASSWORD_LEN; i++) {
sys_data.password[i] = AT24C02_ReadByte(i);
}
// 检查是否为首次使用(EEPROM为空)
if(sys_data.password[0] == 0xFF) {
// 设置默认密码:123456
sys_data.password[0] = 1;
sys_data.password[1] = 2;
sys_data.password[2] = 3;
sys_data.password[3] = 4;
sys_data.password[4] = 5;
sys_data.password[5] = 6;
// 保存到EEPROM
for(i = 0; i < PASSWORD_LEN; i++) {
AT24C02_WriteByte(i, sys_data.password[i]);
}
}
}
void Password_Save(void) {
unsigned char i;
for(i = 0; i < PASSWORD_LEN; i++) {
AT24C02_WriteByte(i, sys_data.password[i]);
}
}
unsigned char Password_Verify(void) {
unsigned char i;
for(i = 0; i < PASSWORD_LEN; i++) {
if(sys_data.input_buf[i] != sys_data.password[i]) {
return 0; // 密码错误
}
}
return 1; // 密码正确
}
四、系统状态机
4.1 主状态机
/* 系统状态机 */
void System_Init(void) {
// 初始化系统数据
sys_data.state = SYS_INIT;
sys_data.input_len = 0;
sys_data.try_times = 0;
sys_data.setting_mode = 0;
sys_data.beep_count = 0;
sys_data.led_count = 0;
sys_data.lock_timer = 0;
// 初始化硬件
LED_PORT = 0xFF; // LED端口输出高电平
BEEP = 1; // 蜂鸣器关闭
LOCK = 1; // 锁关闭
// 初始化外设
Timer0_Init();
LCD_Init();
Password_Init();
// 显示启动画面
LCD_ShowString(0, 0, "Electronic Lock");
LCD_ShowString(1, 0, "Initializing...");
DelayMs(2000);
sys_data.state = SYS_IDLE;
LED_GREEN = 0; // 绿灯亮,系统就绪
}
void System_Idle(void) {
LCD_ClearLine(0);
LCD_ClearLine(1);
LCD_ShowString(0, 0, "Input Password:");
LCD_ShowString(1, 0, "Press * to Set");
sys_data.input_len = 0;
memset(sys_data.input_buf, 0, sizeof(sys_data.input_buf));
}
void System_Input(unsigned char key) {
if(sys_data.input_len < PASSWORD_LEN) {
if(key >= KEY_0 && key <= KEY_9) {
sys_data.input_buf[sys_data.input_len] = key;
sys_data.input_len++;
// 显示星号
LCD_SetCursor(1, 0);
LCD_WriteData('*');
// 短蜂鸣提示
BEEP = 0;
sys_data.beep_count = 50; // 50ms蜂鸣
if(sys_data.input_len == PASSWORD_LEN) {
sys_data.state = SYS_VERIFY;
}
}
}
}
void System_Verify(void) {
LCD_ClearLine(1);
if(Password_Verify()) {
// 密码正确
LCD_ShowString(1, 0, "Password Correct!");
LED_GREEN = 0; // 绿灯亮
BEEP = 0; // 蜂鸣器响
sys_data.beep_count = 1000; // 1秒蜂鸣
sys_data.state = SYS_UNLOCK;
sys_data.try_times = 0; // 重置尝试次数
} else {
// 密码错误
LCD_ShowString(1, 0, "Password Error!");
LED_RED = 0; // 红灯亮
BEEP = 0; // 蜂鸣器响
sys_data.beep_count = 500; // 0.5秒蜂鸣
sys_data.try_times++;
if(sys_data.try_times >= MAX_TRY_TIMES) {
sys_data.state = SYS_LOCKED;
sys_data.lock_timer = LOCK_TIME; // 锁定30秒
} else {
DelayMs(2000);
sys_data.state = SYS_IDLE; // 返回待机状态
}
}
}
void System_Unlock(void) {
LOCK = 0; // 打开锁
DelayMs(3000); // 开锁3秒
LOCK = 1; // 关闭锁
sys_data.state = SYS_IDLE; // 返回待机状态
LED_GREEN = 1; // 关闭绿灯
}
void System_Locked(void) {
LCD_ClearLine(0);
LCD_ClearLine(1);
LCD_ShowString(0, 0, "System Locked!");
sprintf(display_buf, "Wait %02lus", sys_data.lock_timer/1000);
LCD_ShowString(1, 0, display_buf);
LED_RED = 0; // 红灯常亮
LED_GREEN = 1; // 关闭绿灯
}
void System_Setting(unsigned char key) {
static unsigned char new_password[PASSWORD_LEN];
static unsigned char confirm_password[PASSWORD_LEN];
static unsigned char step = 0;
if(step == 0) {
// 输入旧密码
LCD_ClearLine(0);
LCD_ShowString(0, 0, "Input Old Pass:");
step = 1;
} else if(step == 1) {
// 输入旧密码过程
if(key >= KEY_0 && key <= KEY_9) {
if(sys_data.input_len < PASSWORD_LEN) {
sys_data.input_buf[sys_data.input_len] = key;
sys_data.input_len++;
LCD_SetCursor(1, 0);
LCD_WriteData('*');
if(sys_data.input_len == PASSWORD_LEN) {
if(Password_Verify()) {
step = 2; // 旧密码正确,进入新密码输入
sys_data.input_len = 0;
LCD_ClearLine(1);
LCD_ShowString(1, 0, "Input New Pass:");
} else {
LCD_ShowString(1, 0, "Old Pass Error!");
DelayMs(2000);
step = 0; // 重新开始
}
}
}
}
} else if(step == 2) {
// 输入新密码过程
if(key >= KEY_0 && key <= KEY_9) {
if(sys_data.input_len < PASSWORD_LEN) {
new_password[sys_data.input_len] = key;
sys_data.input_len++;
LCD_SetCursor(1, 0);
LCD_WriteData('*');
if(sys_data.input_len == PASSWORD_LEN) {
step = 3; // 进入确认密码输入
sys_data.input_len = 0;
LCD_ClearLine(1);
LCD_ShowString(1, 0, "Confirm Pass:");
}
}
}
} else if(step == 3) {
// 确认新密码过程
if(key >= KEY_0 && key <= KEY_9) {
if(sys_data.input_len < PASSWORD_LEN) {
confirm_password[sys_data.input_len] = key;
sys_data.input_len++;
LCD_SetCursor(1, 0);
LCD_WriteData('*');
if(sys_data.input_len == PASSWORD_LEN) {
// 检查两次输入是否一致
unsigned char i;
unsigned char match = 1;
for(i = 0; i < PASSWORD_LEN; i++) {
if(new_password[i] != confirm_password[i]) {
match = 0;
break;
}
}
if(match) {
// 密码一致,保存新密码
memcpy(sys_data.password, new_password, PASSWORD_LEN);
Password_Save();
LCD_ShowString(1, 0, "Password Saved!");
BEEP = 0;
sys_data.beep_count = 500;
} else {
LCD_ShowString(1, 0, "Pass Not Match!");
}
DelayMs(2000);
step = 0; // 返回设置模式
sys_data.state = SYS_IDLE;
}
}
}
}
}
五、主程序
5.1 主程序框架
/* 主程序 */
void main(void) {
unsigned char key;
// 系统初始化
System_Init();
while(1) {
// 键盘扫描
key = KeyScan();
// 根据系统状态处理
switch(sys_data.state) {
case SYS_IDLE:
if(key != KEY_NONE) {
if(key == KEY_CLEAR) {
// 进入设置模式
sys_data.state = SYS_SETTING;
sys_data.setting_mode = 1;
System_Setting(key);
} else if(key >= KEY_0 && key <= KEY_9) {
// 开始输入密码
sys_data.state = SYS_INPUT;
System_Input(key);
}
}
break;
case SYS_INPUT:
if(key != KEY_NONE) {
if(key == KEY_CLEAR) {
// 清除输入
sys_data.input_len = 0;
memset(sys_data.input_buf, 0, sizeof(sys_data.input_buf));
LCD_ClearLine(1);
} else if(key == KEY_ENTER) {
// 确认输入
if(sys_data.input_len == PASSWORD_LEN) {
sys_data.state = SYS_VERIFY;
}
} else {
System_Input(key);
}
}
break;
case SYS_VERIFY:
System_Verify();
break;
case SYS_UNLOCK:
System_Unlock();
break;
case SYS_LOCKED:
System_Locked();
break;
case SYS_SETTING:
if(key != KEY_NONE) {
System_Setting(key);
}
break;
default:
sys_data.state = SYS_IDLE;
break;
}
DelayMs(10); // 主循环延时
}
}
参考代码 基于STC单片机电子密码锁 www.youwenfan.com/contentcst/133201.html
六、扩展功能
6.1 报警功能
/* 报警功能 */
void Alarm_Trigger(unsigned char alarm_type) {
switch(alarm_type) {
case 1: // 防拆报警
LED_RED = 0;
BEEP = 0;
LOCK = 1; // 锁死系统
sys_data.state = SYS_ERROR;
LCD_ClearLine(0);
LCD_ShowString(0, 0, "Tamper Alarm!");
break;
case 2: // 超时报警
LED_RED = 0;
BEEP = 0;
sys_data.beep_count = 2000; // 2秒蜂鸣
LCD_ClearLine(1);
LCD_ShowString(1, 0, "Timeout Alarm!");
break;
}
}
6.2 串口通信
/* 串口通信 */
void UART_Init(void) {
SCON = 0x50; // 8位数据,可变波特率
TMOD &= 0x0F; // 清除T1控制位
TMOD |= 0x20; // 设置T1为模式2(8位自动重装)
TH1 = 0xFD; // 装载初值(9600@11.0592MHz)
TL1 = 0xFD;
ET1 = 0; // 禁止T1中断
TR1 = 1; // 启动T1
ES = 1; // 允许串口中断
}
void UART_SendByte(unsigned char dat) {
SBUF = dat;
while(!TI);
TI = 0;
}
void UART_SendString(char *str) {
while(*str) {
UART_SendByte(*str++);
}
}
/* 串口中断服务函数 */
void UART_ISR(void) interrupt 4 {
unsigned char received;
if(RI) {
RI = 0;
received = SBUF;
// 处理接收到的数据
if(received == 'R') {
// 远程开锁命令
sys_data.state = SYS_UNLOCK;
}
}
}
七、系统测试
7.1 测试方案
/* 系统测试程序 */
void System_Test(void) {
unsigned char test_result = 1;
// 1. LCD显示测试
LCD_ShowString(0, 0, "LCD Test Start");
DelayMs(1000);
// 2. 键盘扫描测试
LCD_ShowString(1, 0, "Key Test...");
// 等待按键输入
// 3. EEPROM读写测试
AT24C02_WriteByte(0xFF, 0x55);
if(AT24C02_ReadByte(0xFF) != 0x55) {
test_result = 0;
}
// 4. 蜂鸣器测试
BEEP = 0;
DelayMs(500);
BEEP = 1;
// 5. LED测试
LED_GREEN = 0;
LED_RED = 0;
LED_BLUE = 0;
DelayMs(500);
LED_GREEN = 1;
LED_RED = 1;
LED_BLUE = 1;
// 6. 继电器测试
LOCK = 0;
DelayMs(500);
LOCK = 1;
// 测试结果
if(test_result) {
LCD_ShowString(0, 0, "Test Passed!");
} else {
LCD_ShowString(0, 0, "Test Failed!");
}
}
八、总结
基于STC单片机的电子密码锁系统实现了以下功能:
核心功能:
- 密码输入验证:6位数字密码,支持确认和清除功能
- EEPROM存储:密码断电不丢失,支持修改密码
- 防暴力破解:连续输错3次锁定30秒
- 状态指示:LED和蜂鸣器提供操作反馈
- LCD显示:实时显示系统状态和输入提示
技术亮点:
- 矩阵键盘扫描:4×4键盘,16个按键功能齐全
- I²C EEPROM驱动:AT24C02稳定存储密码数据
- 状态机设计:清晰的系统状态转换逻辑
- 定时中断:精确的系统节拍和蜂鸣器控制
- 低功耗设计:待机状态下最小化功耗
扩展功能:
- 串口远程控制:通过串口实现远程开锁
- 报警功能:防拆报警和超时报警
- 多用户管理:支持多个用户密码
- 临时密码:生成一次性临时密码
- 记录功能:存储开锁记录到EEPROM
应用场景:
- 家庭门锁:住宅门禁系统
- 办公室锁具:办公场所门禁
- 储物柜锁:商场储物柜、健身房储物柜
- 设备机箱:电子设备防盗锁
- 教室门锁:学校教室、实验室门禁