一、系统架构设计
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
重要说明:
-
硬件连接:
- 指纹模块:UART2 (PA2-TX, PA3-RX)
- OLED:I2C1 (PB6-SCL, PB7-SDA)
- 键盘:GPIO端口扫描
- 继电器:PC13
- EEPROM:I2C1 (与OLED共用)
-
功能特性:
- 指纹+密码双验证
- 管理员模式管理用户
- 开锁记录存储
- 防撬报警
- 低功耗模式
-
扩展建议:
- 添加蓝牙/WIFI模块
- 增加RFID/NFC功能
- 添加实时时钟
- 实现远程开锁