STM32指纹密码锁的程序

一、系统架构设计

c 复制代码
// 硬件配置
// 1. STM32F103C8T6
// 2. AS608指纹模块
// 3. 矩阵键盘
// 4. OLED显示屏
// 5. 电磁锁继电器
// 6. EEPROM存储

二、主程序框架

c 复制代码
// main.c
#include "stm32f1xx_hal.h"
#include "fingerprint.h"
#include "keypad.h"
#include "oled.h"
#include "lock.h"
#include "eeprom.h"

typedef enum {
    MODE_NORMAL,      // 正常模式
    MODE_ADMIN,       // 管理员模式
    MODE_ENROLL,      // 录入模式
    MODE_DELETE       // 删除模式
} SystemMode;

SystemMode current_mode = MODE_NORMAL;

int main(void) {
    HAL_Init();
    SystemClock_Config();
    
    // 外设初始化
    UART2_Init();      // 指纹模块串口
    UART1_Init();      // 调试串口
    Keypad_Init();
    OLED_Init();
    Lock_Init();
    EEPROM_Init();
    
    // 欢迎界面
    OLED_ShowString(0, 0, "Finger Lock v1.0");
    HAL_Delay(1000);
    
    while (1) {
        switch (current_mode) {
            case MODE_NORMAL:
                NormalMode_Process();
                break;
            case MODE_ADMIN:
                AdminMode_Process();
                break;
            case MODE_ENROLL:
                EnrollMode_Process();
                break;
            case MODE_DELETE:
                DeleteMode_Process();
                break;
        }
        
        // 低功耗处理
        if (!CheckUserActivity()) {
            EnterSleepMode();
        }
    }
}

三、指纹模块驱动

c 复制代码
// fingerprint.h
#ifndef __FINGERPRINT_H
#define __FINGERPRINT_H

#define FP_ADDRESS        0xFFFFFFFF
#define FP_PASSWORD       0x00000000

// 指令定义
#define CMD_GET_IMAGE     0x01
#define CMD_GEN_CHAR      0x02
#define CMD_MATCH         0x03
#define CMD_SEARCH        0x04
#define CMD_REG_MODEL     0x05
#define CMD_STORE         0x06
#define CMD_LOAD_CHAR     0x07
#define CMD_UP_IMAGE      0x0A
#define CMD_DOWN_IMAGE    0x0B
#define CMD_DEL_CHAR      0x0C
#define CMD_EMPTY         0x0D
#define CMD_READ_INFO     0x1F

typedef struct {
    uint8_t header[2];      // 固定头
    uint8_t addr[4];        // 模块地址
    uint8_t type;           // 包标识
    uint8_t length[2];      // 包长度
    uint8_t data[256];      // 数据
    uint8_t checksum[2];    // 校验和
} FP_Packet;

uint8_t FP_VerifyPassword(void);
uint8_t FP_GetImage(void);
uint8_t FP_GenChar(uint8_t bufferID);
uint8_t FP_SearchFinger(uint8_t bufferID, uint16_t startPage, uint16_t pageNum);
uint8_t FP_RegModel(void);
uint8_t FP_StoreFinger(uint8_t bufferID, uint16_t pageID);
uint8_t FP_DeleteFinger(uint16_t pageID, uint16_t num);
uint16_t FP_GetEmptyID(void);
uint8_t FP_EnrollFinger(uint16_t id);

#endif
c 复制代码
// fingerprint.c
#include "fingerprint.h"
#include "uart.h"
#include "string.h"

// 发送指纹指令
uint8_t FP_SendCmd(uint8_t cmd, uint8_t *param, uint8_t param_len) {
    FP_Packet packet;
    uint16_t checksum = 0;
    uint8_t i;
    
    // 构造数据包
    packet.header[0] = 0xEF;
    packet.header[1] = 0x01;
    
    memcpy(packet.addr, &FP_ADDRESS, 4);
    packet.type = cmd;
    
    packet.length[0] = (param_len + 2) >> 8;
    packet.length[1] = (param_len + 2) & 0xFF;
    
    if (param_len > 0) {
        memcpy(packet.data, param, param_len);
    }
    
    // 计算校验和
    checksum = packet.type + packet.length[0] + packet.length[1];
    for (i = 0; i < param_len; i++) {
        checksum += packet.data[i];
    }
    
    packet.checksum[0] = checksum >> 8;
    packet.checksum[1] = checksum & 0xFF;
    
    // 发送数据
    UART_SendData((uint8_t*)&packet, 6 + param_len + 2);
    
    return 0;
}

