ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

STM32口罩识别门禁系统:视觉模块串口通信与继电器控制实战解析

2026/9/5 21:59:13 拓冰建站 浏览量
STM32口罩识别门禁系统:视觉模块串口通信与继电器控制实战解析 1. 项目背景与系统概述之前整理 STM32 与边缘视觉项目时我发现很多同学手里有一套“STM32 口罩识别门禁系统”的开源资料但要么被资料包里的代码结构劝退要么不知道怎么看原理图要么把视觉模块识别到的结果接到 STM32 后逻辑处理得不对。这篇文章就以这类开源项目比如编号 0465A 的常见版本为主线把硬件组成、识别原理、串口通信、门禁控制逻辑、原理图阅读要点和排错思路完整梳理一遍。这类系统非常适合三类读者刚学完 STM32 基础外设想找一个“单片机 传感器 执行机构 通信协议”综合项目的同学准备做毕业设计、课程设计或竞赛作品需要兼顾硬件图纸、上位端代码和演示效果的学生从事门禁、考勤、闸机等终端设备开发想了解低成本口罩识别/人脸识别辅助判断方案的工程师。学完本文后你可以读懂这套开源项目的源码结构与原理图也能自己搭建一个最小可用版本视觉模块负责“看”STM32 负责“想”和“动”最后通过继电器/电磁锁执行开门动作。1.1 为什么要用“STM32 视觉模块”方案纯 STM32 能否直接跑口罩识别这个问题很多初学者都会问。广义上STM32F4/H7 系列虽然能跑轻量级神经网络但模型推理、摄像头采集、显示、门控逻辑全部放在一颗 MCU 上开发难度和成本都会明显上升。大多数开源口罩识别门禁项目采用这种折中方案视觉模块完成图像采集与识别常见硬件为 OpenMV、K210 摄像头模块或树莓派/RK3588 上位机STM32 作为主控制器负责接收视觉模块的判断结果并控制继电器、电磁锁、舵机、LED 和语音播报两者之间用 UART 串口通信协议足够简单可靠。用 STM32 做主控的好处很明显外设资源丰富、代码生态成熟、继电器驱动电路设计资料多、生产制版成本低而且门禁逻辑并不需要很强的算力。真正吃算力的模型推理已经被视觉模块卸掉了STM32 只需要处理“收到结果 - 判断 - 动作”这类确定逻辑。对于“为什么不是 STM32 直接接普通摄像头”这个问题也要多说一句普通 OV7670/OV2640 在 STM32 上一般只能拿到原始图像数据若没有经过足够训练的图像分类器做口罩识别会非常吃力。视觉模块相当于把“深度学习算法落地”这件事隔离到独立硬件上项目可维护性反而更高。1.2 系统整体架构与工作流程整体架构可以划分为三个层次感知层摄像头与视觉模块。摄像头采集画面视觉模块内部运行口罩检测/人脸检测模型判别人脸是否佩戴口罩。决策层STM32 主控。接收串口数据帧解析出“未戴口罩”“已戴口罩”“识别失败”等状态结合门禁权限、应急按钮、手动开门信号进行综合决策。执行层继电器、电磁锁/电插锁、舵机、LED 指示灯、蜂鸣器或语音播报模块。典型的工作流程如下人员靠近门禁视觉模块检测到人脸并判断是否佩戴口罩视觉模块将结果封装为约定好的帧格式通过串口发送给 STM32STM32 对帧头、校验字节完成校验避免误动作若结果为“已佩戴口罩”STM32 控制继电器吸合或舵机转动电磁锁断电/开锁同时 LED 显示绿色语音播报“体温正常请通行”之类的提示若结果为“未佩戴口罩”或“未识别到人脸”STM32 不动作LED 显示红色蜂鸣器发出短促提示音门禁保持一段时间后自动关闭系统回到待机状态。这里的“未佩戴口罩不准通行”只是功能演示实际安装在校园、社区、医院时通常还会叠加刷卡、密码、测温等权限判断不能只看单一视觉结果。后续第 7 节我会重点展开安全和合规设计。2. 系统开发环境准备无论你是直接下载开源工程还是希望按源码自己重写一遍环境都需要提前准备。下面按“硬件清单、软件工具、工程目录结构”三部分说明。不同开源版本的芯片型号和电路有差异本文以常见的 STM32F103C8T6 主控、OpenMV/K210 视觉模块、继电器驱动电磁锁的方案为例。如果手头资料是其他型号配置思路是一样的。2.1 硬件清单模块说明作用STM32 主控板常见如 STM32F103C8T6 最小系统板处理串口数据、控制门禁输出视觉识别模块OpenMV、K210 MaixPy、树莓派等图像采集 模型推理 串口发送USB 转 TTL 模块CH340/CP2102下载调试、查看 STM32 日志继电器模块低电平或高电平触发注意选择 3.3V/5V 兼容版本控制电磁锁通断电磁锁或电插锁12V 供电的常见型号门禁执行机构12V 电源及降压电路12V - 5V/3.3V整机供电LED、蜂鸣器/语音模块可选声光提示按键常开按键应急开门/允许通行杜邦线/排针/PCB根据原理图制作连接与固定这里有一个容易踩的坑视觉模块如果使用 USB 供电电流需求可能超过 STM32 板上 LDO 的承受范围。不要用 STM32 板子的 3.3V 引脚去给摄像头模块供电推荐独立供电并把多个模块的 GND 连在一起否则串口通信会出现乱码。2.2 软件开发工具芯片固件库STM32CubeF1 固件包或者较老的 SPL 标准库。给 STM32 写串口解析逻辑时HAL 库代码可读性更高便于初学者调试。集成开发环境Keil MDK 是主流选择也可以用 STM32CubeIDE。Keil 工程版本建议保持 5.x 之后安装好对应器件支持包否则打开源码会提示找不到芯片。串口助手XCOM、SSCOM、MobaXterm 都可以。视觉模块 IDEOpenMV IDE 或 MaixPy IDE方便在线调试摄像头画面。原理图查看软件Altium Designer、嘉立创EDA、KiCad、Cadence 等。开源项目如果提供 PDF 版原理图则用浏览器直接查看。版本说明不建议照抄网上教程请以你手头源码工程为准。很多开源工程用 STM32F103C8T6但有些版本已经迁移到 STM32F407、GD32 等平台固件包、启动文件和启动模式都要对应修改。2.3 项目目录结构一个典型的 STM32 端工程目录会分成这样0465A_mask_door/ ├── Doc/ # 使用说明、引脚对照表 ├── Hardware/ # 原理图 PDF │ └── SCH_0465A.pdf ├── MDK-ARM/ # Keil 工程文件 │ ├── project.uvprojx │ └── ... ├── Src/ │ ├── main.c │ ├── uart_protocol.c │ ├── door_control.c │ └── system_clock.c ├── Inc/ │ ├── uart_protocol.h │ └── door_control.h └── VisionModule/ # 视觉模块端源码(MicroPython/C) ├── mask_recognition.py └── send_protocol.py视觉模块端的代码往往不随 Keil 工程一起编译需要单独打开这一点初学者要留意。若你只下载了 STM32 端源码却没有把视觉模块程序烧录进摄像头模块系统是不可能自动识别的。3. 核心原理拆解3.1 口罩检测与识别原理口罩识别从算法上讲属于目标分类或目标检测问题而不是“看口罩颜色”这么简单。视觉模块摄像头拿到 RGB 图像后先做人脸检测再从人脸区域提取特征判断口鼻区域是否被口罩覆盖。常见实现方案有传统图像处理方案检测人脸区域后根据肤色像素占比判断嘴部区域有没有被遮挡。优点是无需训练模型缺点是受光线和肤色影响大误判率较高。轻量级神经网络方案将训练好的模型量化部署到 K210、OpenMV 或树莓派上。比如 K210 使用 KPU 加速器跑 kmodel 文件OpenMV 部分较高版本支持加载经过转换的网络模型。上位机方案树莓派/RK3588 运行 YOLOv5、YOLOv8 或 MediaPipe 等框架再把结果发送给 STM32。开源项目选择哪种算法取决于视觉模块芯片的算力。K210 这类带 KPU 的芯片跑 MobileNet 或 Tiny YOLO 比较常见。如果算法在本地帧率不高可以把输入分辨率调低例如使用 QVGA320x240或 VGA640x480作为检测输入而不是直接送大图。3.2 STM32 与视觉模块的串口通信协议这是整套系统最容易出 bug 的地方之一。不能像调试串口收发那样直接发一个字节“0x01”就算完“0x01”在线上任何一个干扰都可能被误判成合法状态。工程上会自定义一帧数据至少包含帧头、消息类型、数据长度、数据域和校验字节。给出一种通用帧格式偏移内容长度说明0帧头 11 字节0xAA1帧头 21 字节0x552功能码1 字节0x01 表示识别结果3数据长度1 字节N4数据域N 字节状态值4N校验字节1 字节累加和或 CRC85N帧尾1 字节0x0D比如视觉模块识别到“人员已佩戴口罩”可发送AA 55 01 01 01 58 0D数据域中的 0x01 表示允许通行。如果识别到未佩戴口罩则是AA 55 01 01 00 57 0DSTM32 中断接收一帧数据后不要马上改变外设状态要先做状态机解析校验通过后再更新结果这样能过滤大部分总线毛刺。3.3 门禁输出控制电路原理门禁系统的执行机构大体分两类继电器控制电磁锁电磁锁是一种大电流设备如果直接接在 STM32 GPIO 上灌电流或拉电流不够还会产生反向电动势可能烧毁单片机引脚。即使使用继电器模块也要注意模块上有无三极管驱动和续流二极管。推荐使用带光耦隔离的继电器模块控制端和输出端分开供电。舵机控制挡板/门栓舵机信号只需要 50Hz 左右的 PWM 波STM32 通过定时器输出不同占空比改变舵机角度。相比继电器舵机没有大电流通断干扰更小但不适合直接带动电插锁。使用继电器模块时控制逻辑可能是“高电平触发”也可能是“低电平触发”两者不能简单替换。如果项目原理图里标注的是低电平触发而你买到高电平触发模块会发现 STM32 上电瞬间门锁误动作这是很危险的隐患。3.4 状态提示与应急逻辑优秀的工程不仅包含主控逻辑还应该有声光提示和人工兜底机制识别成功绿色 LED 亮语音模块播放“请通行”识别失败红色 LED 亮蜂鸣器短鸣系统异常红色 LED 闪烁通过串口或屏幕输出错误码长时间未关门如果装有门磁传感器发出“门未关闭”提示管理按钮/钥匙开关在断电或识别失效时供管理员手动操作。从稳定性角度讲如果视觉模块长时间没有回应STM32 也应该超时复位通信状态避免系统一直卡在等待状态。4. 完整实战最小可运行的口罩识别门禁为了让你不只停留在“看资料包”层面这一节我们搭一个最小可运行版本。代码会分成视觉模块端与 STM32 端两者通过串口帧通信。这里给出的代码是简化示例思路不是某个项目文件的无脑完整代码你需要按实际开发板、引脚和库版本调整。4.1 硬件连接规划先规划视觉模块与 STM32 的串口连接STM32 引脚视觉模块引脚说明PA2 (USART2_TX)RXSTM32 发送数据PA3 (USART2_RX)TXSTM32 接收数据GNDGND共地必须连接PA1继电器 IN控制电磁锁PA0按键管理员允许开门如果视觉模块的串口电平是 3.3V可以直接使用。若摄像头模块是 5V 的 TTL 电平则在连接 STM32 RX 前使用电平转换模块或查看视觉模块是否允许把电平切换到 3.3V。不同 STM32 开发板的串口号不同请查看原理图确认。若使用 USART1则默认引脚为 PA9(USART1_TX) 和 PA10(USART1_RX)。入门时建议先用 USB 转 TTL 分别测试“STM32 通过串口向电脑发数据”和“视觉模块向电脑发数据”两者都正常后再互连。4.2 STM32CubeMX 外设配置打开 STM32CubeMX按以下步骤创建工程选择芯片型号例如 STM32F103C8T6配置时钟源在 RCC 中把 HSE 设为 Crystal/Ceramic Resonator配置 USART2 异步模式波特率设为 115200数据位 8无校验停止位 1配置 GPIOPA1 设置为 Output别名为 RELAY_CTRLPA0 设置为 Input可配置上拉别名为 MANUAL_OPEN_KEYPA5 设置为 Output别名为 LED_GREENPA6 设置为 Output别名为 LED_RED配置系统时钟树为 72MHz生成代码时会自动配置设置工程名与工具链生成初始代码。在 HAL 库中如果启用了 USART2 中断请在main.c中使用HAL_UART_Receive_IT(huart2, rx_byte, 1)以字节为单位启动接收。也可以使用HAL_UART_Receive_DMA()但对小数据量而言中断接收足够。4.3 视觉模块端代码实现以下以 OpenMV 系列为例K210 MaixPy 的 API 存在差异但帧构造逻辑通用。# VisionModule/main.py import sensor import image import time from pyb import UART # 初始化摄像头 sensor.reset() sensor.set_pixformat(sensor.RGB565) sensor.set_framesize(sensor.QVGA) sensor.skip_frames(time2000) # 初始化串口 uart UART(3, 115200, timeout_char1000) # 返回 0x01 表示已佩戴0x00 表示未佩戴0x02 表示未识别到人脸 def mask_detect_status(): # 实际项目中这里会加载训练好的分类器/CNN模型 # 例如根据模型热度判断 person_with_mask model.predict(img) # 本文不展开模型训练过程只演示协议封装 person_with_mask 0x01 return person_with_mask def send_frame(status): # 帧头1 帧头2 功能码 数据长度 数据域 校验和 帧尾 data bytearray([0xAA, 0x55, 0x01, 0x01]) data.append(status 0xFF) checksum 0 for b in data: checksum (checksum b) 0xFF data.append(checksum) data.append(0x0D) uart.write(data) while True: status mask_detect_status() send_frame(status) time.sleep_ms(200)如果你手头是 K210 摄像头模块通常需要引入fpioa_manager和machine.UART将摄像头引脚复用为 UART 引脚再用kpu加载.kmodel模型文件。帧构造部分保持一致。由于不同固件版本的加载函数名称不同建议直接阅读开源项目的VisionModule目录。4.4 STM32 端核心代码实现STM32 端要完成三件事接收完整帧、解析状态、根据状态控制 GPIO。首先是串口接收回调放在整个工程中// 文件路径Src/usart_com.c #include usart_com.h #include door_control.h // 接收状态机 typedef enum { FRAME_STATE_WAIT_HEAD1, FRAME_STATE_WAIT_HEAD2, FRAME_STATE_WAIT_FUNC, FRAME_STATE_WAIT_LEN, FRAME_STATE_WAIT_DATA, FRAME_STATE_WAIT_CHECK, FRAME_STATE_WAIT_TAIL } FrameState; uint8_t rx_byte 0; uint8_t frame_buf[16]; uint8_t frame_len 0; uint8_t data_index 0; uint8_t sum_check 0; FrameState state FRAME_STATE_WAIT_HEAD1; void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart-Instance USART2) { // 串口字节处理函数 uart_parse_byte(rx_byte); HAL_UART_Receive_IT(huart2, rx_byte, 1); } } void uart_parse_byte(uint8_t byte) { switch (state) { case FRAME_STATE_WAIT_HEAD1: if (byte 0xAA) { state FRAME_STATE_WAIT_HEAD2; frame_len 0; data_index 0; sum_check 0; } break; case FRAME_STATE_WAIT_HEAD2: if (byte 0x55) { state FRAME_STATE_WAIT_FUNC; } else { state FRAME_STATE_WAIT_HEAD1; } break; case FRAME_STATE_WAIT_FUNC: if (byte 0x01) { state FRAME_STATE_WAIT_LEN; } else { state FRAME_STATE_WAIT_HEAD1; } break; case FRAME_STATE_WAIT_LEN: frame_len byte; data_index 0; sum_check 0xAA 0x55 0x01 frame_len; state FRAME_STATE_WAIT_DATA; break; case FRAME_STATE_WAIT_DATA: if (data_index frame_len data_index 16) { frame_buf[data_index] byte; sum_check byte; } if (data_index frame_len) { state FRAME_STATE_WAIT_CHECK; } break; case FRAME_STATE_WAIT_CHECK: if (byte sum_check) { state FRAME_STATE_WAIT_TAIL; } else { state FRAME_STATE_WAIT_HEAD1; } break; case FRAME_STATE_WAIT_TAIL: if (byte 0x0D) { // 帧合法取第一个数据字节作为识别结果 door_handle_mask_status(frame_buf[0]); } state FRAME_STATE_WAIT_HEAD1; break; default: state FRAME_STATE_WAIT_HEAD1; break; } }这段代码里sum_check采用最简的“累加和取低 8 位”更适合学习演示。正式项目中建议使用 CRC8 或 CRC16降低误判概率。门控逻辑放在独立文件里// 文件路径Src/door_control.c #include door_control.h #include main.h // 开锁保持时间 #define OPEN_DELAY_MS 3000 // 未戴口罩提示时间 #define ALARM_DELAY_MS 1000 void door_handle_mask_status(uint8_t status) { if (status 0x01) { // 已佩戴口罩继电器吸合绿灯亮 HAL_GPIO_WritePin(RELAY_CTRL_GPIO_Port, RELAY_CTRL_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, GPIO_PIN_RESET); // 开锁时间延时后自动关闭 HAL_Delay(OPEN_DELAY_MS); HAL_GPIO_WritePin(RELAY_CTRL_GPIO_Port, RELAY_CTRL_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin, GPIO_PIN_RESET); } else if (status 0x00) { // 未佩戴口罩红灯亮不打开门锁 HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, GPIO_PIN_SET); HAL_Delay(ALARM_DELAY_MS); HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, GPIO_PIN_RESET); } else { // 未识别到人脸不做动作 } }如果你使用的是标准外设库那么 GPIO 函数名会不同但状态机处理思路完全一致。另外在实际项目里不建议在中断回调中直接调用HAL_Delay()更推荐用一个“开门计时标志”配合主循环查询但本文为清晰展示控制逻辑先采用延时方式。4.5 编译、下载与整机验证STM32 端编译下载步骤打开 Keil 工程选择正确的芯片型号点击 Options - Debug选择 ST-Link 或 J-Link在 Utilities 页面勾选 Reset and Run编译无误后下载。视觉模块端则用 OpenMV IDE/MaixPy IDE 连接模块运行主脚本。整机验证时如果只接 STM32 而没有摄像头模块可以用 USB 转 TTL 把电脑串口接到 STM32 的 USART2 RX 引脚手动发送以下两帧数据测试反应发送AA 55 01 01 01 58 0D预期继电器吸合约 3 秒后释放绿色 LED 亮。发送AA 55 01 01 00 57 0D预期红色 LED 亮约 1 秒继电器不动作。由于 0x01 0x57 才是 0x58两帧数据都符合累加和规则所以可以测试状态机。学习时把这个测试步骤放在前面可以确认 STM32 端解析逻辑没有问题再接入视觉模块排查问题会高效很多。4.6 预期运行效果正常运行时视觉模块大约每 200ms 发送一帧结果。把一张真人照片或摄像头对着人脸已戴口罩时STM32 收到 0x01控制继电器吸合门锁释电打开未戴口罩时STM32 收到 0x00不执行开门动作红灯提示距离摄像头太远或人脸过小时视觉模块可能返回 0x02系统保持待机。注意很多开源项目的识别模型只针对成人面部儿童身高不够、人侧脸、口罩遮挡鼻子等情况下识别率会明显下降。测试时尽量在光线均匀、正脸、人脸占画面面积较大的条件下进行。5. 原理图阅读与分析要点拿到开源项目时不能只盯着源码看原理图能告诉你为什么 GPIO 会这样分配、为什么门锁用继电器而不是三极管直驱。下面按最小系统、电源与执行机构、通讯接口三部分展开。5.1 主控最小系统原理图主控最小系统由电源、晶振、复位、启动模式选择、下载电路组成。电源部分常见的是 5V 输入经过 AMS1117-3.3 降压成 3.3V给 STM32 供电。AMS1117 的输入输出端各有一只 10uF 和 0.1uF 电容用于滤波和抗高频噪声。看原理图时如果芯片供电脚附近没有去耦电容板子可能会在继电器动作瞬间复位。晶振部分如果使用 8MHz 外部晶振需要外接两个 20pF 左右的负载电容。有些最小系统板省掉了外部晶振直接用内部 HSI这时在源码里要把HSE_VALUE和时钟配置改成内部时钟模式。如果你下载的程序在别人的板子上能跑、在自己板子上不能跑先检查外部晶振是否焊接正常。启动模式 BOOT0 和 BOOT1 的跳线决定从 Flash 启动还是从系统存储器启动。STM32F103 中 BOOT0 拉低通常是从主 Flash 启动如果板子 BOOT0 被拉高下载后会复位进 ISP 模式程序不运行。5.2 电源与继电器驱动看门禁系统原理图时重点看继电器驱动部分的 BT1、BT2、BT3 等标注。如果继电器模块的原理图展开通常会包含光耦隔离让 MCU 侧与继电器驱动侧电气隔离三极管或达林顿管用 MCU 的小电流驱动继电器线圈的大电流续流二极管 D1继电器线圈在断电瞬间会产生反向电动势续流二极管可以吸收该电压避免损坏三极管或 GPIO继电器触点输出常开NO和公共端COM接到电磁锁回路。如果一个继电器模块没有续流二极管ST 官方不推荐直接使用否则电磁锁频繁开关时容易出现复位。电磁锁的供电通常不是 3.3V而是 12V。因此在整机原理图中需要看到 12V 电源如何接入5V 用于视觉模块还是其他传感器。电源地线要足够粗否则电磁锁吸合瞬间大电流会在 GND 上引起电压抬升导致串口通信乱码。5.3 通讯接口与传感器接口在原理图上找到视觉模块接口通常是 4pin 或 6pin 排针VCCGNDTXD视觉模块发送给 STM32RXDSTM32 发送给视觉模块可能还有 PWM 或 BOOT 引脚需要注意很多模块的 TXD/RXD 是交叉相连的即视觉模块的 TXD 接 STM32 的 RXD。如果照抄反了会出现“识别正常但 STM32 到不了数据”的现象。最佳做法是在原理图上把 UART_TX、UART_RX 的网络名追踪到主控引脚确认是否交叉正确。如果原理图中包含按键、LED、蜂鸣器、语音模块和温湿度传感器也要注意这些外设引脚与串口引脚是否冲突。比如你看到工程里初始化了 I2C 用的 PB6/PB7同时又定义了一个按键接在 PB6 上那么就需要检查是不是原理图版本和代码版本不匹配。6. 常见问题与排查思路6.1 常见现象与解决方案速查表问题现象常见原因解决思路STM32 串口收到乱码波特率不一致GND 未共地电源质量差统一 115200明确共地改用独立电源继电器在 STM32 上电瞬间误动作触发电平不匹配GPIO 默认电平不对查看原理图是高电平还是低电平触发程序中先初始化 GPIO 并在主循环前拉低门锁已动作但视觉模块状态一直未更新视觉模块没有收到/发送帧帧头校验不一致先电脑模拟帧测试 STM32再独立测试视觉模块串口输出STM32 能识别二维码但屏幕/继电器反应慢主循环 Delay 过长视觉模块发送周期过长降低发送周期为 100ms关键判断放到中断或短周期轮询中继电器吸合一次后不再动作继电器触点电流过大或粘连STM32 驱动能力不足更换合格继电器模块检查触点负载是否超过额定值Keil 下载时报 No Target Connected接线错误、驱动未安装或板子供电不足检查 SWDIO/SWCLK 是否接反按住复位键尝试下载视觉模块重启或画面花屏电流不足、线材过长使用独立稳压电源给摄像头模块单独供电6.2 串口乱码如何处理串口乱码几乎每个做过嵌入式的人都会遇到解决思路要按顺序执行检查波特率STM32 端设置 115200那么电脑串口助手和视觉模块端必须都是 115200不能有一端是 9600检查电平标准STM32 的串口引脚是 3.3V TTL 电平USB 转 TTL 模块需要支持 3.3V检查 GNDMCU、摄像头模块、USB 转 TTL 模块三者的 GND 必须连在一起检查串口接线TX 接 RXRX 接 TX不要同向连接排除电源干扰当继电器动作瞬间出现乱码说明 GND 上存在较大扰动应在继电器供电回路和 MCU 供电回路上增加电容或使用光耦隔离模块。6.3 电磁锁动作异常怎么查电磁锁不动作或误动作可按如下方法排查先用万用表量继电器输出端若继电器已闭合但锁不动作说明是锁的供电问题不是 MCU 问题若继电器未闭合但门锁动作则是常闭触点接线错误或者继电器模块触发极性接反如果程序中成功状态延时 3 秒但锁只打开 1 秒检查继电器模块供电是否被电磁锁线圈拉低必要时单独给继电器模块供 5V而不是从 MCU 板的 3.3V 取电若按键手动开门正常、自动识别时无法开门重点检查串口解析状态机是否被错误帧卡住。7. 工程化与合规建议7.1 逻辑安全设计口罩识别门禁系统本质上是一个“自动执行开锁”的电子系统安全风险不只是识别率这一项。工程上需要设计多层保护第一层视觉识别不是唯一权限。真实门禁还应叠加刷卡、密码、远程审批或现场安保人员确认。口罩识别的作用是提升通行效率而不是替代所有授权机制。第二层超时保护。系统判断“允许开门”后开锁时间应限制在 2 到 5 秒防止有人长时间挡住门禁后门锁一直打开。电磁锁本身通常有“断电开锁”或“通电开锁”两种类型调试前要确认安全状态。一般来说在火灾等紧急情况下门禁应自动进入逃生状态这通常是硬件保障不是软件唯一保障。第三层异常降级。当视觉模块故障或通信中断时系统应自动进入“人工模式”或“限制模式”不能因为识别不到人脸就永久锁死也不能在系统初始化阶段误开门。第四层应急手段。现场需要有管理员按钮、钥匙开关或机械解锁机构。按键和继电器控制引脚要分开不要共用同一个 GPIO。7.2 隐私与合规注意口罩识别/人脸识别属于生物特征相关应用。即使只是课程设计或开源演示如果实际部署到公共环境也要注意摄像头采集到的人脸图像不要随意上传到公网如果产品需要保存识别日志应做匿名化处理只保存“通过/不通过”记录不长期保存原始人脸图在门禁旁边明确提示“区域内进行图像识别”告知使用者系统设计应遵循最小权限原则识别结果只用于门禁通行不用于其他数据挖掘。如果是个人学习开源项目在自己的局域网或测试环境里做功能验证没有问题如果要商业部署请先确认算法授权、模型训练数据集来源、商标和开源许可证等法律问题。7.3 开源协议与二次开发建议标题里写着“免费开源”但不同开源作者对代码和硬件资料使用的授权并不一样。下载源码后应查看目录中是否有 LICENSE 或 README 说明。如果代码采用 MIT/Apache 协议可以自由修改、商用但要保留版权声明如果采用 GPL 协议你的二次开发版本需要开源如果硬件部分声明“不可商用”则不能用来做产品。二次开发时建议先把源码整理成自己的工程而不是在原工程上乱改。做版本管理时把原理图、视觉模块代码、STM32 工程放在同一个 Git 仓库里方便回溯。8. 总结与下一步学习路线8.1 本文要点回顾STM32 口罩识别门禁系统并不是一个不可拆解的“黑盒项目”。这套开源资料的核心价值在于展示了嵌入式综合项目的分层方式视觉模块与 STM32 各司其职串口通信通过帧头、校验、帧尾保证可靠性继电器控制电磁锁需要了解电路驱动和续流设计源码与原理图要配合阅读GPIO 分配、触发电平、共地问题最容易踩坑加入人工按钮、超时保护、日志记录后才能从“能运行的 demo”变成“可部署的小系统”。如果你从未接触过 STM32 项目建议先不要直接改视觉模块算法而是把重点放在 STM32 端状态机和继电器控制上使用电脑串口助手模拟视觉模块发数据一步步验证。8.2 后续升级方向当你完全跑通这套口罩识别门禁后可以考虑从以下方向继续升级视觉模块端换成更强模型从口罩分类升级为“人脸检测 口罩佩戴检测 体温检测”多任务识别把主控从 STM32F103C8T6 换成 STM32F407/H750本地增加数据处理和联网能力增加 RC522 刷卡模块形成“刷卡 口罩识别”双重认证增加 4G/WiFi 模块将门禁记录上传服务器使用 RTOS 改造主循环把串口解析、门禁控制和状态显示拆成独立任务。在实际项目中比“能不能识别口罩”更值得关心的是“识别错了之后系统怎么兜底”。希望你在复现这套开源项目时不只把它当作一个跑马灯程序而是真正理解每个模块承担什么职责、每一个信号为什么这样连接。学完这套资料后你完全有条件设计属于自己的门禁或安防终端系统。欢迎把本文收藏备用也欢迎在评论区分享你的实物运行效果和踩坑经历。