当前位置: 首页 > news >正文

【嵌入式实战-06】从零搭建 STM32+MFRC522 RFID 门禁系统

前言

很多嵌入式初学者学完 RFID 理论后,往往卡在 "怎么落地成一个能用的项目" 这一步。本文将带你从零开始,搭建一个工业级可用的 RFID 门禁系统,涵盖硬件选型、电路连接、代码实现、调试排坑全流程。

本文亮点:

  • 基于STM32F103C8T6+MFRC522,成本低、资料多、易移植
  • 完整可运行的HAL 库源码,注释详细,直接编译烧录
  • 支持按键加卡 / 删卡,授权信息断电不丢失
  • 真实项目踩坑记录,解决 90% 新手会遇到的问题
  • 提供 5 种以上功能扩展方案,可直接用于毕设或小项目

适合人群:嵌入式初学者、物联网从业者、正在做毕设的学生

一、系统整体设计

1.1 核心功能

  • ✅ 刷卡开门:识别授权 IC 卡,自动控制电磁锁
  • ✅ 声光提示:绿灯亮 + 短鸣 = 开门成功;红灯亮 + 长鸣 = 非法卡
  • ✅ 授权管理:通过按键添加 / 删除授权卡,最多支持 20 张
  • ✅ 自动关门:开门 3 秒后自动上锁
  • ✅ 防冲突处理:多张卡同时刷卡时,能正确识别单张卡

1.2 系统架构

STM32F103C8T6主控 ├─ MFRC522 RFID读卡器 → 读取IC卡UID ├─ 5V继电器模块 → 控制12V电磁锁 ├─ 有源蜂鸣器 → 声音提示 ├─ 红绿LED指示灯 → 状态指示 └─ 2个独立按键 → 加卡/删卡功能

二、硬件选型与电路连接

2.1 完整 BOM 表(总成本约 80 元)

模块名称推荐型号核心作用选型原因成本参考
主控板STM32F103C8T6 最小系统板系统核心控制入门经典款,性价比高,资料丰富¥15
RFID 读卡器MFRC522(带天线)识别 13.56MHz IC 卡集成度高,SPI 通信,驱动简单¥12
执行机构5V 单路继电器模块控制电磁锁通断带光耦隔离,抗干扰能力强¥8
门锁12V 电磁锁(吸力 60kg)执行开门 / 关门动作断电上锁,安全可靠¥25
提示模块有源蜂鸣器 + 红绿 LED声光状态提示成本低,效果直观¥5
输入模块2 个独立按键加卡 / 删卡操作简单易用,无需额外驱动¥2
电源模块12V/2A 适配器 + 3.3V 降压模块系统供电电磁锁单独供电,避免干扰¥13

2.2 详细引脚连接表

STM32 引脚连接模块引脚功能
PA4MFRC522SDA(SPI 片选)
PA5MFRC522SCK(SPI 时钟)
PA6MFRC522MISO(主入从出)
PA7MFRC522MOSI(主出从入)
PA8MFRC522RST(复位)
PB0继电器模块IN(控制信号)
PB1绿色 LED正极
PB2红色 LED正极
PB3有源蜂鸣器正极
PA0加卡按键输入(下拉)
PA1删卡按键输入(下拉)
3.3VMFRC522/LED/ 蜂鸣器 / 按键电源
GND所有模块

⚠️ 关键硬件注意事项

  1. MFRC522 只能用 3.3V 供电,接 5V 会直接烧毁芯片
  2. 电磁锁必须单独供电,并在两端并联FR107 续流二极管(阴极接 12V 正极,阳极接负极),防止断电瞬间的反电动势击穿继电器和主控
  3. MFRC522 天线要远离金属物体,否则读取距离会大幅缩短(正常 3-5cm)
  4. 继电器触点容量要大于电磁锁工作电流(通常 1-2A)

三、软件实现(完整 HAL 库源码)

3.1 开发环境

  • Keil MDK5.38
  • STM32CubeMX 6.10.0
  • ST-Link/V2 仿真器

