CMS8S5880 电子锁程序(51单片机)

一、硬件连接设计

1.1 引脚分配表

模块 引脚 说明
矩阵键盘 P1.0-P1.7 4×4矩阵键盘
继电器控制 P2.0 电磁锁驱动
蜂鸣器 P2.1 报警提示
LED指示灯 P2.2-P2.4 状态指示
LCD1602 P0.0-P0.7 数据线
LCD RS P2.5 寄存器选择
LCD RW P2.6 读写控制
LCD EN P2.7 使能信号
EEPROM P3.4/P3.5 I2C接口
备用电源 P3.0 电源检测

1.2 系统框图

复制代码
┌─────────────────────────────────────┐
│            CMS8S5880               │
│  ┌─────────────┐  ┌─────────────┐  │
│  │  矩阵键盘   │  │  继电器驱动  │  │
│  │  4×4输入    │  │  电磁锁控制  │  │
│  └─────────────┘  └─────────────┘  │
│  ┌─────────────┐  ┌─────────────┐  │
│  │  LCD1602显示 │  │  蜂鸣器报警  │  │
│  │  状态提示   │  │  错误提示    │  │
│  └─────────────┘  └─────────────┘  │
│  ┌─────────────┐  ┌─────────────┐  │
│  │  EEPROM存储  │  │  LED状态灯  │  │
│  │  密码保存    │  │  工作指示    │  │
│  └─────────────┘  └─────────────┘  │
└─────────────────────────────────────┘

二、完整程序代码

2.1 主程序 (main.c)

c 复制代码
/***********************************************************
* 文件名:ElectronicLock.c
* 功能:CMS8S5880电子锁主程序
* 硬件:CMS8S5880 + 4×4矩阵键盘 + LCD1602 + 继电器
***********************************************************/

#include "main.h"
#include "keyboard.h"
#include "lcd1602.h"
#include "eeprom.h"
#include "relay.h"
#include "beep.h"
#include "led.h"

/* 系统参数 */
#define PASSWORD_LENGTH 6        // 密码长度
#define MAX_TRY_TIMES 3          // 最大尝试次数
#define LOCK_TIME 30000          // 锁定时间30秒
#define ADMIN_PASSWORD_ADDR 0x00 // 管理员密码存储地址
#define USER_PASSWORD_ADDR 0x10  // 用户密码存储地址

/* 全局变量 */
volatile uint8_t system_state = STATE_NORMAL;
volatile uint8_t input_index = 0;
volatile uint8_t try_times = 0;
volatile uint32_t lock_timer = 0;
uint8_t input_password[PASSWORD_LENGTH];
uint8_t stored_password[PASSWORD_LENGTH];

/* 函数声明 */
void System_Init(void);
void State_Machine(void);
void Input_Password(void);
void Verify_Password(void);
void Unlock_Success(void);
void Lock_System(void);
void Change_Password(void);
void Display_State(void);

/***********************************************************
* 主函数
***********************************************************/
void main(void)
{
    /* 系统初始化 */
    System_Init();
    
    /* 显示欢迎界面 */
    LCD_ShowString(0, 0, "Electronic Lock");
    LCD_ShowString(0, 1, "Initializing...");
    Delay_ms(2000);
    
    /* 读取存储的密码 */
    EEPROM_Read(USER_PASSWORD_ADDR, stored_password, PASSWORD_LENGTH);
    
    /* 主循环 */
    while(1)
    {
        /* 状态机处理 */
        State_Machine();
        
        /* 键盘扫描 */
        Keyboard_Scan();
        
        /* 显示更新 */
        Display_State();
        
        /* 延时 */
        Delay_ms(10);
    }
}

/***********************************************************
* 系统初始化
***********************************************************/
void System_Init(void)
{
    /* IO口初始化 */
    P0M0 = 0x00; P0M1 = 0x00;  // P0准双向
    P1M0 = 0x00; P1M1 = 0x00;  // P1准双向
    P2M0 = 0x00; P2M1 = 0x00;  // P2准双向
    P3M0 = 0x00; P3M1 = 0x00;  // P3准双向
    
    /* 外设初始化 */
    LCD_Init();
    Keyboard_Init();
    Relay_Init();
    Beep_Init();
    LED_Init();
    EEPROM_Init();
    
    /* 定时器初始化 */
    Timer0_Init();
    
    /* 开中断 */
    EA = 1;
}