// 录入指纹
uint8_t FP_EnrollFinger(uint16_t id) {
    uint8_t ret;
    
    OLED_Clear();
    OLED_ShowString(0, 0, "Place finger");
    
    // 第一次采集
    do {
        ret = FP_GetImage();
        if (ret != 0x00) {
            OLED_ShowString(0, 2, "GetImg1 Fail");
            return ret;
        }
        ret = FP_GenChar(0x01);
    } while (ret != 0x00);
    
    OLED_ShowString(0, 2, "Remove finger");
    HAL_Delay(1000);
    
    // 第二次采集
    OLED_ShowString(0, 0, "Place again");
    do {
        ret = FP_GetImage();
        if (ret != 0x00) {
            OLED_ShowString(0, 2, "GetImg2 Fail");
            return ret;
        }
        ret = FP_GenChar(0x02);
    } while (ret != 0x00);
    
    // 生成模板
    ret = FP_RegModel();
    if (ret != 0x00) {
        OLED_ShowString(0, 2, "Gen Model Fail");
        return ret;
    }
    
    // 存储模板
    ret = FP_StoreFinger(0x01, id);
    if (ret != 0x00) {
        OLED_ShowString(0, 2, "Store Fail");
        return ret;
    }
    
    OLED_ShowString(0, 2, "Enroll Success");
    return 0x00;
}

四、键盘处理模块

c 复制代码
// keypad.c
#include "keypad.h"

#define KEY_ENTER   0x0D
#define KEY_CANCEL  0x0C
#define KEY_ADMIN   0x0B
#define PASSWORD_LEN 6

char input_buffer[20];
uint8_t input_index = 0;
uint32_t admin_code = 123456;  // 默认管理员密码

uint8_t GetKey(void) {
    // 矩阵键盘扫描代码
    // 返回按键值
}

void Keypad_Process(void) {
    uint8_t key = GetKey();
    
    if (key == 0xFF) return;  // 无按键
    
    switch (current_mode) {
        case MODE_NORMAL:
            if (key <= 9) {  // 数字键
                if (input_index < PASSWORD_LEN) {
                    input_buffer[input_index++] = '0' + key;
                    OLED_ShowChar(input_index, 2, '*');
                }
            } 
            else if (key == KEY_ENTER) {
                if (input_index == PASSWORD_LEN) {
                    VerifyPassword();
                }
                input_index = 0;
                memset(input_buffer, 0, sizeof(input_buffer));
            }
            else if (key == KEY_ADMIN) {
                // 进入管理员模式
                current_mode = MODE_ADMIN;
                OLED_Clear();
                OLED_ShowString(0, 0, "Admin Mode");
            }
            break;
            
        case MODE_ADMIN:
            // 管理员模式按键处理
            break;
    }
}

五、锁控制模块

c 复制代码
// lock.c
#include "lock.h"

// 继电器控制
void Lock_Open(void) {
    HAL_GPIO_WritePin(LOCK_GPIO_Port, LOCK_Pin, GPIO_PIN_SET);
    OLED_ShowString(0, 3, "Door Open");
    HAL_Delay(3000);  // 开门3秒
    
    HAL_GPIO_WritePin(LOCK_GPIO_Port, LOCK_Pin, GPIO_PIN_RESET);
    OLED_ShowString(0, 3, "Door Locked");
}

void Lock_Alarm(void) {
    // 报警处理
    for (int i = 0; i < 5; i++) {
        HAL_GPIO_TogglePin(BUZZER_GPIO_Port, BUZZER_Pin);
        HAL_Delay(200);
    }
}

六、EEPROM存储管理

c 复制代码
// eeprom.c
#include "eeprom.h"

#define EEPROM_ADDR_FINGER_COUNT  0x0000
#define EEPROM_ADDR_FINGER_LIST   0x0010
#define EEPROM_ADDR_PASSWORD      0x0100
#define EEPROM_ADDR_ADMIN_CODE    0x0200

// 存储指纹信息
typedef struct {
    uint16_t id;
    uint8_t  valid;
    uint32_t timestamp;
} FingerInfo;

void SaveFingerInfo(FingerInfo *info) {
    uint16_t addr = EEPROM_ADDR_FINGER_LIST + info->id * sizeof(FingerInfo);
    HAL_I2C_Mem_Write(&hi2c1, 0xA0, addr, I2C_MEMADD_SIZE_16BIT,
                     (uint8_t*)info, sizeof(FingerInfo), 100);
}

