基于STM32的指纹考勤系统设计

基于STM32的指纹考勤系统设计

一、系统概述与核心功能

1. 系统定位

基于STM32的指纹考勤系统以“指纹采集-身份识别-考勤记录-数据管理”为核心,通过指纹传感器实现人员身份快速验证,结合实时时钟(RTC)记录考勤时间,支持本地存储、查询及远程数据上传,适用于企业、学校、工厂等场景的自动化考勤管理,替代传统打卡机,提升考勤效率与安全性。

2. 核心功能模块

模块 功能描述
指纹采集与识别 光学/半导体指纹传感器(如AS608)采集指纹图像,STM32通过UART发送指令实现指纹录入、存储、比对(1:N识别)
时间记录 实时时钟(RTC,如DS3231)提供精准时间(年/月/日/时/分/秒),支持断电走时(纽扣电池备份)
数据存储 存储用户指纹模板(传感器内部FLASH/外部EEPROM)及考勤记录(时间、用户ID、状态),支持SD卡扩展
用户交互 OLED/LCD显示菜单(录入/识别/查询/设置),按键操作(功能选择、确认、返回),蜂鸣器提示(成功/失败)
数据管理 本地查询考勤记录(按日期/ID),支持删除/导出;通过Wi-Fi/蓝牙上传数据至云端/手机APP
低功耗设计 待机时关闭非必要模块(显示/传感器),STM32进入STOP模式,续航≥7天(18650电池)

二、硬件设计方案

1. 核心硬件选型

模块 型号 关键参数 接口方式
主控MCU STM32F103C8T6 72MHz Cortex-M3,64KB Flash,20KB RAM,3个UART,2个I2C,支持低功耗模式 核心控制器
指纹传感器 AS608 光学指纹,500dpi分辨率,存储1000枚模板,UART接口(57600bps),支持1:N识别 UART2(PA2=TX,PA3=RX)
实时时钟 DS3231 精度±2ppm(±1分钟/年),I2C接口,内置温度补偿,纽扣电池(CR2032)备份 I2C1(PB6=SCL,PB7=SDA)
显示模块 OLED 12864(I2C) 0.96寸,128×64像素,自发光,低功耗(<10mA),显示菜单与考勤信息 I2C1(复用DS3231)
存储模块 AT24C256(EEPROM) 256Kb(32KB),I2C接口,擦写10万次,存储用户ID与考勤记录(约5000条) I2C1(复用)
按键模块 轻触按键×4 功能:菜单/确认/返回/查询,上拉输入,消抖处理 GPIO(PC0-PC3)
通信模块 ESP8266-12F(Wi-Fi) 802.11 b/g/n,UART接口,支持AT指令/透传模式,上传数据至云端(如OneNET) UART1(PA9=TX,PA10=RX)
电源模块 18650电池+TP4056+AMS1117 3.7V/2000mAh锂电池,TP4056充电(5V Micro USB),AMS1117-3.3V给MCU/传感器 供电一体化(带过充保护)
辅助模块 蜂鸣器+LED 有源蜂鸣器(5V,85dB),LED(红/绿双色),提示操作结果(成功/失败/低电量) GPIO(PB0=蜂鸣器,PB1=LED)

2. 硬件电路设计要点

2.1 核心电路连接

2.2 抗干扰设计

三、软件设计与核心代码

1. 系统架构(FreeRTOS多任务调度)

采用FreeRTOS实时操作系统,划分5个核心任务(优先级从高到低):

  1. 指纹处理任务(优先级4):通过UART与AS608通信,实现指纹录入、识别、删除。
  2. 时间管理任务(优先级3):读取DS3231时间,更新系统时钟,处理考勤时间记录。
  3. 用户交互任务(优先级2):扫描按键、更新OLED显示、蜂鸣器提示。
  4. 数据存储任务(优先级2):将考勤记录(时间、ID)写入AT24C256/SD卡。
  5. 通信任务(优先级1):通过ESP8266上传考勤数据至云端(如OneNET平台)。

2. 核心代码实现(基于HAL库)

2.1 指纹传感器驱动(AS608 UART通信)

#include "as608.h"
#include "usart.h"

// AS608指令集(部分)
#define AS608_CMD_GETIMAGE    0x01  // 采集指纹图像
#define AS608_CMD_GENCHAR     0x02  // 生成特征码
#define AS608_CMD_REGMODEL    0x05  // 合并特征码(录入)
#define AS608_CMD_STORECHAR   0x06  // 存储特征码
#define AS608_CMD_SEARCH      0x04  // 搜索指纹(1:N)
#define AS608_CMD_EMPTY       0x0D  // 清空指纹库

// 发送指令至AS608
void AS608_SendCmd(uint8_t *cmd, uint8_t len) {
  HAL_UART_Transmit(&huart2, cmd, len, 100);  // UART2发送(PA2=TX)
}

// 接收AS608响应(带校验和)
uint8_t AS608_ReceiveResp(uint8_t *resp, uint8_t max_len) {
  uint8_t rx_len = 0;
  while (HAL_UART_Receive(&huart2, &resp[rx_len], 1, 100) == HAL_OK) {
    if (rx_len >= 1 && resp[0] == 0xEF && resp[1] == 0x01) {  // 帧头
      if (rx_len >= resp[9] + 12) {  // 长度校验(数据+校验和)
        // 校验和验证(略)
        return rx_len;
      }
    }
    rx_len++;
    if (rx_len >= max_len) break;
  }
  return 0;  // 接收失败
}