/***********************************************************
* 状态机处理
***********************************************************/
void State_Machine(void)
{
    static uint8_t last_state = 0xFF;
    
    switch(system_state)
    {
        case STATE_NORMAL:
            /* 正常工作状态 */
            if(last_state != STATE_NORMAL)
            {
                LED_Set(LED_GREEN, LED_ON);
                LED_Set(LED_RED, LED_OFF);
                LCD_Clear();
                LCD_ShowString(0, 0, "Enter Password:");
                LCD_ShowString(0, 1, "Press # to confirm");
                input_index = 0;
                memset(input_password, 0, PASSWORD_LENGTH);
            }
            break;
            
        case STATE_INPUT:
            /* 密码输入状态 */
            Input_Password();
            break;
            
        case STATE_VERIFY:
            /* 密码验证状态 */
            Verify_Password();
            break;
            
        case STATE_UNLOCK:
            /* 解锁状态 */
            Unlock_Success();
            break;
            
        case STATE_LOCKED:
            /* 系统锁定状态 */
            Lock_System();
            break;
            
        case STATE_CHANGE_PWD:
            /* 修改密码状态 */
            Change_Password();
            break;
            
        default:
            system_state = STATE_NORMAL;
            break;
    }
    
    last_state = system_state;
}

/***********************************************************
* 密码输入处理
***********************************************************/
void Input_Password(void)
{
    uint8_t key_value;
    
    key_value = Get_Key_Value();
    
    if(key_value != NO_KEY)
    {
        Beep_Short();  // 按键提示音
        
        if(key_value >= '0' && key_value <= '9')
        {
            /* 数字键 */
            if(input_index < PASSWORD_LENGTH)
            {
                input_password[input_index] = key_value - '0';
                LCD_ShowChar(12 + input_index, 0, '*');
                input_index++;
            }
        }
        else if(key_value == '#')
        {
            /* 确认键 */
            if(input_index == PASSWORD_LENGTH)
            {
                system_state = STATE_VERIFY;
            }
            else
            {
                /* 密码长度不足 */
                LCD_ShowString(0, 1, "Incomplete Password!");
                Beep_Error();
                Delay_ms(1000);
                system_state = STATE_NORMAL;
            }
        }
        else if(key_value == '*')
        {
            /* 删除键 */
            if(input_index > 0)
            {
                input_index--;
                input_password[input_index] = 0;
                LCD_ShowChar(12 + input_index, 0, ' ');
            }
        }
        else if(key_value == 'A')
        {
            /* 管理员功能 */
            system_state = STATE_CHANGE_PWD;
        }
    }
}

/***********************************************************
* 密码验证
***********************************************************/
void Verify_Password(void)
{
    uint8_t i;
    uint8_t match = 1;
    
    /* 比较密码 */
    for(i = 0; i < PASSWORD_LENGTH; i++)
    {
        if(input_password[i] != stored_password[i])
        {
            match = 0;
            break;
        }
    }
    
    if(match)
    {
        /* 密码正确 */
        try_times = 0;
        system_state = STATE_UNLOCK;
    }
    else
    {
        /* 密码错误 */
        try_times++;
        Beep_Error();
        LED_Set(LED_RED, LED_ON);
        
        if(try_times >= MAX_TRY_TIMES)
        {
            /* 超过最大尝试次数,锁定系统 */
            system_state = STATE_LOCKED;
            lock_timer = LOCK_TIME;
        }
        else
        {
            /* 显示错误信息 */
            LCD_Clear();
            LCD_ShowString(0, 0, "Wrong Password!");
            LCD_ShowString(0, 1, "Try again:");
            LCD_ShowNumber(10, 1, MAX_TRY_TIMES - try_times, 1);
            LCD_ShowString(12, 1, "left");
            
            /* 清空输入 */
            input_index = 0;
            memset(input_password, 0, PASSWORD_LENGTH);
            system_state = STATE_NORMAL;
        }
    }
}

