基于STC单片机的电子密码锁设计

基于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单片机的电子密码锁系统实现了以下功能:

核心功能:

  1. 密码输入验证:6位数字密码,支持确认和清除功能
  2. EEPROM存储:密码断电不丢失,支持修改密码
  3. 防暴力破解:连续输错3次锁定30秒
  4. 状态指示:LED和蜂鸣器提供操作反馈
  5. LCD显示:实时显示系统状态和输入提示

技术亮点:

  1. 矩阵键盘扫描:4×4键盘,16个按键功能齐全
  2. I²C EEPROM驱动:AT24C02稳定存储密码数据
  3. 状态机设计:清晰的系统状态转换逻辑
  4. 定时中断:精确的系统节拍和蜂鸣器控制
  5. 低功耗设计:待机状态下最小化功耗

扩展功能:

应用场景:

专注于matlab/simulink,电子电路,编程