3.2 STM32CubeMX 配置

  1. 时钟配置:外部 8MHz 晶振,系统时钟 72MHz
  2. SPI1 配置:Mode 0(CPOL=0, CPHA=0),数据大小 8 位,波特率 5MHz(实测最稳定)
  3. GPIO 配置
    • PA4/PA5/PA6/PA7/PA8:推挽输出(MFRC522)
    • PB0/PB1/PB2/PB3:推挽输出(继电器 / LED / 蜂鸣器)
    • PA0/PA1:下拉输入(按键)
  4. USART1 配置:波特率 115200,用于调试输出

3.3 核心代码实现

3.3.1 MFRC522 驱动核心函数

// mfrc522.h #ifndef __MFRC522_H #define __MFRC522_H #include "stm32f1xx_hal.h" #define MI_OK 0 #define MI_ERR 1 // MFRC522命令定义 #define PICC_REQIDL 0x26 #define PICC_ANTICOLL1 0x93 #define PICC_SELECTTAG 0x93 #define PICC_HALT 0x50 // 函数声明 void MFRC522_Init(void); uint8_t MFRC522_Request(uint8_t reqMode, uint8_t *TagType); uint8_t MFRC522_Anticoll(uint8_t *cardID); uint8_t MFRC522_Select(uint8_t *cardID); void MFRC522_Halt(void); #endif
// mfrc522.c(核心函数节选) #include "mfrc522.h" #include "spi.h" #include "gpio.h" // 写寄存器 void MFRC522_WriteReg(uint8_t reg, uint8_t value) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, &reg, 1, 100); HAL_SPI_Transmit(&hspi1, &value, 1, 100); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); } // 读寄存器 uint8_t MFRC522_ReadReg(uint8_t reg) { uint8_t value; reg = 0x80 | reg; HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, &reg, 1, 100); HAL_SPI_Receive(&hspi1, &value, 1, 100); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); return value; } // 防冲突函数:读取卡片唯一ID uint8_t MFRC522_Anticoll(uint8_t *cardID) { uint8_t status; uint8_t i, snr_check = 0; uint16_t recvLen; uint8_t sendData[2] = {PICC_ANTICOLL1, 0x20}; status = MFRC522_Communicate(PCD_TRANSCEIVE, sendData, 2, sendData, &recvLen); if(status == MI_OK && recvLen == 40) { for(i=0; i<4; i++) { cardID[i] = sendData[i]; snr_check ^= sendData[i]; } if(snr_check != sendData[4]) status = MI_ERR; } else { status = MI_ERR; } return status; }

3.3.2 授权卡管理(Flash 存储)

// card_manager.h #ifndef __CARD_MANAGER_H #define __CARD_MANAGER_H #include "stm32f1xx_hal.h" #define MAX_CARD_NUM 20 // 最多支持20张授权卡 #define FLASH_ADDR 0x0800F800 // Flash存储地址(最后一页) // 函数声明 void CardManager_Init(void); uint8_t CardManager_Check(uint8_t *cardID); uint8_t CardManager_Add(uint8_t *cardID); uint8_t CardManager_Delete(uint8_t *cardID); void CardManager_Save(void); #endif

3.3.3 主逻辑代码