/***********************************************************
* 解锁成功
***********************************************************/
void Unlock_Success(void)
{
    static uint16_t unlock_time = 0;
    
    LCD_Clear();
    LCD_ShowString(0, 0, "Access Granted!");
    LCD_ShowString(0, 1, "Door Unlocked");
    
    /* 点亮绿灯,打开继电器 */
    LED_Set(LED_GREEN, LED_ON);
    LED_Set(LED_RED, LED_OFF);
    Relay_Open();
    Beep_Success();
    
    /* 延时5秒后重新锁定 */
    unlock_time++;
    if(unlock_time >= 500)  // 5秒
    {
        Relay_Close();
        unlock_time = 0;
        system_state = STATE_NORMAL;
    }
}

/***********************************************************
* 系统锁定
***********************************************************/
void Lock_System(void)
{
    static uint16_t lock_display_time = 0;
    
    LCD_Clear();
    LCD_ShowString(0, 0, "SYSTEM LOCKED!");
    LCD_ShowString(0, 1, "Wait:");
    LCD_ShowNumber(6, 1, lock_timer/1000, 2);
    LCD_ShowString(10, 1, "seconds");
    
    /* 红色LED闪烁,蜂鸣器报警 */
    if(lock_display_time % 100 == 0)
    {
        LED_Set(LED_RED, LED_ON);
        Beep_Long();
    }
    else if(lock_display_time % 100 == 50)
    {
        LED_Set(LED_RED, LED_OFF);
    }
    
    /* 倒计时 */
    if(lock_timer > 0)
    {
        lock_timer--;
    }
    else
    {
        /* 锁定时间到,恢复正常状态 */
        try_times = 0;
        system_state = STATE_NORMAL;
    }
    
    lock_display_time++;
}

/***********************************************************
* 修改密码
***********************************************************/
void Change_Password(void)
{
    static uint8_t step = 0;
    static uint8_t old_password[PASSWORD_LENGTH];
    static uint8_t new_password[PASSWORD_LENGTH];
    static uint8_t confirm_password[PASSWORD_LENGTH];
    uint8_t key_value;
    
    key_value = Get_Key_Value();
    
    switch(step)
    {
        case 0:  // 输入旧密码
            LCD_Clear();
            LCD_ShowString(0, 0, "Enter Old Pwd:");
            step = 1;
            input_index = 0;
            break;
            
        case 1:  // 等待输入旧密码
            if(key_value != NO_KEY)
            {
                if(key_value >= '0' && key_value <= '9')
                {
                    if(input_index < PASSWORD_LENGTH)
                    {
                        old_password[input_index] = key_value - '0';
                        LCD_ShowChar(12 + input_index, 0, '*');
                        input_index++;
                    }
                }
                else if(key_value == '#')
                {
                    if(input_index == PASSWORD_LENGTH)
                    {
                        /* 验证旧密码 */
                        uint8_t i, match = 1;
                        for(i = 0; i < PASSWORD_LENGTH; i++)
                        {
                            if(old_password[i] != stored_password[i])
                            {
                                match = 0;
                                break;
                            }
                        }
                        
                        if(match)
                        {
                            step = 2;
                            input_index = 0;
                        }
                        else
                        {
                            LCD_ShowString(0, 1, "Wrong Old Pwd!");
                            Beep_Error();
                            Delay_ms(1000);
                            step = 0;
                        }
                    }
                }
            }
            break;
            
        case 2:  // 输入新密码
            LCD_Clear();
            LCD_ShowString(0, 0, "Enter New Pwd:");
            step = 3;
            input_index = 0;
            break;
            
        case 3:  // 等待输入新密码
            if(key_value != NO_KEY)
            {
                if(key_value >= '0' && key_value <= '9')
                {
                    if(input_index < PASSWORD_LENGTH)
                    {
                        new_password[input_index] = key_value - '0';
                        LCD_ShowChar(12 + input_index, 0, '*');
                        input_index++;
                    }
                }
                else if(key_value == '#')
                {
                    if(input_index == PASSWORD_LENGTH)
                    {
                        step = 4;
                        input_index = 0;
                    }
                }
            }
            break;
            
        case 4:  // 确认新密码
            LCD_Clear();
            LCD_ShowString(0, 0, "Confirm New Pwd:");
            step = 5;
            input_index = 0;
            break;
            
        case 5:  // 等待确认密码
            if(key_value != NO_KEY)
            {
                if(key_value >= '0' && key_value <= '9')
                {
                    if(input_index < PASSWORD_LENGTH)
                    {
                        confirm_password[input_index] = key_value - '0';
                        LCD_ShowChar(12 + input_index, 0, '*');
                        input_index++;
                    }
                }
                else if(key_value == '#')
                {
                    if(input_index == PASSWORD_LENGTH)
                    {
                        /* 比较两次密码 */
                        uint8_t i, match = 1;
                        for(i = 0; i < PASSWORD_LENGTH; i++)
                        {
                            if(new_password[i] != confirm_password[i])
                            {
                                match = 0;
                                break;
                            }
                        }
                        
                        if(match)
                        {
                            /* 保存新密码到EEPROM */
                            EEPROM_Write(USER_PASSWORD_ADDR, new_password, PASSWORD_LENGTH);
                            memcpy(stored_password, new_password, PASSWORD_LENGTH);
                            
                            LCD_ShowString(0, 1, "Password Changed!");
                            Beep_Success();
                            Delay_ms(2000);
                            system_state = STATE_NORMAL;
                        }
                        else
                        {
                            LCD_ShowString(0, 1, "Password Mismatch!");
                            Beep_Error();
                            Delay_ms(1000);
                            step = 2;  // 重新输入新密码
                        }
                    }
                }
            }
            break;
    }
}

