1. 项目概述:基于STM32的RFID员工打卡门禁系统
去年指导本科生毕业设计时,遇到一个典型的工控类课题——用STM32开发RFID员工打卡门禁系统。这个看似简单的项目实际上涵盖了嵌入式开发、射频识别、数据存储等多个技术模块的有机整合。市面上虽然有成套的门禁解决方案,但自己动手实现一套完整系统,对理解物联网终端设备的运作机制特别有帮助。
系统核心功能是通过RFID读卡器识别员工卡信息,验证权限后控制电磁锁开关,同时记录考勤数据到本地存储器。相比商业产品,我们的DIY方案在硬件成本上可以控制在200元以内,特别适合中小型企业或学校实验室的场景需求。下面我就从硬件选型、程序设计到实际部署的完整流程,分享这个项目的技术细节和踩坑经验。
2. 硬件架构设计
2.1 核心器件选型
主控芯片选用STM32F103C8T6最小系统板(俗称"蓝板"),这款Cortex-M3内核的MCU性价比极高,72MHz主频完全能满足需求。RFID模块采用经典的RC522,其13.56MHz工作频率的识别距离约5cm,正好符合门禁场景的使用距离。其他关键部件包括:
- 电磁锁:12V供电的常闭型锁体,电流需≥300mA
- 电平转换模块:TXS0108E解决3.3V与5V系统兼容问题
- 存储模块:AT24C256 EEPROM(存储员工数据库)
- 显示模块:0.96寸OLED(SSD1306驱动)
- 报警模块:有源蜂鸣器+LED指示灯
硬件选型避坑提示:电磁锁务必选用带续流二极管的型号,否则继电器触点断开时产生的反向电动势可能损坏控制电路。我们第一批采购的廉价锁体就因为这个原因烧毁了两个IO口。
2.2 电路设计要点
电源部分采用AMS1117-3.3为STM32供电,同时需要一路12V/1A输出驱动电磁锁。RC522模块通过SPI接口连接,注意其NSS引脚要接单独GPIO而非硬件SPI片选。电磁锁控制电路设计如下:
c复制// 电磁锁驱动电路原理
MCU_GPIO -> 1K电阻 -> NPN三极管基极
三极管集电极接继电器线圈
继电器常开触点接电磁锁
并联续流二极管保护电路
实际焊接时发现,如果直接将RC522的天线模块与主板用杜邦线连接,读卡距离会大幅缩短。后来改用屏蔽线并保持天线部分远离金属物体,才达到标称识别距离。
3. 软件系统实现
3.1 嵌入式程序架构
整个工程采用HAL库开发,在CubeMX中配置:
- SPI1用于RC522通信(波特率设4.5Mbps)
- I2C1连接EEPROM和OLED
- USART1用于调试输出
- 三个GPIO分别控制电磁锁、蜂鸣器和指示灯
主程序状态机设计如下:
c复制void main() {
hardware_init();
while(1) {
switch(sys_state) {
case IDLE:
if(detect_card()) sys_state = AUTH;
break;
case AUTH:
if(verify_card()) unlock_door();
else alarm();
sys_state = IDLE;
break;
}
display_refresh();
}
}
3.2 RFID数据处理关键代码
RC522的底层驱动需要实现ISO14443A协议通信,重点在防冲突处理和UID读取:
c复制uint8_t read_card_uid(uint8_t *uid) {
// 寻卡指令
PcdRequest(PICC_REQALL, buffer);
// 防冲突处理
PcdAnticoll(buffer);
memcpy(uid, buffer, 5);
// 选择卡片
PcdSelect(uid);
return STATUS_OK;
}
员工数据库存储在EEPROM中,采用如下数据结构:
| 地址偏移 | 字段 | 长度 | 说明 |
|---|---|---|---|
| 0x0000 | 记录数量 | 2 | 大端存储 |
| 0x0002 | 员工1 UID | 5 | 卡片唯一标识 |
| 0x0007 | 员工1姓名 | 16 | UTF-8编码 |
| 0x0017 | 员工1部门 | 8 | 部门代码 |
| ... | ... | ... | 每条记录占29字节 |
3.3 考勤记录实现
每次成功打卡后,系统会在EEPROM末尾追加记录,格式为:
c复制#pragma pack(1)
typedef struct {
uint8_t uid[5];
uint32_t timestamp; // Unix时间戳
uint8_t reserved[3]; // 对齐填充
} AttendanceRecord;
由于EEPROM有擦写寿命限制(约10万次),实际工程中需要做磨损均衡处理。我们采用循环队列的方式,当写满时自动覆盖最早记录。
4. 系统优化与问题排查
4.1 抗干扰优化
现场测试时发现,当多张卡片同时靠近读卡器时会出现误识别。通过以下改进显著提升稳定性:
- 在寻卡阶段增加超时判断(300ms无响应则重置)
- 添加软件去抖机制:连续3次读取到相同UID才确认有效
- 调整天线匹配电路:将原厂推荐的50Ω匹配改为47Ω+3pF电容
4.2 典型问题排查表
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 读卡无反应 | 天线接触不良 | 检查天线焊点与匹配电路 |
| 偶尔误识别 | 电源纹波过大 | 在RC522的VCC引脚加104电容 |
| EEPROM写入失败 | I2C总线冲突 | 检查上拉电阻(建议4.7K) |
| 电磁锁无法保持 | 驱动电流不足 | 改用MOSFET替代NPN三极管 |
4.3 功耗优化技巧
虽然本项目采用有线供电,但为后续电池供电方案考虑,我们测试了低功耗模式:
- 将STM32主频降至8MHz(仍能满足需求)
- 非活动期间进入STOP模式,通过RC522的中断引脚唤醒
- 显示模块改用静态显示模式,刷新率从60Hz降至1Hz
实测可使整机待机电流从85mA降至12mA,但响应速度会稍有延迟。
5. 扩展功能实现
5.1 网络同步模块
通过添加ESP8266 WiFi模块,可以实现考勤数据实时上传。我们在硬件上预留了USART2接口,软件层面采用AT指令通信:
c复制void upload_record(AttendanceRecord *rec) {
char cmd[128];
sprintf(cmd, "AT+CIPSTART=\"TCP\",\"192.168.1.100\",8080");
send_at_command(cmd);
sprintf(cmd, "POST /api/attendance HTTP/1.1\r\nHost: server\r\n");
send_at_command(cmd);
// 拼接JSON数据...
}
5.2 指纹识别扩展
在现有RFID基础上,可以并联指纹模块(如FPM10A)实现双因素认证。需要注意:
- 指纹算法需要较大内存,建议换用STM32F4系列
- 两种认证方式需分时操作(共享SPI总线)
- 数据库结构需要扩展指纹特征字段
6. 论文撰写要点
作为毕业设计项目,论文需要突出以下技术亮点:
- 硬件设计部分:重点描述抗干扰电路设计和功耗优化方案
- 软件算法:详细说明RFID的防冲突算法实现
- 创新点:如基于EEPROM的简易数据库管理系统
- 测试数据:提供不同距离下的读卡成功率曲线
特别提醒:论文中的电路图建议使用KiCad绘制,比Visio更专业;程序流程图建议用PlantUML生成,保持风格统一。