1. 项目背景与核心需求
最近帮朋友公司做了个基于STM32的考勤系统,正好也是计算机专业学生常见的毕业设计选题。这种系统看起来简单,实际开发时会遇到不少坑。传统的指纹或IC卡考勤机价格昂贵,而用STM32自主开发成本能控制在200元以内,特别适合中小企业或学校实验室使用。
这个系统的核心功能很简单:员工刷卡或指纹验证身份,记录考勤时间,并通过WiFi/4G模块上传数据到服务器。但要在STM32上稳定实现这些功能,需要处理好以下几个关键点:
- 低功耗设计(毕竟要7x24小时运行)
- 实时时钟精度(考勤记录时间必须准确)
- 生物识别模块的响应速度
- 断网时的数据缓存机制
2. 硬件选型与电路设计
2.1 主控芯片选择
我用的是STM32F103C8T6最小系统板(俗称"蓝板"),性价比极高:
- 72MHz主频足够处理考勤逻辑
- 64KB Flash + 20KB RAM
- 自带RTC(需外接32.768kHz晶振)
- 市场价仅15-20元
注意:一定要买带Bootloader的版本,否则需要ST-Link烧录器
2.2 外围模块配置
-
身份识别模块:
- 指纹模块:FPM10A光学指纹头(约60元)
- IC卡读卡器:RC522射频模块(15元)
-
网络模块:
- ESP8266 WiFi模块(12元)
- 4G模块推荐SIM7600CE(但成本较高约150元)
-
其他外设:
- DS1302时钟芯片(保证断电后时间不丢失)
- AT24C256 EEPROM(存储本地考勤记录)
- 0.96寸OLED显示屏(显示实时状态)
2.3 电源设计要点
考勤机通常需要24小时运行,电源设计很关键:
c复制// 低功耗模式配置示例
void Enter_StopMode(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
}
实测电流:
- 正常工作:85mA
- 休眠模式:2.3mA
- 指纹识别时峰值:120mA
建议选用5V/2A电源适配器,并增加1000μF电容缓冲。
3. 软件架构设计
3.1 系统流程图
整个系统采用前后台架构:
- 前台:中断处理(按键、指纹识别、网络通信)
- 后台:主循环轮询各模块状态
mermaid复制graph TD
A[上电初始化] --> B[读取EEPROM配置]
B --> C{网络连接?}
C -->|是| D[同步服务器时间]
C -->|否| E[使用RTC时间]
D --> F[进入主循环]
E --> F
F --> G{有刷卡/指纹?}
G -->|是| H[验证身份]
G -->|否| F
H --> I[记录考勤时间]
I --> J[尝试上传数据]
J --> K{上传成功?}
K -->|是| F
K -->|否| L[本地存储]
L --> F
3.2 关键代码实现
RTC时钟配置:
c复制void RTC_Config(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
PWR_BackupAccessCmd(ENABLE);
if(BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5)
{
RCC_LSEConfig(RCC_LSE_ON);
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
RCC_RTCCLKCmd(ENABLE);
RTC_WaitForSynchro();
RTC_WaitForLastTask();
BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);
}
}
指纹识别处理:
c复制uint8_t Fingerprint_Verify(void)
{
uint8_t ret;
uint16_t id;
ps_GetImage(); // 采集指纹图像
ps_GenChar(1); // 生成特征
ret = ps_Search(1, &id); // 搜索指纹库
if(ret == 0) {
OLED_ShowString(2,1,"ID:");
OLED_ShowNum(2,4,id,3);
return 1;
}
return 0;
}
4. 服务器通信协议
4.1 数据格式设计
采用精简的JSON格式传输:
json复制{
"device_id": "D001",
"emp_id": "10086",
"time": "2023-08-20 08:30:45",
"type": 1 // 1签到 2签退
}
4.2 断网处理机制
-
本地存储:
- 使用EEPROM循环存储最多500条记录
- 存储满后自动覆盖最早记录
-
重传策略:
c复制void Data_Upload_Task(void)
{
while(1) {
if(Check_Network()) {
record = Read_Next_Record();
if(Upload_Record(record)) {
Delete_Record(record);
} else {
Delay_Minutes(5); // 5分钟后重试
}
}
osDelay(1000);
}
}
5. 常见问题与解决方案
5.1 指纹识别失败率高
可能原因:
- 手指干燥/潮湿
- 指纹模块镜面脏污
- 按压角度偏差
解决方法:
- 增加指纹录入次数(建议同一手指录入3次)
- 定期用酒精棉清洁模块
- 在OLED上显示按压位置指引
5.2 时间不同步问题
现象:
- 设备重启后时间归零
- 与服务器时间差超过5分钟
排查步骤:
- 检查32.768kHz晶振是否起振
- 测量VBAT引脚电压(应>2V)
- 测试NTP服务器连通性
5.3 数据上传失败
典型错误码:
- 400:数据格式错误
- 401:设备未注册
- 500:服务器内部错误
处理策略:
flow复制st=>start: 上传失败
e=>end: 放弃上传
op1=>operation: 重试3次
cond1=>condition: 仍失败?
op2=>operation: 存储到EEPROM
op3=>operation: 标记为待同步
st->op1->cond1
cond1(yes)->op2->op3->e
cond1(no)->e
6. 毕业设计优化建议
如果想拿高分,可以考虑增加这些功能:
-
人脸识别模块:
- 使用OV2640摄像头
- 移植OpenMV算法
-
数据分析功能:
- 迟到/早退统计
- 月度考勤报表生成
-
低功耗优化:
- 运动检测唤醒(PIR传感器)
- 动态调整CPU频率
-
防作弊机制:
- 活体检测(指纹)
- 地理位置验证
实际开发中,建议先用Proteus做电路仿真,再用Keil编写代码。最后用串口调试助手和网络调试助手联调通信模块。这个项目我前后调试了2周时间,最耗时的部分是指纹模块的误识别率优化,后来发现是供电不足导致,增加一个470μF电容后问题解决。