/***********************************************************
* 显示系统状态
***********************************************************/
void Display_State(void)
{
    static uint8_t display_counter = 0;
    
    if(display_counter % 100 == 0)
    {
        switch(system_state)
        {
            case STATE_NORMAL:
                LED_Set(LED_GREEN, LED_ON);
                LED_Set(LED_RED, LED_OFF);
                break;
            case STATE_INPUT:
                LED_Set(LED_GREEN, LED_BLINK);
                LED_Set(LED_RED, LED_OFF);
                break;
            case STATE_VERIFY:
                LED_Set(LED_GREEN, LED_ON);
                LED_Set(LED_RED, LED_ON);
                break;
            case STATE_UNLOCK:
                LED_Set(LED_GREEN, LED_ON);
                LED_Set(LED_RED, LED_OFF);
                break;
            case STATE_LOCKED:
                LED_Set(LED_GREEN, LED_OFF);
                LED_Set(LED_RED, LED_BLINK);
                break;
            case STATE_CHANGE_PWD:
                LED_Set(LED_GREEN, LED_ON);
                LED_Set(LED_RED, LED_ON);
                break;
        }
    }
    
    display_counter++;
}

/***********************************************************
* 定时器0中断服务程序
***********************************************************/
void Timer0_ISR(void) interrupt 1
{
    static uint16_t beep_counter = 0;
    static uint16_t led_counter = 0;
    
    /* 蜂鸣器控制 */
    if(beep_counter > 0)
    {
        beep_counter--;
        BEEP = 1;
    }
    else
    {
        BEEP = 0;
    }
    
    /* LED闪烁控制 */
    if(led_counter % 500 == 0)
    {
        LED_GREEN = ~LED_GREEN;
    }
    
    led_counter++;
}

2.2 头文件 (main.h)

c 复制代码
#ifndef __MAIN_H
#define __MAIN_H

#include <reg52.h>
#include <intrins.h>

/* 系统状态定义 */
#define STATE_NORMAL     0
#define STATE_INPUT      1
#define STATE_VERIFY     2
#define STATE_UNLOCK     3
#define STATE_LOCKED     4
#define STATE_CHANGE_PWD 5