uint8_t LoadFingerInfo(uint16_t id, FingerInfo *info) {
    uint16_t addr = EEPROM_ADDR_FINGER_LIST + id * sizeof(FingerInfo);
    return HAL_I2C_Mem_Read(&hi2c1, 0xA0, addr, I2C_MEMADD_SIZE_16BIT,
                           (uint8_t*)info, sizeof(FingerInfo), 100);
}

参考代码 stm32指纹密码锁程序 www.youwenfan.com/contentcsu/70268.html

七、完整工作流程示例

c 复制代码
// 正常模式处理
void NormalMode_Process(void) {
    static uint8_t error_count = 0;
    
    // 1. 显示状态
    OLED_ShowString(0, 0, "1.Finger 2.Pwd");
    
    // 2. 检查指纹
    if (FP_CheckFinger()) {
        uint16_t finger_id;
        if (FP_VerifyFinger(&finger_id) == FP_OK) {
            OLED_ShowString(0, 2, "Finger OK");
            LogAccess(finger_id, 1);  // 记录指纹开锁
            Lock_Open();
            error_count = 0;
            return;
        }
    }
    
    // 3. 处理键盘输入
    Keypad_Process();
    
    // 4. 密码验证
    if (input_index == PASSWORD_LEN) {
        if (VerifyPassword(input_buffer)) {
            OLED_ShowString(0, 2, "Password OK");
            LogAccess(0, 0);  // 记录密码开锁
            Lock_Open();
            error_count = 0;
        } else {
            error_count++;
            OLED_ShowString(0, 2, "Wrong Password");
            if (error_count >= 3) {
                Lock_Alarm();
                error_count = 0;
            }
        }
        input_index = 0;
    }
}

八、Makefile示例

makefile 复制代码
TARGET = Fingerprint_Lock
MCU = STM32F103C8T6

CC = arm-none-eabi-gcc
OBJCOPY = arm-none-eabi-objcopy

CFLAGS = -mcpu=cortex-m3 -mthumb -Wall -O2
LDFLAGS = -TSTM32F103C8.ld -nostartfiles

SRCS = main.c system_stm32f1xx.c startup_stm32f103xb.s \
       fingerprint.c keypad.c oled.c lock.c eeprom.c \
       stm32f1xx_hal_uart.c stm32f1xx_hal_gpio.c \
       stm32f1xx_hal_i2c.c stm32f1xx_hal.c

OBJS = $(SRCS:.c=.o)

all: $(TARGET).bin

$(TARGET).bin: $(TARGET).elf
	$(OBJCOPY) -O binary $< $@

$(TARGET).elf: $(OBJS)
	$(CC) $(LDFLAGS) -o $@ $^

clean:
	rm -f *.o *.elf *.bin

重要说明:

  1. 硬件连接

    • 指纹模块:UART2 (PA2-TX, PA3-RX)
    • OLED:I2C1 (PB6-SCL, PB7-SDA)
    • 键盘:GPIO端口扫描
    • 继电器:PC13
    • EEPROM:I2C1 (与OLED共用)
  2. 功能特性

    • 指纹+密码双验证
    • 管理员模式管理用户
    • 开锁记录存储
    • 防撬报警
    • 低功耗模式
  3. 扩展建议

    • 添加蓝牙/WIFI模块
    • 增加RFID/NFC功能
    • 添加实时时钟
    • 实现远程开锁
相关推荐
Achou.Wang1 小时前
从 Atomic 到 Futex:深入解析并发同步的三重境界
单片机·嵌入式硬件
不怕犯错,就怕不做1 小时前
linux的notifier_block内核通知链
linux·驱动开发·嵌入式硬件
时空自由民.2 小时前
Arm Coretex-M核MCU做IAP/OTA升级时候为什么要做中断向量表地址偏移?
arm开发·单片机·嵌入式硬件
不脱发的程序猿2 小时前
MCU升级固件合并和转换工具
单片机·嵌入式硬件
qq_370773092 小时前
OpenOCD 嵌入式调试完全指南:从零开始调试 GD32/STM32 单片机
stm32·单片机·嵌入式硬件·openocd
LCG元2 小时前
STM32实战:基于STM32F103的迷迭香智慧种植系统(自动补光+滴灌)
stm32·单片机·嵌入式硬件
SDAU200511 小时前
CH32V103C8T6的时钟操作
单片机·嵌入式硬件
不做无法实现的梦~12 小时前
SBUS 接收机到 STM32:为什么要做硬件反相、如何解析数据、如何接线与实现代码
stm32·单片机·嵌入式硬件
一路往蓝-Anbo12 小时前
第二章:隔离硬件 —— 利用 CMock 伪造 GPIO 与定时器
stm32·单片机·嵌入式硬件·软件工程·信息与通信·tdd