// main.c #include "main.h" #include "spi.h" #include "gpio.h" #include "usart.h" #include "mfrc522.h" #include "card_manager.h" #include "relay.h" #include "beep.h" #include "led.h" #include "key.h" int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_SPI1_Init(); MX_USART1_UART_Init(); MFRC522_Init(); CardManager_Init(); printf("RFID门禁系统启动成功\r\n"); uint8_t cardID[4]; uint8_t status; uint32_t door_timer = 0; uint8_t door_state = 0; while(1) { // 按键处理:加卡/删卡 Key_Process(); // 寻卡 if(MFRC522_Request(PICC_REQIDL, cardID) == MI_OK) { // 防冲突,读取UID if(MFRC522_Anticoll(cardID) == MI_OK) { printf("检测到卡片,UID: %02X%02X%02X%02X\r\n", cardID[0], cardID[1], cardID[2], cardID[3]); // 检查是否是授权卡 if(CardManager_Check(cardID) == MI_OK) { printf("授权卡,开门\r\n"); Relay_Open(); LED_Green_On(); Beep_Short(); door_timer = HAL_GetTick(); door_state = 1; } else { printf("非法卡,报警\r\n"); LED_Red_On(); Beep_Long(); HAL_Delay(1000); LED_Red_Off(); } MFRC522_Halt(); // 休眠卡片 } } // 自动关门:3秒后 if(door_state && (HAL_GetTick() - door_timer > 3000)) { Relay_Close(); LED_Green_Off(); door_state = 0; printf("自动关门\r\n"); } HAL_Delay(10); } }

四、测试与验证

4.1 测试步骤

  1. 上电测试:连接所有硬件,上电后绿色 LED 常亮,表示系统正常
  2. 刷卡测试:将一张空白 IC 卡靠近读卡器,串口会输出卡片 UID
  3. 加卡测试:按下加卡按键(PA0),蜂鸣器响一声,然后刷卡,提示 "加卡成功"
  4. 开门测试:刷刚添加的授权卡,继电器吸合,电磁锁打开,3 秒后自动关闭
  5. 非法卡测试:刷未授权的卡,蜂鸣器长鸣,红灯亮,门锁不打开
  6. 删卡测试:按下删卡按键(PA1),蜂鸣器响一声,然后刷卡,提示 "删卡成功"
  7. 断电测试:断电后重新上电,授权卡信息仍然保留

4.2 预期结果

  • 授权卡刷卡成功率 100%,响应时间 < 0.5 秒
  • 非法卡无法开门,报警提示正常
  • 加卡 / 删卡功能正常,断电不丢失数据
  • 自动关门时间准确,无卡顿

五、新手必看:踩坑与解决方案

这是我在实际项目中踩过的坑,90% 的新手都会遇到:

5.1 MFRC522 读取不到卡

问题现象:上电后读卡器无反应,串口无输出可能原因及解决

  1. SPI 引脚接反:MISO 和 MOSI 是最容易接反的,一定要仔细核对
  2. 电源错误:MFRC522 必须用 3.3V,接 5V 会直接烧毁
  3. SPI 配置错误:必须设置为Mode 0(CPOL=0, CPHA=0),速率不要超过 5MHz
  4. 复位引脚未接:RST 引脚必须接 STM32 的 GPIO,不能悬空
  5. 天线问题:天线焊接不良或靠近金属,会导致读取距离为 0

5.2 电磁锁干扰导致系统死机

问题现象:开门瞬间系统死机,需要重新上电根本原因:电磁锁是感性负载,断电瞬间会产生数百伏的反电动势,通过电源线路干扰主控解决方案

  1. 电磁锁必须单独供电,不要和主控共用电源
  2. 在电磁锁两端并联FR107 续流二极管(阴极接 12V 正极,阳极接负极)
  3. 继电器模块必须带光耦隔离,切断干扰路径
  4. 在主控电源输入端加 100uF 电解电容和 0.1uF 陶瓷电容滤波

5.3 多张卡同时刷卡出错

问题现象:两张卡同时靠近读卡器时,系统无反应或识别错误解决方案:正确实现 MFRC522 的防碰撞算法,本文提供的代码已经包含完整的防碰撞处理,能正确识别多张卡中的任意一张

5.4 授权卡信息断电丢失

问题现象:断电后重新上电,之前添加的授权卡全部失效解决方案:不要将授权卡信息存储在 RAM 中,要存储到 STM32 的Flash中。本文提供的 CardManager 模块已经实现了 Flash 读写功能,断电后数据不会丢失。

六、功能扩展方案