/* 按键定义 */
#define NO_KEY          0xFF
#define KEY_0           '0'
#define KEY_1           '1'
#define KEY_2           '2'
#define KEY_3           '3'
#define KEY_4           '4'
#define KEY_5           '5'
#define KEY_6           '6'
#define KEY_7           '7'
#define KEY_8           '8'
#define KEY_9           '9'
#define KEY_CONFIRM     '#'
#define KEY_DELETE      '*'
#define KEY_ADMIN       'A'

/* LED状态 */
#define LED_ON          0
#define LED_OFF         1
#define LED_BLINK       2

/* 硬件引脚定义 */
sbit RELAY = P2^0;     // 继电器控制
sbit BEEP = P2^1;      // 蜂鸣器
sbit LED_GREEN = P2^2; // 绿色LED
sbit LED_RED = P2^3;   // 红色LED
sbit LED_BLUE = P2^4;  // 蓝色LED

/* LCD引脚定义 */
sbit LCD_RS = P2^5;
sbit LCD_RW = P2^6;
sbit LCD_EN = P2^7;

/* EEPROM引脚定义 */
sbit EEPROM_SDA = P3^4;
sbit EEPROM_SCL = P3^5;

/* 函数声明 */
void Delay_ms(unsigned int ms);
void Delay_us(unsigned int us);

#endif

2.3 矩阵键盘驱动 (keyboard.c)

c 复制代码
/***********************************************************
* 文件名:keyboard.c
* 功能:4×4矩阵键盘驱动
***********************************************************/

#include "keyboard.h"

/* 键盘映射表 */
unsigned char code KeyMap[4][4] = {
    {'1', '2', '3', KEY_DELETE},
    {'4', '5', '6', KEY_ADMIN},
    {'7', '8', '9', KEY_CONFIRM},
    {'*', '0', '#', 'B'}
};

/***********************************************************
* 键盘初始化
***********************************************************/
void Keyboard_Init(void)
{
    /* P1口设置为准双向模式 */
    P1M0 = 0x00;
    P1M1 = 0x00;
}

/***********************************************************
* 扫描键盘
***********************************************************/
unsigned char Keyboard_Scan(void)
{
    unsigned char i, j;
    unsigned char key_value = NO_KEY;
    
    /* 扫描行 */
    for(i = 0; i < 4; i++)
    {
        P1 = ~(0x01 << i);  // 设置第i行为低电平
        
        /* 短暂延时 */
        Delay_us(10);
        
        /* 读取列状态 */
        for(j = 0; j < 4; j++)
        {
            if((P1 & (0x10 << j)) == 0)  // 第j列为低电平
            {
                key_value = KeyMap[i][j];
                /* 等待按键释放 */
                while((P1 & (0x10 << j)) == 0);
                return key_value;
            }
        }
    }
    
    return NO_KEY;
}

/***********************************************************
* 获取键值(带消抖)
***********************************************************/
unsigned char Get_Key_Value(void)
{
    static unsigned char last_key = NO_KEY;
    static unsigned char debounce_count = 0;
    unsigned char current_key;
    
    current_key = Keyboard_Scan();
    
    if(current_key == last_key)
    {
        if(debounce_count < 255)
            debounce_count++;
    }
    else
    {
        debounce_count = 0;
        last_key = current_key;
    }
    
    if(debounce_count >= 3)  // 消抖3次
    {
        return current_key;
    }
    
    return NO_KEY;
}

2.4 LCD1602驱动 (lcd1602.c)

c 复制代码
/***********************************************************
* 文件名:lcd1602.c
* 功能:LCD1602液晶显示驱动
***********************************************************/

#include "lcd1602.h"

/***********************************************************
* 延时函数
***********************************************************/
void LCD_Delay(unsigned int t)
{
    unsigned int i, j;
    for(i = 0; i < t; i++)
        for(j = 0; j < 120; j++);
}

/***********************************************************
* 写命令
***********************************************************/
void LCD_WriteCmd(unsigned char cmd)
{
    LCD_RS = 0;
    LCD_RW = 0;
    P0 = cmd;
    LCD_EN = 1;
    LCD_Delay(5);
    LCD_EN = 0;
}

