资讯详情

基于单片机的门禁系统设计:从硬件选型到状态机实现

📅 2026/10/19 0:55:51 | 华诺云谱 👁 阅读
基于单片机的门禁系统设计:从硬件选型到状态机实现
简介这份资源是一篇完整的学位论文文档主题为基于单片机的门禁系统设计面向计算机、电子信息及自动化相关专业的本科生与研究生可用于毕业设计选题参考、课程设计借鉴或论文写作模板学习。文档围绕写字楼安全管理场景提出一套基于无线通信模式的联网式门禁方案重点解决传统有线门禁布线复杂、成本高、难以扩展升级等问题。压缩包内共1个doc文件整体约1.33MB即论文正文全文包含摘要、绪论、方案设计、硬件设计、软件设计、总结、参考文献与致谢等完整章节。硬件部分涉及电源、门禁控制器、RFM12射频模块无线传输平台、读卡器、RS232转换电路与电子锁等模块软件部分涵盖主控设备、无线传输模块与管理软件设计并采用C语言与Visual Basic实现人机界面。目前已有36人学习适合需要参考完整论文结构、系统方案论证与软硬件设计思路的读者。1. 从一份“学位论文—基于单片机的门禁系统设计论文.doc”说起这套方案到底能不能落地很多做嵌入式课程设计的人第一次看到“基于单片机的门禁系统设计”这个题目第一反应是去搜一份现成的 .doc 文档把目录、原理图、流程图、代码一股脑抄下来改改封面就交差。但真正做过一线项目的人都知道门禁系统最核心的不是论文格式而是“识别—判断—执行—反馈”这条闭环能不能稳定跑起来。它解决的是如何用一颗几十块钱的单片机配合读卡模块、电控锁、显示与报警电路做出一套能识别合法用户、拒绝非法闯入、并在异常时给出提示的小型控制系统。适合谁适合正在做课程设计、毕业设计、或者想入门嵌入式系统集成的开发者。这一章不聊论文怎么写只聊这套系统从硬件选型到软件状态机怎么一步步做成能演示、能复现、能经得起答辩追问的实物。2. 门禁系统的硬件选型与最小系统搭建别让电源和地线先翻车2.1 单片机主控怎么选51、STM32 还是 ESP32常见做法是如果只是完成“刷卡—开锁—显示”的基础功能STC89C52 或 STM32F103C8T6 都够用。51 单片机便宜、资料多、IO 口操作直接适合新手快速点灯和驱动继电器STM32 资源多、中断和定时器更稳适合需要同时处理读卡、显示、按键和锁控的多任务场景。我一般会建议如果论文里要写“系统稳定性”和“低功耗”选 STM32F103如果只求快速出实物51 单片机加最小系统板是最短路径。注意选型一旦定了后面所有代码和电路都要围绕它的供电电压、IO 驱动能力和时钟频率来设计不要中途换芯片。2.2 读卡模块与电控锁的接口设计读卡模块常见有 RFID-RC522、MFRC522 这类 13.56MHz 方案通过 SPI 接口和单片机通信。电控锁一般是 12V 供电单片机 IO 口不能直接驱动必须经过继电器或 MOS 管模块。接线时最容易忽略的是共地读卡模块、单片机、继电器模块、电控锁电源四者的地必须连在一起否则会出现“刷卡有反应但锁不动”或者“锁一动单片机就复位”的玄学现象。下面是一个典型的接口分配表实际布线时按这个逻辑走模块信号线接单片机引脚备注RC522SDA/SSPA4片选RC522SCKPA5SPI 时钟RC522MOSIPA7主出从入RC522MISOPA6主入从出RC522RSTPA3复位继电器INPB0高电平触发蜂鸣器I/OPB1低电平触发OLEDSCL/SDAPB6/PB7I2C 接口2.3 最小系统搭建的四个必查点第一电源。单片机用 3.3V 或 5V读卡模块通常 3.3V继电器和锁用 12V必须分开供电或加稳压模块。第二复位电路。51 单片机高电平复位STM32 低电平复位接错会一直复位。第三晶振。51 常用 11.0592MHz 或 12MHzSTM32 用 8MHz 外部晶振加内部 PLL。第四下载接口。51 用串口下载STM32 用 SWD 或串口提前把下载排针引出来不然后面调试要拆线。把这几步做完再上电测电压确认 3.3V 和 5V 都正常再插模块。// 以 STM32 HAL 库为例初始化 RC522 的 SPI 和 GPIO void RC522_Init(void) { // 使能 SPI1 和 GPIOA 时钟 __HAL_RCC_SPI1_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); // 配置 PA5/PA7 为复用推挽PA6 为浮空输入 GPIO_InitTypeDef gpio {0}; gpio.Pin GPIO_PIN_5 | GPIO_PIN_7; gpio.Mode GPIO_MODE_AF_PP; gpio.Speed GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, gpio); gpio.Pin GPIO_PIN_6; gpio.Mode GPIO_MODE_INPUT; gpio.Pull GPIO_NOPULL; HAL_GPIO_Init(GPIOA, gpio); // 配置 PA4 片选和 PA3 复位为普通输出 gpio.Pin GPIO_PIN_4 | GPIO_PIN_3; gpio.Mode GPIO_MODE_OUTPUT_PP; gpio.Pull GPIO_NOPULL; gpio.Speed GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA, gpio); // 拉高片选和复位进入待机状态 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_SET); }这段代码的逻辑是先开时钟再配 SPI 引脚复用功能然后配片选和复位引脚为普通输出。参数说明SPI 速率建议先设 1MHz 以下等读卡稳定后再往上调片选和复位初始电平要拉高否则 RC522 上电就进不了正常模式。如果读不到卡号先量 PA5、PA7 有没有波形再查片选有没有拉低。3. 读卡识别与权限判断的代码实现状态机比 if-else 更靠谱3.1 读卡流程寻卡、防冲突、选卡、读序列号RC522 读一张卡要经过四步寻卡Request、防冲突Anticollision、选卡Select、读序列号Read UID。很多新手只做寻卡就以为读到了卡号结果多张卡同时靠近时数据全乱。正确做法是每一步都判断返回值只有四步都成功才把 UID 存下来做权限比对。下面是一个简化的读卡函数uint8_t Read_Card_ID(uint8_t *uid) { uint8_t status; uint8_t buffer[5]; // 寻卡返回 ATQA status PCD_Request(PICC_REQIDL, buffer); if (status ! MI_OK) return status; // 防冲突获取 UID status PCD_Anticoll(buffer); if (status ! MI_OK) return status; // 选卡为后续读写做准备 status PCD_Select(buffer); if (status ! MI_OK) return status; // 拷贝 4 字节 UID memcpy(uid, buffer, 4); return MI_OK; }逻辑说明PCD_Request 的参数 PICC_REQIDL 表示寻感应区内所有卡PCD_Anticoll 返回的 buffer 前 4 字节是 UID第 5 字节是校验PCD_Select 用 UID 选中一张卡。参数上如果现场有多张卡防冲突阶段会返回第一张卡的 UID后续要循环读才能读全。失败时看返回值MI_NOTAGERR 表示没卡MI_ERR 表示通信出错先查 SPI 接线和供电。3.2 权限表怎么存数组、EEPROM 还是 Flash常见做法是如果只有几张固定卡直接定义一个二维数组存 UID 和权限等级如果需要发卡和删卡用 AT24C02 这类 EEPROM 存掉电不丢如果卡数量大用 STM32 内部 Flash 模拟 EEPROM。我一般会建议课程设计用数组加 EEPROM 的组合数组做快速比对EEPROM 做持久化。下面是一个权限表结构typedef struct { uint8_t uid[4]; // 卡号 uint8_t level; // 权限等级0 非法1 普通用户2 管理员 } CardInfo; CardInfo cardTable[10]; // 最多存 10 张卡 uint8_t cardCount 0; // 当前卡数量参数说明level 为 0 时直接拒绝为 1 时开锁并记录为 2 时进入管理模式。比对时用 memcmp 比较 4 字节 UID不要用字符串比较否则遇到 0x00 会截断。3.3 状态机设计待机、读卡、验证、开锁、报警用状态机写主循环比一堆 if-else 清晰得多。状态定义如下状态行为转移条件IDLE显示待机界面蜂鸣器不响检测到卡 → READREAD读 UID超时 500ms读到 UID → VERIFY超时 → IDLEVERIFY查权限表合法 → UNLOCK非法 → ALARMUNLOCK继电器吸合 3 秒显示欢迎3 秒到 → IDLEALARM蜂鸣器响 2 秒显示拒绝2 秒到 → IDLEvoid Main_Loop(void) { static uint8_t state IDLE; uint8_t uid[4]; switch (state) { case IDLE: if (Card_Present()) state READ; break; case READ: if (Read_Card_ID(uid) MI_OK) { state VERIFY; } else if (Timeout(500)) { state IDLE; } break; case VERIFY: if (Check_Permission(uid) 0) { state UNLOCK; } else { state ALARM; } break; case UNLOCK: Relay_On(); if (Timeout(3000)) { Relay_Off(); state IDLE; } break; case ALARM: Buzzer_On(); if (Timeout(2000)) { Buzzer_Off(); state IDLE; } break; } }逻辑说明每个状态只做一件事超时用毫秒计数。参数上读卡超时设 500ms 是为了避免卡没放稳就报错开锁 3 秒是常见门禁的默认时长可以按需改成 1 到 5 秒报警 2 秒足够引起注意又不扰民。如果状态卡死先查 Timeout 函数有没有被正确调用再查继电器和蜂鸣器有没有把电源拉低导致单片机复位。4. 显示、报警与数据记录让系统有“反馈”和“后悔药”4.1 OLED 显示待机、刷卡、拒绝三种界面OLED 用 I2C 接口显示内容分三行第一行状态第二行卡号第三行提示。待机显示“请刷卡”读到卡显示 UID 后四位拒绝显示“非法卡”。常见坑是 I2C 地址写错0x78 和 0x7A 要试一下。下面是一个显示函数void OLED_Show_Status(uint8_t *uid, uint8_t status) { OLED_Clear(); if (status 0) { OLED_ShowString(0, 0, Please Swipe); } else if (status 1) { OLED_ShowString(0, 0, Welcome); OLED_ShowHexNum(0, 2, uid[0], 2); OLED_ShowHexNum(20, 2, uid[1], 2); } else { OLED_ShowString(0, 0, Denied); } }参数说明OLED_ShowHexNum 的第三个参数是数值第四个是显示位数。如果显示乱码先查 I2C 速率是不是太高降到 100kHz 试试。4.2 报警电路蜂鸣器驱动与静音策略蜂鸣器分有源和无源有源给电就响无源要 PWM。课程设计常用有源蜂鸣器加三极管驱动单片机 IO 口输出高电平导通。注意蜂鸣器电流可能达到 30mA直接接 IO 口会拉低电压导致单片机复位必须加 S8050 或类似三极管。静音策略管理员刷卡后进入管理模式可以临时关闭报警但要有超时自动恢复避免忘记打开。4.3 数据记录把刷卡记录写进 EEPROM每次刷卡把 UID、时间戳、结果写进 EEPROM。时间戳可以用单片机内部 RTC 或者简单的开机计时。记录格式4 字节 UID 1 字节结果 2 字节计数。写之前先读出来判断是不是空再写。注意 EEPROM 擦写次数有限不要每次刷卡都写同一地址用环形缓冲区。void Log_Event(uint8_t *uid, uint8_t result) { static uint16_t addr 0x00; uint8_t buf[7]; memcpy(buf, uid, 4); buf[4] result; buf[5] addr 8; buf[6] addr 0xFF; AT24C02_Write(addr, buf, 7); addr 7; if (addr 0x7F) addr 0x00; // 环形覆盖 }逻辑说明addr 从 0 开始每次加 7超过 0x7F 就回到 0。参数上AT24C02 容量 256 字节最多存 36 条记录。如果写不进去查 I2C 上拉电阻是不是 4.7k地址是不是 0xA0。5. 避坑与常见问题那些让门禁系统“时好时坏”的细节5.1 刷卡没反应但电压正常现象读卡模块灯亮单片机也在跑但刷卡就是没数据。原因SPI 片选引脚接错或者 RC522 的 RST 一直拉低。解决用示波器看片选有没有拉低RST 上电后要拉高至少 10ms 再操作。没有示波器就用万用表测电压片选待机高电平刷卡瞬间拉低。5.2 开锁瞬间单片机复位现象继电器一吸合OLED 黑屏单片机重启。原因电控锁启动电流大电源被拉低。解决电控锁单独供电继电器模块加续流二极管单片机电源加 100uF 和 0.1uF 电容。如果还不行继电器和单片机之间加光耦隔离。5.3 多张卡同时靠近读不出卡号现象一张卡正常两张卡一起放就读不到。原因防冲突没做完整只寻卡没选卡。解决按 3.1 的四步走每一步判断返回值。如果还不行降低 SPI 速率到 500kHz 以下。5.4 断电后权限表丢失现象重新上电之前发的卡都不认了。原因权限表只存在 RAM 里。解决发卡时同步写 EEPROM上电时从 EEPROM 读回 cardTable。注意 EEPROM 读写要加延时AT24C02 写周期 5ms。5.5 论文里的流程图和实物对不上现象答辩时老师问“你这个防冲突怎么实现的”答不上来。原因论文抄的流程图和实际代码不一致。解决画流程图之前先把代码状态机写清楚按状态转移画不要凭想象画。论文里的每一个模块都要能在实物上指出对应的芯片和引脚。6. 从能跑到好用门禁系统的进阶技巧与验证方法6.1 用串口打印调试信息把黑匣子打开很多新手调试门禁系统全靠看灯和猜。我一般会先在主循环里加串口打印把状态、UID、权限结果都打出来。串口波特率设 115200用 USB 转 TTL 接电脑开串口助手看。这样刷卡没反应时能立刻知道是寻卡失败还是权限比对失败。打印格式建议[STATE] IDLE - READ、[UID] 12 34 56 78、[RESULT] DENIED。注意串口打印会占用时间读卡超时时间要相应放宽否则打印一半就超时了。6.2 用逻辑分析仪抓 SPI 时序确认 RC522 通信正常如果串口打印显示寻卡失败下一步就是抓 SPI 波形。逻辑分析仪接 SCK、MOSI、MISO、CS 四根线采样率设 1MHz 以上。正常时序CS 拉低SCK 八个脉冲MOSI 发命令MISO 回数据。如果 SCK 没波形查 SPI 初始化如果 MISO 一直是高查 MISO 接线或 RC522 供电。这个步骤能把“玄学”问题变成确定问题。6.3 权限表加超时锁定防止暴力试卡进阶做法连续 3 次非法卡锁定 30 秒期间不响应任何卡。实现方式在 VERIFY 状态加一个失败计数超过阈值进 LOCK 状态用定时器计时。这样能防止有人拿一堆卡反复试。参数上3 次和 30 秒是常见值可以按需调整。注意锁定期间 OLED 要显示“已锁定”否则用户以为坏了。6.4 验证方法用一张卡跑通全流程再用多张卡测边界验证时不要只测一张卡。准备三张卡一张管理员卡、一张普通卡、一张未授权卡。按顺序测管理员卡开锁并进管理模式普通卡开锁但不进管理未授权卡报警。然后测边界卡放在感应区边缘、快速划过、两张卡叠放、断电重启后权限是否还在。最后测异常拔掉读卡模块看是否报警短接继电器看是否复位。把这些测完系统才算能跑。6.5 一个具体技巧用状态机的超时计数替代 delay很多新手在开锁时用delay(3000)结果这 3 秒内单片机什么都不干刷卡没反应。正确做法是用定时器中断每 1ms 减计数主循环里判断计数到 0 再关锁。这样开锁期间还能响应其他事件。代码片段volatile uint32_t tick 0; void SysTick_Handler(void) { if (tick 0) tick--; } void Relay_On_With_Timeout(uint32_t ms) { Relay_On(); tick ms; while (tick 0) { // 这里可以处理其他任务比如读卡 } Relay_Off(); }参数说明tick 是全局变量SysTick 每 1ms 中断一次。Relay_On_With_Timeout 传入 3000 就是 3 秒。注意 while 里不要放阻塞操作否则超时不准。我自己的习惯是每次做完门禁系统先不急着写论文而是把实物放在桌上连续刷 100 次卡看有没有一次失败。如果有就查电源和接线如果没有再写文档。因为答辩时老师最可能问的不是原理而是“你这个稳定吗”。希望帮到你。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