ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

STM32口罩识别门禁系统:源码原理图与联调实战解析

STM32口罩识别门禁系统:源码原理图与联调实战解析 STM32 口罩识别门禁系统这类项目对很多嵌入式初学者来说第一眼会觉得门槛很高既要图像识别又要门禁控制还要解决误判和稳定性。但如果你真正拿到一份免费开源的源码和原理图会发现项目重点并不是把模型训练得多复杂而是把 STM32、摄像头识别模块、继电器或舵机、门锁执行器串成一条清晰的控制链路。它解决的实际问题很直接判断门口人员是否佩戴口罩再根据结果决定放行还是报警。如果你准备拿这套方案做课程设计或者想学习 STM32 与前端识别模块之间的配合这个项目很适合当模板。它的价值不只是“能识别口罩”而是把串口通信、GPIO 控制、状态提示、硬件联动完整地串在了一个真实场景里。接下来我按实际落地顺序拆开讲先讲系统分工再讲源码和原理图怎么配合最后给出编译、接线、联调、排错的具体流程。1. 先拆任务口罩识别到底跑在 STM32 哪一层1.1 主控和图像识别模块要分开看STM32 芯片本身有很多型号不同型号算力差异很大。口罩识别门禁系统里最常见的情况是识别工作由摄像头前端或者独立视觉识别模块完成STM32 作为主控接收识别结果然后驱动门锁、蜂鸣器、OLED 显示等外设。这里的边界很重要。STM32 不是不能跑轻量模型但在低主频、少内存、没有硬件加速的型号上让它直接对摄像头图像做口罩检测往往会导致画面帧率低、处理卡顿、主循环被阻塞。而门禁系统需要的是“快速判断加稳定动作”所以项目结构一般会拆成两个角色图像识别端负责采集图像判断有没有戴口罩输出结果。STM32 主控端负责接收结果执行门禁逻辑控制锁、指示灯、声音提示。哪怕你下载的工程文件里没有独立视觉模块源码只要看到 STM32 通过串口接收一帧异常识别结果就能确认这个分工模式。1.2 串口是两边沟通的主要通道图像识别端与 STM32 之间最常走的是串口通信。识别端把结果编码成一帧数据发送给 STM32STM32 的串口接收中断解析出结果再决定是否开门。这里的关键不是代码本身难写而是你要先知道帧格式。有的项目用一个标识符加状态位比如 0xAA 0x01 表示佩戴口罩0xAA 0x00 表示未佩戴有的项目直接发字符串。还有的项目会发送两到三位识别状态比如“无人、有人戴口罩、有人未戴口罩、识别超时”。如果收到的源码里没有明确注释建议先打开串口初始化部分的回调函数比如 HAL_UART_RxCpltCallback看看它拿到的 data 做了什么判断。这是理解主控逻辑最快的方法。1.3 这个分工直接影响原理图阅读顺序如果你手里有原理图不要一上来就从左上角看到右下角。按功能区块找会快很多电源区块看供电分成几路有没有给电锁独立供电。主控区块看 STM32 型号、晶振、复位电路、下载口。通信区块寻找串口引脚定义确定接哪个串口。执行区块看门锁驱动引脚、继电器类型、是否加隔离。提示区块看蜂鸣器、指示灯、屏幕接在哪些 GPIO 上。先确认这三个区块后面的接线就不会乱。原因很简单代码逻辑跟随引脚只要引脚地址对应错了程序写得再正确也运行不出现象。2. 拿到源码和原理图后先做环境确认2.1 目录结构先扫一遍重点看 README 和原理图版本免费开源项目最常见的坑是下载包里的文件跟说明文档不是同一个版本。你手里这份源码即使标题写得很完整也要先打开一层目录确认以下内容源码工程Keil 工程文件、CubeIDE 工程文件或 GCC 工程文件。原理图格式PDF、AD 工程还是立创 EDA 工程。固件依赖是否带完整的 STM32 HAL 库还是需要自己补。硬件说明是否标注了 STM32 型号、摄像头模块型号、电锁驱动方式。我的建议是先找 README 或者“说明.txt”把里面提到的串口波特率、接线引脚、芯片型号抄下来再开工。这一步看起来很基础但能帮你少走很多弯路。如果原项目只给了一版 PDF 原理图没有芯片型号标注那你就要能通过芯片丝印和电路判断出来。2.2 先确认目标 STM32 型号再开工程你拿到的源码可能是在 STM32F103C8T6 上调试的也可能是在 STM32F407ZGT6 上调试的。两颗芯片管脚不兼容外设资源也不一样。如果你手头板子与源码目标不同不能直接烧录要先做这几件事打开工程里 Device 或芯片选择。确认原理图和代码里的 GPIO 引脚能否对应到新芯片。检查串口中断、定时器、时钟配置是否超出当前芯片资源。留意系统主频STM32F103 常见 72MHzSTM32F407 可到 168MHz延时和外设时序会受影响。如果只是从 F103 换到同系列另一颗 F103且引脚相同通常改动较小。如果是跨系列替换比如 F1 换 F4建议先重新配置时钟和引脚再考虑业务逻辑移植。2.3 确认 Keil 和芯片支持包版本很多初学编译失败都是因为 Keil 里没有对应芯片的 Device Pack。打开源码工程后如果页面提示找不到芯片或头文件大概率不是代码问题而是环境问题。在 Keil 中常见操作是检查 Device FamilyPack。不同版本 Keil MDK 对老工程支持度不同老工程用 MDK5 打开时可能会提示需要装相应包。装完包后再确认工程配置里的宏定义比如 USE_HAL_DRIVER、STM32F407xx必须与目标芯片一致。宏定义不正确会导致 HAL 库代码编译报错或者芯片时钟初始化失败。3. 编译和烧录按最小可行路径走3.1 打开工程后第一步不是直接按 F7常见新手的做法是打开工程直接编译报错后对着错误乱改。更稳的流程是先在工程设置里选择目标芯片型号确认与原理图一致。配置烧录器类型比如 ST-Link、J-Link 还是串口 ISP。检查 Flash Download 区域是否选了对应容量。确认宏定义头文件路径存在没有残留的本地绝对路径。再按编译分批看警告和错误。如果你下载的源码目录里没有 .uvprojx 工程文件而是在 CubeIDE 环境里开发的那就用 STM32CubeIDE 打开。直接改扩展名去强行导入 Keil 是行不通的。3.2 常见三种烧录方式STM32 烧录并不是只有一种方法。选择哪种取决于你买了什么下载器和开发板有没有自动串口下载电路。烧录方式连接方式优点常见限制ST-Link SWDSWDIO、SWCLK、GND、3.3V速度快可在线调试需要板载或外接 ST-LinkJ-LinkSWD 或 JTAG调试功能强兼容芯片多价格偏高线序要小心串口 ISPBOOT0 拉高后复位只要 USB-TTL成本低不能在线调试下载速度一般我实际更推荐先用 ST-Link SWD 调试一次因为门禁源码需要跑起来后看变量状态。如果手头只有 USB-TTL也能烧但排查串口数据时要多准备一个 USB-TTL做接收不然会占用同一个串口。3.3 烧录后验证两件事程序有没有跑UART 有没有输出如果代码烧录成功但板子没有现象不要立刻去改 GPIO。先确认两件事主控有没有进入 main 函数。串口有没有周期性或即时打印调试信息。结合现有源码结构初次验证可以看 LED 或 OLED 在上电后是否初始化成功。如果屏幕直接有开机画面说明主控运行基本正常后续问题多半出在识别模块或者串口通信上。如果屏幕没反应先用调试器在下断点或者用示波器量主控晶振确认系统时钟是否起来了。4. 原理图和接线从纸面到开发板4.1 看懂代码里的引脚再对照原理图画连接表原则是“代码引脚为主原理图为辅”。因为每个开源项目命名习惯不同有的管引脚叫 DOOR有的叫 Lock有的叫 RELAY。你得先看代码注释中定义的 GPIO再回原理图里找对应网络标号。举个例子如果代码里是这么定义的#define LOCK_PIN_PORT GPIOA #define LOCK_PIN GPIO_PIN_8 #define DETECT_STATE 1那么 LOCK_PIN 就是主控输出控制门的引脚。原理图里 GPIOA8 一般会连到继电器驱动模块的输入脚或者三极管基极。如果发现原理图里该引脚被连到 OLED 或者其他外设说明你手里的原理图版本与代码版本不一致。这是最容易踩坑的地方下载的是最新代码但原理图是旧版本两边的引脚对不上。此时应以代码为准重新看硬件实际连接再调整接线。4.2 接线方案以一个典型串口识别模块示例很多 STM32 口罩识别项目会采用独立摄像头识别模块模块把口罩结果通过串口发出来。STM32 这边接线大体是这样摄像头识别模块 TXD ---- STM32 USARTx_RX 摄像头识别模块 RXD ---- STM32 USARTx_TX 摄像头识别模块 GND ---- STM32 GND 摄像头识别模块 VCC ---- STM32 3.3V 或 5V这里要注意TX 和 RX 是交叉连接的。摄像头发送端接 STM32 接收端STM32 发送端接摄像头接收端。不要两根线都同名直连那样收不到数据。代码里面可能需要配置串口中断接收// 伪代码仅示例 uint8_t rx_data 0; void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart-Instance USART1) { // 根据数据帧判断口罩识别结果 if (rx_data 0x01) { // 佩戴了口罩执行开门动作 open_door(); } else if (rx_data 0x00) { // 未佩戴口罩执行报警提示 alarm_notice(); } HAL_UART_Receive_IT(huart1, rx_data, 1); } }上面的片段只是为了展示主控逻辑结构不代表你下载源码里的确切实现。如果你打开源码看到的不是这样就去找工程里真正处理识别结果的函数。4.3 门锁和继电器不要直接挂在 STM32 引脚上原理图里最容易让人忽略的部分是门锁驱动。STM32 一个 GPIO 通常只能输出几毫安到二十毫安左右电流直接驱动电磁锁、继电器线圈、舵机都是不现实的。即使能勉强带动STM32 电源也会被拉垮导致复位、重启、屏幕闪烁。正确做法是通过三极管、MOSFET、继电器模块或专用电机驱动板去控制电锁。STM32 GPIO --- MOS 管/继电器模块输入端 --- 独立电源 12V --- 电磁锁这里有两个关键点控制电源与 STM32 电源要共地否则信号无法形成回路。电锁电源不一定用 3.3V通常独立供电不能直接用电锁电源给 STM32 供。实际项目中我会把“开锁”分成两步测试。第一步先看 GPIO 有没有正确翻转第二步再接上电锁观察动作。如果一接上电锁 STM32 就复位先查是不是继电器线圈反压、电源功率不足或者共地没接好。5. 门禁联调单功能验证后再做完整流程5.1 先跑最简单的“无人通过”状态联调不能上来就站在摄像头前测试口罩因为影响识别的因素很多很容易分不清问题是出在识别端还是 STM32 控制端。更稳的是先测试摄像头没有目标时模块是否输出一个确定的空闲状态。比如串口会周期返回“无人”或保持静默。如果这个状态都不稳定那就不用测后面开锁了。通过后再拿样本测试戴普通口罩通过。没戴口罩通过。手持口罩放在嘴前。侧脸加帽子。每种情况记录结果。目标不是追求永远正确而是确定主控逻辑是否跟随识别结果开关门。真实项目里单一摄像头方案本来就有视角、遮挡、同色背景等限制所以不要因为某一次没识别出来就觉得系统完全坏了。5.2 开锁逻辑要设置延时的原因门禁开锁通常不是一直把锁打开而是给一个短暂通电时间让门可以拉开时间到了自动闭锁。如果没有延时闭环一直维持开门信号可能出现两个问题电磁锁长期通电发热缩短寿命。人可以尾随进入没有任何通行记录区分。在代码里通常会看到这样的逻辑void open_door(void) { // 打开门锁 HAL_GPIO_WritePin(LOCK_PIN_PORT, LOCK_PIN, GPIO_PIN_SET); // 延时一段时间后关闭 HAL_Delay(3000); HAL_GPIO_WritePin(LOCK_PIN_PORT, LOCK_PIN, GPIO_PIN_RESET); }但是这个延时是有代价的。如果你在 main 循环的同一线程里使用 HAL_Delay延时期间单片机干不了别的事比如串口连续到达的识别结果就可能丢失。对课设或学习场景这种阻塞式逻辑一般够用。如果要做得更稳定可以把延时改成非阻塞定时器状态机主控收到开门指令后执行定时器计时时间到关锁同时还能继续接收识别数据。收到合法结果 - 置位开门标志 - 定时器计时 3 秒 - 时间到后关锁 - 恢复待机5.3 结果判断标准测试过程中建议记录这样一张表测试场景识别模块输出STM32 反应GPIO 状态门锁状态无人经过无目标不动作低电平闭锁正确佩戴口罩识别为已佩戴执行开门高电平 3 秒开锁未佩戴口罩识别为未佩戴执行报警不变或闪烁闭锁模块未上电无输出无动作低电平闭锁如果 GPIO 状态变化正确但门锁不动那问题在继电器、独立电源或门锁本身。如果 GPIO 状态根本没变化那就要向前端查识别输出和串口帧。6. 常见问题排查链路6.1 系统上电后完全没反应按下面的顺序排查不要把时间先花在代码上看电源灯是否亮测量主控电源引脚电压。看下载器能不能识别到芯片。用调试器在线全速运行在 main 函数入口打断点。如果代码停在启动文件里持续跑不进去检查晶振和 BOOT0 电平。如果 BOOT0 被拉到高电平代码可能进入 ISP 模式。这里最容易漏掉的是 BOOT0。很多板子默认有跳帽如果被插到 1 位置烧录后程序不会正常运行必须拨回 0 再复位。6.2 摄像头已经在上电但 STM32 始终收不到口罩状态多数情况下不是“没有识别”而是“识别结果没传过来”。建议这样排查先把摄像头模块单独上电看它自己的运行指示灯和画面是否正常。用 USB-TTL 直接接摄像头的 TX 和 GND在电脑串口助手里看有没有数据。如果电脑端能看到数据说明摄像头模块正常问题在 STM32 串口接线或中断代码。如果电脑端也看不到数据说明摄像头模块本身没有正确输出检查模块固件与串口设置。如果 STM32 串口能收到数据但是识别结果不稳定常见原因是波特率偏离。摄像头模块实际波特率与你代码配置不一致时偶尔能收到几个正确字节但大部分是乱码。用串口助手把波特率从 9600 到 115200 多试几档先确认正常输出频段再去改 STM32 程序。另外还有一个典型环境问题识别模块和 STM32 的 GND 没共地。如果不把两边地线接在一起串口信号没有统一参考平面接收端很容易收到乱码或完全无法触发中断。6.3 开锁失败不能只怀疑代码一次门禁测试失败时明确告诉你先看三层第一层STM32 的 GPIO 有没有翻转。用万用表量一下引脚电压或者接一个 LED 指示灯看是否亮起。第二层继电器有没有切换。如果 GPIO 翻转了但是继电器不动作就是驱动部分问题。检测继电器模块输入电压、模块供电电压。 第三层门锁有没有得到有效供电。继电器切换了但锁不动可能门锁电源功率不足、锁体电压不够、接线太细。门禁系统是“主控驱动执行器电源”多级链路每一级都可能断。调试时逐级往后查比反复改主控代码有效得多。6.4 修改源码后编译报错针对已有源码项目报错信息很有用。如果你改动后报错 “xxx is not defined”先确认头文件路径有没有被 Keil 工程包含。如果你添加了新的 c 文件但没有加入工程编译器根本不会编译它。还有一类常见错误是“Flash Download Failed”。这个不一定是代码报错通常是下载器连接错误或者芯片保护开启。先重新插拔下载器再检查 SWD 四根线是否都接好最后在 Flash Download 里执行擦除。如果芯片有读保护需要先执行全片擦除才能重新烧录。不同芯片保护级别不一样普通 ST-Link 工具里可以看到相应选项。这里建议不要动不动就选全片擦除有可能会把之前保存的出厂数据清掉但芯片本身一般不会损坏。7. 拿到这套代码以后可以怎么继续扩展7.1 从 GPIO 点灯式关门改成继电器控制锁很多学习项目里的开门动作是点亮 LED 或者驱动继电器没有真正接电锁。如果你要做成演示效果可以保留 LED 提示。如果你想做成接近真实门禁的模型就需要把执行器从 LED 换成继电器加电锁模块。改动时要注意电源是否足够电锁需要独立供电。门锁开启时间要控制不能一直供电。要有明显提示比如门锁动作同时蜂鸣器短鸣一声。建议增加一个手动按钮作为应急开门手段也便于调试。7.2 代码层面可以加入状态机目前的门禁逻辑如果只是简单 if/else识别结果连续到来时每次都会重新执行 3 秒延时。如果想实现“识别到未戴口罩后锁定 10 秒”“最多连续报警三次”建议改成状态机而不是在回调函数里直接延时。阶段状态可以定义为IDLE - CHECK - DOOR_OPEN - ALARM - CLOSE - IDLE这样排程更清晰边界逻辑也好改。连续未佩戴口罩、多次非法尝试、超时无人通过等场景都能放进状态机里处理。7.3 不要忽略日志和调试口如果你准备长期调试门禁系统一定要保留一个调试串口输出日志。格式建议统一[时间字段] 当前状态: ... [时间字段] 识别结果: ... [时间字段] 执行动作: ...不要只在代码里留一堆空行和 printf却没有说明每行代表什么。有了日志后联调时你很容易判断问题是出在图像端、串口端还是主控决策上。真实项目里日志不是附加功能而是排错的基础工具。8. 边界提醒这只适合学习与验证场景最后我必须说清楚一个边界这种基于普通摄像头模块加 STM32 的口罩识别门禁系统最合适的场景是嵌入式学习、课程设计和原型验证不适合直接当成生产级安全检查设备。主要原因有三点图像识别通常不包含活体检测拿一张照片也能通过。普通摄像头对光线、角度很敏感弱光下表现会明显下降。门禁安全性不只是识别口罩还涉及权限、记录、回看、防尾随等多层问题。如果你只是学 STM32 外设和通信联动这套源码和原理图是很好的学习材料。它能让你把串口、GPIO、中断、继电器这些分散的知识点串联起来。如果是毕业设计要做完善系统就要在这个基础上去补数据库、上位机、远端日志和更可靠的识别方案。真正落地时最该盯住的不是功能列表有多漂亮而是输入图像稳不稳、串口协议对不对、门锁驱动电源够不够、代码有没有冗余延时。先把这几条跑通再把功能一项项加上去比一开始就堆所有模块要省事很多。
返回列表