/***********************************************************
* 写数据
***********************************************************/
void LCD_WriteData(unsigned char dat)
{
    LCD_RS = 1;
    LCD_RW = 0;
    P0 = dat;
    LCD_EN = 1;
    LCD_Delay(5);
    LCD_EN = 0;
}

/***********************************************************
* 初始化LCD
***********************************************************/
void LCD_Init(void)
{
    LCD_Delay(15000);
    LCD_WriteCmd(0x38);  // 8位数据,2行显示,5×7点阵
    LCD_Delay(5000);
    LCD_WriteCmd(0x38);
    LCD_Delay(5000);
    LCD_WriteCmd(0x38);
    LCD_WriteCmd(0x0C);  // 显示开,光标关
    LCD_WriteCmd(0x06);  // 地址递增
    LCD_WriteCmd(0x01);  // 清屏
    LCD_Delay(2000);
}

/***********************************************************
* 清屏
***********************************************************/
void LCD_Clear(void)
{
    LCD_WriteCmd(0x01);
    LCD_Delay(2000);
}

/***********************************************************
* 设置显示位置
***********************************************************/
void LCD_SetCursor(unsigned char x, unsigned char y)
{
    unsigned char addr;
    
    if(y == 0)
        addr = 0x80 + x;
    else
        addr = 0xC0 + x;
    
    LCD_WriteCmd(addr);
}

/***********************************************************
* 显示字符
***********************************************************/
void LCD_ShowChar(unsigned char x, unsigned char y, unsigned char ch)
{
    LCD_SetCursor(x, y);
    LCD_WriteData(ch);
}

/***********************************************************
* 显示字符串
***********************************************************/
void LCD_ShowString(unsigned char x, unsigned char y, unsigned char *str)
{
    LCD_SetCursor(x, y);
    while(*str)
    {
        LCD_WriteData(*str);
        str++;
    }
}

/***********************************************************
* 显示数字
***********************************************************/
void LCD_ShowNumber(unsigned char x, unsigned char y, unsigned int num, unsigned char len)
{
    unsigned char i;
    unsigned char temp[5];
    
    for(i = 0; i < len; i++)
    {
        temp[i] = num % 10 + '0';
        num /= 10;
    }
    
    LCD_SetCursor(x, y);
    for(i = len; i > 0; i--)
    {
        LCD_WriteData(temp[i-1]);
    }
}

2.5 EEPROM驱动 (eeprom.c)

c 复制代码
/***********************************************************
* 文件名:eeprom.c
* 功能:24C02 EEPROM驱动
***********************************************************/

#include "eeprom.h"

/***********************************************************
* I2C起始信号
***********************************************************/
void I2C_Start(void)
{
    EEPROM_SDA = 1;
    EEPROM_SCL = 1;
    Delay_us(5);
    EEPROM_SDA = 0;
    Delay_us(5);
    EEPROM_SCL = 0;
}

/***********************************************************
* I2C停止信号
***********************************************************/
void I2C_Stop(void)
{
    EEPROM_SDA = 0;
    EEPROM_SCL = 1;
    Delay_us(5);
    EEPROM_SDA = 1;
    Delay_us(5);
}

/***********************************************************
* I2C应答
***********************************************************/
void I2C_Ack(void)
{
    EEPROM_SDA = 0;
    EEPROM_SCL = 1;
    Delay_us(5);
    EEPROM_SCL = 0;
}

/***********************************************************
* I2C非应答
***********************************************************/
void I2C_NoAck(void)
{
    EEPROM_SDA = 1;
    EEPROM_SCL = 1;
    Delay_us(5);
    EEPROM_SCL = 0;
}

/***********************************************************
* I2C等待应答
***********************************************************/
bit I2C_WaitAck(void)
{
    bit ack;
    
    EEPROM_SDA = 1;
    EEPROM_SCL = 1;
    Delay_us(5);
    ack = EEPROM_SDA;
    EEPROM_SCL = 0;
    
    return ack;
}