// 指纹录入(用户ID:0-999)
uint8_t AS608_Enroll(uint16_t user_id) {
  uint8_t cmd[20], resp[20];
  // 步骤1:采集第一幅图像
  cmd[0] = 0xEF; cmd[1] = 0x01; cmd[2] = 0xFF; cmd[3] = 0xFF; cmd[4] = 0x01;  // 包头+地址
  cmd[5] = 0x01; cmd[6] = 0x00; cmd[7] = 0x03; cmd[8] = AS608_CMD_GETIMAGE;  // 指令
  cmd[9] = 0x01; cmd[10] = 0x00;  // 校验和(简化)
  AS608_SendCmd(cmd, 11);
  if (AS608_ReceiveResp(resp, 20) == 0) return 1;  // 采集失败
  if (resp[9] != 0x00) return 1;  // 错误码非0
  
  // 步骤2:生成特征码1
  cmd[8] = AS608_CMD_GENCHAR; cmd[9] = 0x01;  // 缓冲区1
  // ... 类似步骤1,发送指令并接收响应
  
  // 步骤3:采集第二幅图像,生成特征码2,合并,存储(完整流程需参考AS608手册)
  return 0;  // 成功
}

2.2 实时时钟(DS3231)驱动

#include "ds3231.h"
#include "i2c.h"

// 读取DS3231时间(BCD码转十进制)
void DS3231_ReadTime(RTC_TimeTypeDef *time) {
  uint8_t data[7];
  HAL_I2C_Mem_Read(&hi2c1, 0x68<<1, 0x00, 1, data, 7, 100);  // 从寄存器0x00读取7字节(秒-年)
  
  time->Seconds = (data[0]>>4)*10 + (data[0]&0x0F);  // BCD转十进制
  time->Minutes = (data[1]>>4)*10 + (data[1]&0x0F);
  time->Hours = (data[2]>>4)*10 + (data[2]&0x0F);
  time->Day = (data[3]>>4)*10 + (data[3]&0x0F);
  time->Date = (data[4]>>4)*10 + (data[4]&0x0F);
  time->Month = (data[5]>>4)*10 + (data[5]&0x0F);
  time->Year = 2000 + (data[6]>>4)*10 + (data[6]&0x0F);  // 假设2000年后
}

2.3 考勤记录存储(AT24C256 EEPROM)

#include "at24c256.h"
#include "i2c.h"

// 存储考勤记录(时间+用户ID)
void Attendance_Store(uint16_t user_id, RTC_TimeTypeDef *time) {
  uint8_t record[8];
  // 打包数据:年(2)+月(1)+日(1)+时(1)+分(1)+ID(2)
  record[0] = time->Year - 2000; record[1] = (time->Year - 2000) >> 8;
  record[2] = time->Month; record[3] = time->Date;
  record[4] = time->Hours; record[5] = time->Minutes;
  record[6] = user_id; record[7] = user_id >> 8;
  
  // 写入AT24C256(地址递增,假设从0x0000开始)
  static uint16_t write_addr = 0x0000;
  HAL_I2C_Mem_Write(&hi2c1, 0x50<<1, write_addr, 2, record, 8, 100);
  write_addr += 8;
  if (write_addr >= 0x7FFF) write_addr = 0x0000;  // 循环覆盖
}

2.4 主程序框架(FreeRTOS任务调度)

#include "stm32f1xx_hal.h"
#include "FreeRTOS.h"
#include "task.h"
#include "as608.h"
#include "ds3231.h"
#include "oled.h"
#include "at24c256.h"

int main(void) {
  HAL_Init();
  SystemClock_Config();  // 72MHz
  MX_GPIO_Init();        // GPIO初始化(按键、蜂鸣器、LED)
  MX_USART1_Init();      // UART1(ESP8266)
  MX_USART2_Init();      // UART2(AS608)
  MX_I2C1_Init();        // I2C1(DS3231、AT24C256、OLED)
  
  OLED_Init();           // OLED显示初始化
  DS3231_Init();         // RTC初始化
  AS608_Init();          // 指纹传感器初始化
  AT24C256_Init();       // EEPROM初始化
  
  // FreeRTOS任务创建
  xTaskCreate(Fingerprint_Task, "Fingerprint", 256, NULL, 4, NULL);  // 指纹处理
  xTaskCreate(Time_Task, "Time", 128, NULL, 3, NULL);                // 时间管理
  xTaskCreate(UI_Task, "UI", 128, NULL, 2, NULL);                    // 用户交互
  xTaskCreate(Storage_Task, "Storage", 128, NULL, 2, NULL);          // 数据存储
  xTaskCreate(Comm_Task, "Comm", 128, NULL, 1, NULL);                // 通信上传
  
  vTaskStartScheduler();  // 启动调度器
  while (1);
}

四、关键技术与优化

1. 指纹识别优化

2. 数据管理优化

3. 低功耗设计

参考代码 基于STM32指纹考勤设计 www.youwenfan.com/contentcnt/133707.html

五、系统调试与扩展

1. 调试步骤

阶段 操作 工具
硬件调试 测量电源电压(3.3V/5V),示波器检查UART/I2C时序 万用表、示波器
指纹模块测试 用串口助手发送AS608指令(如EF 01 FF FF FF 01 00 03 01 00 05),验证响应 串口调试助手(SSCOM)
RTC校准 对比标准时间与DS3231读数,调整偏差(通过寄存器0x0E设置) 标准时钟、串口打印时间
联调 录入指纹→识别→查看OLED显示考勤记录→上传云端 手机APP(OneNET)、逻辑分析仪

2. 扩展功能

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