1. 项目背景与需求分析
记得我刚开始接触嵌入式开发的时候,最头疼的就是如何把硬件和软件完美结合起来。今天给大家分享的这个STM32+RFID智能考勤门禁系统,正是我当年毕业设计的升级版,现在回想起来还是觉得特别实用。
这个系统说白了就是用RFID卡片代替传统的打卡方式,员工只需要刷一下卡,系统就能自动记录考勤并控制门禁开关。我当初做这个项目的时候,主要考虑了以下几个实际需求:首先是稳定性,不能动不动就死机或者误识别;其次是易用性,管理员要能方便地添加删除员工信息;最后是成本控制,毕竟大多数公司都不愿意在考勤系统上花太多钱。
在实际企业环境中,传统的指纹打卡经常遇到识别率低的问题,而人脸识别又成本较高。RFID技术在这中间找到了一个很好的平衡点 - 识别速度快、成本适中,而且卡片不容易损坏。我测试过,即使在潮湿的工厂环境或者灰尘较多的仓库,这套系统都能稳定工作。
2. 硬件设计方案详解
2.1 核心控制器选型
我选择的是STM32F103C8T6作为主控芯片,这款芯片可以说是嵌入式开发的"国民MCU"了。为什么选它?首先价格实惠,一片才十几块钱;其次资源丰富,72MHz的主频完全够用,而且有足够的GPIO口来连接各种外设。
在实际焊接电路时,我建议大家都使用排针和排座来连接各个模块,这样调试起来会方便很多。我记得第一次做的时候直接把所有模块焊死,后来发现RFID模块有问题,拆下来差点把焊盘都搞坏了,这个坑大家一定要避免。
2.2 RFID模块选择与连接
我用的是MFRC522射频模块,这个模块性价比很高,支持ISO14443A协议,读写距离在5-7cm左右,正好适合考勤使用。接线方面需要注意,STM32的SPI接口是固定引脚,不能随意更改:
RC522 STM32
SDA -> PA4(CS)
SCK -> PA5(SCK)
MOSI -> PA7(MOSI)
MISO -> PA6(MISO)
IRQ -> 不接
GND -> GND
RST -> PA0
3.3V -> 3.3V
这里有个小技巧:RST引脚可以接任意GPIO,不一定要接复位引脚。我在实际测试中发现,如果接在PA0上,稳定性会更好一些。
2.3 其他外设配置
除了RFID模块,还需要一些辅助的外设:
- OLED显示屏:我用的是0.96寸的SSD1306,用来显示打卡状态和时间
- 继电器模块:控制电锁的开关,记得要加反向续流二极管保护电路
- LED指示灯:用红绿双色LED显示打卡状态
- 蜂鸣器:提供声音反馈
电源部分建议使用AMS1117-3.3V稳压芯片,外部输入5V电压,转换成3.3V给STM32和各个模块供电。我在电源输入端加了一个100μF的电解电容和一个104的瓷片电容,有效滤除了电源噪声。
3. 软件架构与核心代码实现
3.1 系统初始化流程
系统的软件架构采用了分层设计,这样后期维护和升级都会很方便。首先是硬件抽象层,负责底层驱动;然后是业务逻辑层,处理考勤逻辑;最后是应用层,实现具体的功能。
初始化代码要按顺序执行,否则很容易出问题:
void System_Init(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI1_Init();
MX_USART1_UART_Init();
OLED_Init();
RFID_Init();
Relay_Init();
Buzzer_Init();
printf("System Init Complete\r\n");
}
这里特别要注意SPI的初始化顺序,必须先初始化GPIO再初始化SPI外设。我遇到过因为初始化顺序不对导致RFID模块无法通信的情况,调试了好久才发现问题。
3.2 RFID读写器驱动
RFID驱动的核心是寻卡、防冲突和选卡三个步骤。下面是简化的寻卡代码:
uint8_t RFID_FindCard(uint8_t* id)
{
uint8_t status;
uint8_t buf[MAX_LEN];
status = MFRC522_Request(PICC_REQIDL, buf);
if(status != MI_OK) return status;
status = MFRC522_Anticoll(buf);
if(status != MI_OK) return status;
memcpy(id, buf, 5);
MFRC522_SelectTag(id);
return MI_OK;
}
在实际使用中,我发现需要加入超时机制,否则有时候卡片离开后程序会卡在寻卡环节。我的做法是加入一个500ms的超时判断,超时后就退出寻卡流程。
3.3 数据库管理设计
我用了最简单的文本文件来存储员工信息,每个员工一行,用逗号分隔格式:姓名,卡号,打卡状态,最后打卡时间。虽然简单,但对于小企业来说完全够用。
void Save_Record(char* name, char* card_id)
{
FILE* fp = fopen("records.txt", "a");
if(fp != NULL)
{
time_t now = time(NULL);
fprintf(fp, "%s,%s,1,%s\n", name, card_id, ctime(&now));
fclose(fp);
}
}
如果要支持更多员工,建议使用SQLite数据库。我后来给一家公司升级系统时就用到了SQLite,查询效率明显提升。
4. 通信协议与上下位机交互
4.1 TCP通信协议设计
上下位机之间采用TCP通信,我自定义了一个简单的协议格式:
- 数据头:3个字节的"###"作为起始标志
- 数据体:变长数据,UTF-8编码
- 数据尾:2个字节的CRLF作为结束标志
上位机作为TCP服务器,下位机作为客户端。这样设计的好处是多个考勤点可以同时连接到一个服务器。在实际部署时,我建议给每台下位机设置不同的设备ID,方便管理。
4.2 数据解析与处理
下位机收到数据后需要解析协议:
void Parse_Protocol(uint8_t* data)
{
if(strncmp(data, "###", 3) == 0)
{
char* payload = data + 3;
if(strcmp(payload, "open") == 0)
{
Relay_Open(3000); //开门3秒
}
else if(strcmp(payload, "invalid") == 0)
{
OLED_ShowString("Invalid Card!");
Buzzer_Beep(3);
}
}
}
这里要注意网络字节序的问题。我第一次测试时发现上位机收到的数据总是乱码,后来才发现是编码方式不一致。建议统一使用UTF-8编码,避免这类问题。
5. 系统调试与优化经验
5.1 常见问题排查
在调试过程中,我总结了几个常见问题及解决方法:
- RFID读卡距离短:检查天线匹配电路,调整匹配电容的值
- 偶尔漏读卡:增加去抖动机制,连续读取多次确认
- 网络连接不稳定:加入心跳包机制,30秒发送一次心跳
- 数据不同步:增加重发机制,重要数据需要接收方确认
特别是RFID读卡距离问题,我通过调整天线的匹配电容,把读卡距离从3cm提升到了7cm。具体方法是使用网络分析仪调试,如果没有仪器,可以尝试不同容值的电容,找到读卡距离最远的那个值。
5.2 性能优化技巧
经过实际测试,我发现了几个提升系统性能的方法:
首先是要优化数据库操作。最初我每次打卡都直接写文件,后来改为先缓存到内存,每隔10条记录写一次文件,这样大大减少了IO操作。
其次是优化网络传输。把多个小数据包打包成一个大数据包传输,减少TCP握手次数。我测试过,这样能提升30%的传输效率。
最后是电源管理。加入自动休眠功能,在没有操作的时候让系统进入低功耗模式。我用的是STM32的Stop模式,功耗可以从50mA降到1mA左右。
6. 实际应用与扩展功能
6.1 企业部署建议
在实际部署时,我建议考虑以下几点:
- 安装位置要避开金属物体,金属会影响RFID读卡距离
- 最好准备备用电源,避免停电导致无法打卡
- 定期导出考勤数据,建议每周备份一次
- 为管理员设置不同的权限等级
我帮一家工厂部署时,就因为没注意金属干扰问题,导致读卡距离只有2cm,后来重新选位安装才解决问题。
6.2 功能扩展思路
这个基础系统还可以扩展很多实用功能:
视频监控联动:打卡时自动拍照存档,我用OV2640摄像头实现了这个功能,需要增加SD卡存储照片。
微信推送:通过ESP8266连接微信API,打卡后给管理员推送消息。
人脸识别双因子认证:增加一个摄像头模块,要求刷卡+人脸识别双验证。
温度检测:疫情期间我还给系统增加了体温检测功能,用的MLX90614红外温度传感器。
这些扩展功能我都实际实现过,代码和接线图都整理好了。如果大家有兴趣,我可以后续分享这些扩展功能的实现细节。
7. 源码结构与使用指南
完整的工程源码采用模块化设计,主要包含以下几个部分:
Hardware文件夹:硬件原理图和PCB设计文件,我用的是Altium Designer画的板子。如果不想自己画板,也可以用洞洞板或者万能板来搭建。
STM32文件夹:下位机源码,使用Keil MDK开发。核心文件包括:
- rfid.c:RFID驱动代码
- oled.c:显示驱动
- network.c:网络通信
- main.c:主程序
PC_Software文件夹:上位机程序,用Python编写。需要安装pyserial和tkinter库。
Database文件夹:数据库文件示例和SQL脚本。
编译下载时要注意选择正确的芯片型号,我用的STM32F103C8T6是中等容量芯片,启动文件要选择md.s那个。第一次下载程序前记得先复位,否则可能无法连接。
如果遇到无法读卡的问题,先用我提供的测试程序单独测试RFID模块,确认硬件没问题再调试整个系统。
873



被折叠的 条评论
为什么被折叠?