/***********************************************************
* 写字节
***********************************************************/
void I2C_WriteByte(unsigned char dat)
{
    unsigned char i;
    
    for(i = 0; i < 8; i++)
    {
        EEPROM_SDA = (dat & 0x80) >> 7;
        EEPROM_SCL = 1;
        Delay_us(5);
        EEPROM_SCL = 0;
        dat <<= 1;
    }
}

/***********************************************************
* 读字节
***********************************************************/
unsigned char I2C_ReadByte(void)
{
    unsigned char i, dat = 0;
    
    EEPROM_SDA = 1;
    for(i = 0; i < 8; i++)
    {
        EEPROM_SCL = 1;
        Delay_us(5);
        dat <<= 1;
        dat |= EEPROM_SDA;
        EEPROM_SCL = 0;
        Delay_us(5);
    }
    
    return dat;
}

/***********************************************************
* 写EEPROM
***********************************************************/
void EEPROM_Write(unsigned char addr, unsigned char *buf, unsigned char len)
{
    unsigned char i;
    
    I2C_Start();
    I2C_WriteByte(0xA0);  // 24C02写地址
    I2C_WaitAck();
    I2C_WriteByte(addr);
    I2C_WaitAck();
    
    for(i = 0; i < len; i++)
    {
        I2C_WriteByte(buf[i]);
        I2C_WaitAck();
        Delay_ms(5);  // 等待写入完成
    }
    
    I2C_Stop();
}

/***********************************************************
* 读EEPROM
***********************************************************/
void EEPROM_Read(unsigned char addr, unsigned char *buf, unsigned char len)
{
    unsigned char i;
    
    I2C_Start();
    I2C_WriteByte(0xA0);  // 24C02写地址
    I2C_WaitAck();
    I2C_WriteByte(addr);
    I2C_WaitAck();
    
    I2C_Start();
    I2C_WriteByte(0xA1);  // 24C02读地址
    I2C_WaitAck();
    
    for(i = 0; i < len-1; i++)
    {
        buf[i] = I2C_ReadByte();
        I2C_Ack();
    }
    
    buf[i] = I2C_ReadByte();
    I2C_NoAck();
    I2C_Stop();
}

2.6 继电器控制 (relay.c)

c 复制代码
/***********************************************************
* 文件名:relay.c
* 功能:继电器控制模块
***********************************************************/

#include "relay.h"

/***********************************************************
* 继电器初始化
***********************************************************/
void Relay_Init(void)
{
    RELAY = 0;  // 初始关闭
}

/***********************************************************
* 打开继电器
***********************************************************/
void Relay_Open(void)
{
    RELAY = 1;
}

/***********************************************************
* 关闭继电器
***********************************************************/
void Relay_Close(void)
{
    RELAY = 0;
}

/***********************************************************
* 继电器状态翻转
***********************************************************/
void Relay_Toggle(void)
{
    RELAY = ~RELAY;
}

2.7 蜂鸣器控制 (beep.c)

c 复制代码
/***********************************************************
* 文件名:beep.c
* 功能:蜂鸣器控制模块
***********************************************************/

#include "beep.h"

/***********************************************************
* 蜂鸣器初始化
***********************************************************/
void Beep_Init(void)
{
    BEEP = 0;  // 关闭蜂鸣器
}

/***********************************************************
* 短响提示
***********************************************************/
void Beep_Short(void)
{
    BEEP = 1;
    Delay_ms(100);
    BEEP = 0;
}

/***********************************************************
* 长响提示
***********************************************************/
void Beep_Long(void)
{
    BEEP = 1;
    Delay_ms(500);
    BEEP = 0;
}

/***********************************************************
* 错误提示
***********************************************************/
void Beep_Error(void)
{
    unsigned char i;
    for(i = 0; i < 3; i++)
    {
        BEEP = 1;
        Delay_ms(200);
        BEEP = 0;
        Delay_ms(200);
    }
}

/***********************************************************
* 成功提示
***********************************************************/
void Beep_Success(void)
{
    BEEP = 1;
    Delay_ms(100);
    BEEP = 0;
    Delay_ms(100);
    BEEP = 1;
    Delay_ms(100);
    BEEP = 0;
}