这个基础门禁系统可以很方便地扩展更多功能:

  1. 添加 LCD 显示屏:使用 0.96 寸 OLED 显示屏,显示卡号、系统状态、操作提示
  2. WiFi 远程控制:添加 ESP8266 模块,实现手机 APP 远程开门、刷卡记录查询
  3. 指纹识别:集成 AS608 指纹模块,实现 RFID + 指纹双重认证
  4. 密码开锁:添加 4x4 矩阵键盘,支持密码开锁
  5. 刷卡记录上传:将刷卡记录上传到云端服务器,实现远程监控
  6. 低功耗设计:使用 STM32 的低功耗模式,适合电池供电的场景

七、总结

本文详细介绍了如何从零搭建一个完整的 RFID 门禁系统,从硬件选型到软件实现,再到调试排坑,每一步都给出了详细的说明和完整的代码。这个系统不仅可以作为学习项目,还可以直接用于实际的门禁场景。

通过这个项目,你可以掌握:

  • STM32 HAL 库的使用
  • SPI 通信协议
  • MFRC522 RFID 模块的驱动开发
  • Flash 数据存储
  • 硬件抗干扰设计
  • 嵌入式系统的整体设计思路

创作不易,如果本文对你有帮助,欢迎点赞、收藏、转发,你的支持是我持续输出的动力!

http://www.cnnetsun.cn/news/2163617.html

相关文章:

  • 创业公司如何借助 Taotoken 低成本试错多款大模型
  • 如何快速搭建Web表格:终极Vue Excel编辑器指南
  • TPFanCtrl2:ThinkPad双风扇控制终极指南,打造静音高效散热系统
  • 使用curl命令快速测试Taotoken接口连通性与模型响应
  • 别再死记公式了!用Python动手推导酉空间的内积、距离与度量矩阵
  • GESP2025年3月认证C++五级( 第一部分选择题(1-8))
  • 系统将自动清除超出预约期限的预约记录并修改相关信息
  • 2025届毕业生推荐的十大降重复率助手横评
  • 终极KMS激活指南:3分钟完成Windows和Office永久免费激活
  • Qt界面美化避坑指南:QSS设置背景图片时,路径、缩放和性能这些坑你踩过吗?
  • 主流虚拟化厂商深度评述:VMware替代的稳妥之选在哪?
  • Android 13音频子系统深度拆解:从AudioTrack到HAL,一次搞懂数据流与核心服务
  • 终极指南:如何在Mac上免费实现NTFS硬盘完整读写功能
  • 韩国投资证券开源交易API:官方SDK对接与自动化交易实战
  • 别再手动转码了!VSCode 1.85+ 这个设置,让你彻底告别中文乱码
  • 开源macOS应用卸载架构演进:Pearcleaner深度技术解析与实战指南
  • 高效利用提示词仓库:提升大语言模型协作质量与效率
  • 观察与对比在 Taotoken 上调用不同模型时的延迟与稳定性体感
  • 为内部知识库问答系统集成Taotoken的多模型备选能力
  • QrazyBox终极指南:像医生一样拯救你的损坏二维码,5分钟恢复任何模糊QR码
  • 对比直连与通过聚合平台调用大模型API的延迟与稳定性体感
  • Harvard格式下,EndNote处理中文作者名的‘坑’与‘桥’:我的GB/T 7714兼容实践
  • 终极指南:如何用Parse12306免费获取全国高铁列车完整数据
  • UnityExplorer完整指南:如何在游戏运行时调试和修改Unity项目
  • 避坑指南:在ESP32上跑MicroPython Web服务器,这几个问题你肯定遇到过
  • 手把手解决AutoDock安装那些坑:从autogrid报错到.map文件生成(Win10/11环境)
  • 别再只调车窗了!用UDS 2F服务控制ECU输入输出,从原理到实战(附报文分析)
  • Weka机器学习算法性能对比实战指南
  • 2026年艺术设计论文降AI工具推荐:创意设计和视觉传达研究降AI方案
  • 【2026年最新600套毕设项目分享】微信小程序线上教育商城(30205)