2.8 LED控制 (led.c)

c 复制代码
/***********************************************************
* 文件名:led.c
* 功能:LED指示灯控制
***********************************************************/

#include "led.h"

/***********************************************************
* LED初始化
***********************************************************/
void LED_Init(void)
{
    LED_GREEN = LED_OFF;
    LED_RED = LED_OFF;
    LED_BLUE = LED_OFF;
}

/***********************************************************
* 设置LED状态
***********************************************************/
void LED_Set(unsigned char led, unsigned char state)
{
    switch(led)
    {
        case LED_GREEN:
            if(state == LED_ON)
                LED_GREEN = 0;
            else if(state == LED_OFF)
                LED_GREEN = 1;
            break;
            
        case LED_RED:
            if(state == LED_ON)
                LED_RED = 0;
            else if(state == LED_OFF)
                LED_RED = 1;
            break;
            
        case LED_BLUE:
            if(state == LED_ON)
                LED_BLUE = 0;
            else if(state == LED_OFF)
                LED_BLUE = 1;
            break;
    }
}

/***********************************************************
* LED闪烁
***********************************************************/
void LED_Blink(unsigned char led, unsigned int times)
{
    unsigned int i;
    for(i = 0; i < times; i++)
    {
        LED_Set(led, LED_ON);
        Delay_ms(200);
        LED_Set(led, LED_OFF);
        Delay_ms(200);
    }
}

三、Keil工程配置

3.1 工程设置

  1. Target: CMS8S5880
  2. Code Rom Size: Large
  3. Xtal: 11.0592MHz
  4. Memory Model: Large
  5. Code Optimization: Level 8 (Favor Speed)

3.2 编译选项

复制代码
Project -> Options for Target 'Target 1':
- Target Tab:
  - Xtal (MHz): 11.0592
  - Memory Model: Large
  - Code Rom Size: Large
  
- Output Tab:
  - Create HEX File: √
  
- Listing Tab:
  - Assembly Code: √
  
- C51 Tab:
  - Code Optimization: Level 8 (Favor Speed)
  - Define: __CMS8S5880__

参考代码 电子锁程序(CMS8S5880,51单片机程序开发) www.youwenfan.com/contentcsv/115986.html

四、使用说明

4.1 首次使用设置

  1. 通电后显示"Electronic Lock"
  2. 默认密码:123456
  3. 输入密码后按#键确认

4.2 管理员功能

  1. 输入密码123456#
  2. 按A键进入管理员模式
  3. 输入旧密码确认
  4. 输入新密码两次
  5. 按#键保存

4.3 安全特性

  • 连续3次密码错误锁定30秒
  • 密码存储在EEPROM中,断电不丢失
  • 支持备用电源接口
相关推荐
振南的单片机世界3 小时前
启动流程:上电先取栈顶和复位向量,再进main
arm开发·stm32·嵌入式硬件
fanged3 小时前
设备树学习2--一个设备
嵌入式硬件
数智工坊3 小时前
【ROS 2 全栈入门指南三】:Action、参数与Launch文件全链路指南
android·stm32·嵌入式硬件·学习·机器人
Inhand陈工3 小时前
映翰通IG502实战:通过RS232采集交通信号灯数据,实现自动短信告警
网络·嵌入式硬件·物联网·网络安全·边缘计算·信息与通信·信号处理
不脱发的程序猿3 小时前
我把360里真正用得到的功能拆出来,做个轻量工具
stm32·单片机·嵌入式硬件
踏着七彩祥云的小丑4 小时前
嵌入式测试学习第 31 天:兼容性测试:版本兼容、外设兼容、硬件版本兼容
单片机·嵌入式硬件·学习
yongui478344 小时前
基于 STM32F103ZET6 的循轨避障蓝牙小车
stm32·单片机·嵌入式硬件
kebidaixu4 小时前
FreeRTOS 移植到 STM32F407VETX 记录(五)
stm32·单片机·嵌入式硬件
listhi5204 小时前
基于单片机的步进电机控制系统
单片机·嵌入式硬件