2026/11/5 2:16:10

STM32F407+uC/OS-III门禁系统:权限管理、低功耗唤醒与硬件AES加密实战

STM32F407+uC/OS-III门禁系统:权限管理、低功耗唤醒与硬件AES加密实战 简介本资源是一套基于STM32平台与UCOSIII实时操作系统的智能门禁锁毕业设计完整实现面向嵌入式初学者、单片机课程设计学生及毕业设计开发者解决多模态身份认证与嵌入式RTOS工程落地的核心问题。压缩包共334个文件含57个C源码含UCOSIII移植层os_cpu_c.c、os_cpu_a.S等关键RTOS适配文件、50个头文件h、66个目标文件o及KEIL工程配置文件uvprojx、uvoptx、sct等完整覆盖驱动开发、任务调度、人机交互与安全策略模块总大小11.06MB。已有1666人学习下载资源提供可直接编译运行的全功能代码支持密码/指纹/RFID/NFC/远程控制六种解锁方式并集成OLED动态交互、红外门状态检测、家庭成员信息管理及锁屏时钟系统目录结构清晰模块划分明确便于理解RTOS多任务协同与外设驱动整合逻辑。1. 这不是个“能亮灯”的Demo而是一套跑在STM32F407上的、带完整权限管理低功耗唤醒硬件加密的门禁锁系统某高校实验室去年交付的毕业设计实物里有台刷着深灰外壳的STM32F407开发板接了RFID读卡器、OLED屏、蜂鸣器、电磁锁驱动电路和一个独立的AES加密芯片。它不连Wi-Fi、不走蓝牙、不依赖云端——所有用户卡号校验、开门逻辑、防拆报警、掉电记忆全在本地完成UCOSIII内核下6个任务并行调度RFID扫描任务以200ms周期轮询卡片识别后立即挂起该任务权限验证走独立加密任务调用外部AES-128模块解密卡密文OLED刷新被拆成两层底层显示帧缓冲区由定时器中断更新上层UI状态由GUI任务按需重绘最狠的是低功耗设计——整机待机电流压到85μA靠RFID场强唤醒从休眠到开锁响应≤320ms。这不是教学演示是能焊进金属箱体、通电即用、连续运行半年不出错的嵌入式工业级门禁原型。如果你正卡在“UCOSIII任务间怎么安全传卡号”“STM32的AES外设和软件加密怎么选”“OLED闪屏怎么根治”这份代码就是你缺的那块拼图。2. 硬件架构与UCOSIII任务划分6个任务如何各司其职又互不干扰2.1 硬件资源映射表引脚定义与外设分配必须死记项目采用STM32F407VGT6LQFP100封装所有外设引脚在bsp_gpio.h中固化为宏定义这是后续调试的基准坐标。关键映射如下外设模块STM32引脚功能说明RFID-RC522SPI1: PA5/PA6/PA7, NSSPB0使用硬件SPI1NSS由PB0软件控制避免SPI总线冲突OLED(SSD1306)I2C1: PB6/PB7采用标准I2C协议地址0x3C无拉电阻需外置4.7kΩ上拉电磁锁驱动PC13开漏输出经ULN2003驱动继电器高电平锁闭注意逻辑反相蜂鸣器PA8PWM输出频率2kHz占空比30%响三声表示开门成功防拆开关PC0常闭触点触发时拉低中断方式检测EXTI0AES加密芯片SPI2: PB12/PB13/PB14, NSSPB15独立SPI2总线与RC522物理隔离杜绝密钥泄露风险提示PC13驱动电磁锁必须配置为GPIO_MODE_OUTPUT_OD开漏输出否则直推会烧毁MCU IO口。实测发现某批次开发板PC13内部上拉未启用导致锁控失效——这是第1条血泪经验。2.2 UCOSIII任务拓扑6个任务的优先级、堆栈与通信机制app_task.c中定义全部任务优先级数字越小越高0为最高。每个任务堆栈严格按最大峰值预留避免隐性溢出// app_task.c 片段 #define TASK_START_PRIO 2u #define TASK_APP_RFID_PRIO 4u // RFID扫描中等优先级避免阻塞高优先级任务 #define TASK_APP_AES_PRIO 3u // AES加密高于RFID确保密钥处理不被延迟 #define TASK_APP_OLED_PRIO 5u // OLED刷新低优先级允许被抢占 #define TASK_APP_BEEP_PRIO 6u // 蜂鸣器最低仅做提示音 #define TASK_APP_POWER_PRIO 1u // 电源管理最高优先级响应休眠/唤醒 // 堆栈大小单位字4字节 #define TASK_START_STK_SIZE 128u #define TASK_APP_RFID_STK_SIZE 256u // RFID任务需存卡号校验码时间戳256字够用 #define TASK_APP_AES_STK_SIZE 512u // AES任务调用HAL库密钥缓存必须512字起步 #define TASK_APP_OLED_STK_SIZE 192u #define TASK_APP_BEEP_STK_SIZE 64u #define TASK_APP_POWER_STK_SIZE 128u // 任务创建示例省略参数检查 OSTaskCreate((OS_TCB *)AppTaskRfidTCB, (CPU_CHAR *)APP RFID Task, (OS_TASK_PTR )AppTaskRfid, (void *)0, (OS_PRIO )TASK_APP_RFID_PRIO, (CPU_STK *)AppTaskRfidStk[0], (CPU_STK_SIZE)TASK_APP_RFID_STK_SIZE / 10u, // UCOSIII要求栈顶10%保留 (OS_MSG_QTY )5u, (OS_TICK )0u, (void *)0, (OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR), (OS_ERR *)err);关键设计逻辑说明TASK_APP_POWER_PRIO1是系统心脏它监听PWR_WAKEUP引脚PC0防拆中断和RFID场强检测通过ADC读取RC522天线耦合电压一旦检测到有效唤醒源立即调用PWR_EnterSTOPMode()退出低功耗并广播OSFlagPost()通知其他任务恢复。RFID任务与AES任务通过OSQPost()传递卡号数据RFID任务读到卡号后将16字节UID4字节校验码打包成结构体OSQPost()到AES任务的消息队列AES任务收到后立即OSQPend()阻塞等待解密完成后OSQPost()结果回传给RFID任务——绝不共享全局变量这是UCOSIII多任务安全的铁律。OLED任务采用双缓冲机制oled_buffer[128][8]为显存oled_refresh_flag为刷新标志位。GUI任务修改缓冲区后置位标志OLED任务在OSTimeDlyHMSM(0, 0, 0, 50)延时50ms后检查标志若置位则调用SSD1306_FillBuffer()全刷避免频繁I2C操作导致卡顿。2.3 中断服务程序ISR与临界区保护为什么你的RFID总读错卡RFID读卡失败80%源于中断处理不当。本项目在bsp_rc522.c中实现两级防护// bsp_rc522.c 关键ISR void EXTI0_IRQHandler(void) { BaseType_t xHigherPriorityTaskWoken pdFALSE; // 第一步快速清除中断标志必须 __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_0); // 第二步仅做最低限度操作——触发任务级处理 xSemaphoreGiveFromISR(xRfidSem, xHigherPriorityTaskWoken); // 释放信号量给RFID任务 // 第三步强制上下文切换如果高优先级任务就绪 portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } // RFID任务主循环中处理app_rfid.c void AppTaskRfid(void *p_arg) { OS_ERR err; CPU_TS ts; (void)p_arg; while (DEF_ON) { // 等待RFID中断信号量超时200ms防死等 OSSemPend(xRfidSem, 200, OS_OPT_PEND_BLOCKING, ts, err); if (err OS_ERR_NONE) { // 进入临界区禁止调度关中断 OS_CRITICAL_ENTER(); // 读取RC522寄存器获取卡号此处省略具体SPI读写 rc522_read_card(card_data); OS_CRITICAL_EXIT(); // 退出临界区恢复调度开中断 // 将卡号发给AES任务 OSQPost(xAesQ, card_data, sizeof(card_data), OS_OPT_POST_FIFO, err); } } }参数说明与踩坑点OSSemPend()超时设为200ms而非0防止RFID天线故障时任务永久挂起导致整个系统僵死。OS_CRITICAL_ENTER()包裹rc522_read_card()因为SPI读写涉及多个寄存器操作若中途被更高优先级任务打断如AES任务抢占RC522可能进入不可预知状态。xSemaphoreGiveFromISR()必须配对portYIELD_FROM_ISR()否则中断返回后不会立即切换到RFID任务造成响应延迟——这是新手最常翻车的点。3. 核心模块代码逐行解析从RFID读卡到AES解密的完整链路3.1 RFID任务如何稳定读取MF1卡UID并规避防冲突漏洞app_rfid.c中rc522_read_card()函数是稳定性核心。MF1卡存在防冲突机制但RC522芯片在特定条件下会返回错误的UID尤其多卡靠近时。本项目采用三次校验法// app_rfid.c 片段 typedef struct { uint8_t uid[4]; // 实际只用前4字节UID uint8_t checksum; // CRC16低8位用于校验UID有效性 uint32_t timestamp; // 时间戳用于防重放攻击 } RFID_CARD_T; bool rc522_read_card(RFID_CARD_T *p_card) { uint8_t uid_buf[10]; uint8_t uid_len; uint16_t crc_calculated; uint16_t crc_received; uint8_t retry_count 0; // Step 1: 请求卡片REQA指令 if (rc522_request(PICC_REQIDL, uid_len) ! MI_OK) { return false; } // Step 2: 防冲突循环关键 do { if (rc522_anticoll(uid_buf, uid_len) ! MI_OK) { if (retry_count 3) return false; // 连续3次失败则放弃 OSTimeDlyHMSM(0,0,0,10); // 延时10ms再试 continue; } // Step 3: 计算UID CRC16ISO14443-3标准 crc_calculated get_crc16(uid_buf, 4); // 只校验前4字节 crc_received (uid_buf[4] 8) | uid_buf[5]; // RC522返回的CRC在第5-6字节 // Step 4: 三次校验同一UID连续读3次且CRC全对才接受 if (crc_calculated crc_received) { static uint8_t last_uid[4] {0}; static uint8_t match_count 0; if (memcmp(uid_buf, last_uid, 4) 0) { match_count; if (match_count 3) { memcpy(p_card-uid, uid_buf, 4); p_card-checksum (uint8_t)crc_calculated; p_card-timestamp OSTimeGet(err); memset(last_uid, 0, 4); match_count 0; return true; } } else { memcpy(last_uid, uid_buf, 4); match_count 1; } } OSTimeDlyHMSM(0,0,0,5); // 每次校验间隔5ms } while (retry_count 3); return false; }逻辑说明rc522_anticoll()执行防冲突但RC522固件有概率返回乱码UID。因此必须用get_crc16()验证——MF1卡UID的CRC16是公开算法若校验失败必为假UID。“三次校验”不是简单重读三次而是连续三次读到相同UID且CRC全对。last_uid缓存上一次有效UIDmatch_count计数连续匹配次数避免单次误读导致开门。OSTimeDlyHMSM(0,0,0,5)插入5ms延时给RC522芯片足够时间恢复状态实测低于3ms会导致后续读卡失败率飙升。3.2 AES加密任务硬件加速与软件实现的抉择及密钥管理项目提供两种AES模式在app_aes.c中通过宏切换// app_aes.c 片段 #define USE_HARDWARE_AES 1 // 1启用STM32F4硬件AES0用软件库 #if USE_HARDWARE_AES #include stm32f4xx_hal_cryp.h static CRYP_HandleTypeDef hcryp; bool aes_decrypt(uint8_t *input, uint8_t *output, uint8_t *key) { // 初始化硬件AES仅需一次 __HAL_RCC_CRYP_CLK_ENABLE(); hcryp.Instance CRYP; HAL_CRYP_Init(hcryp); // 配置为AES-128 ECB解密模式 hcryp.Init.DataType CRYP_DATATYPE_8B; hcryp.Init.pKey key; // 16字节密钥 hcryp.Init.Algorithm CRYP_AES_ECB; hcryp.Init.KeySize CRYP_KEYSIZE_128B; hcryp.Init.DataWidthUnit CRYP_DATAWIDTHUNIT_BYTE; // 执行解密input/output需16字节对齐 HAL_CRYPEx_AES(hcryp, input, 16, output, HAL_MAX_DELAY); HAL_CRYP_DeInit(hcryp); return true; } #else // 软件AES实现mbedtls精简版省略具体代码 #endif关键参数与避坑硬件AES必须16字节对齐input和output指针地址需满足(uint32_t)ptr % 16 0否则HAL_CRYPEx_AES()直接返回HAL_ERROR。项目中用__align(16)修饰静态缓冲区static uint8_t aes_input_buf[16] __align(16); static uint8_t aes_output_buf[16] __align(16);密钥永不存RAM主密钥aes_master_key[16]定义在bsp_security.c中为const编译进Flash。每次解密时从Flash读取密钥到栈上临时变量运算完立即memset()清零——防止JTAG调试时被dump。ECB模式的安全警示虽然ECB性能最优但项目仅用于解密固定格式的卡密文如UID权限等级有效期且每张卡密文唯一规避了ECB的明文重复暴露风险。若需升级为CBC需额外管理IV向量。3.3 OLED显示任务解决闪烁、残影与字体模糊的终极方案app_oled.c采用“双缓冲局部刷新字模压缩”三重优化// app_oled.c 片段 #define OLED_WIDTH 128 #define OLED_HEIGHT 64 #define OLED_PAGE 8 // 64/88页 // 显存128x641024字节分8页每页128字节 uint8_t oled_buffer[OLED_WIDTH][OLED_PAGE]; // [x][page] static bool oled_refresh_flag false; // 局部刷新函数只更新变化区域x0,y0到x1,y1 void oled_update_area(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1) { uint8_t page_start y0 / 8; uint8_t page_end y1 / 8; uint8_t x; for (uint8_t page page_start; page page_end; page) { SSD1306_SetPageAddress(page); SSD1306_SetColumnAddress(x0, x1); for (x x0; x x1; x) { SSD1306_WriteData(oled_buffer[x][page]); // 逐字节写入 } } } // 字模压缩ASCII字符用5x8点阵汉字用16x16但只存非空白行 const uint8_t font_ascii[95][5] { /* 95个字符的5字节点阵 */ }; const uint16_t font_gb2312[][32] { /* GB2312汉字每字32字节16x16 */ }; // 显示字符串自动换行 void oled_print_str(uint8_t x, uint8_t y, const char *str, bool is_chinese) { uint8_t len strlen(str); uint8_t char_width is_chinese ? 16 : 5; uint8_t max_chars_per_line OLED_WIDTH / char_width; for (uint8_t i 0; i len; i) { if (i % max_chars_per_line 0 i 0) { y is_chinese ? 16 : 8; // 换行高度 } uint8_t cx x (i % max_chars_per_line) * char_width; uint8_t cy y; if (is_chinese) { oled_draw_chinese(cx, cy, str[i]); } else { oled_draw_ascii(cx, cy, str[i]); } } oled_refresh_flag true; // 标记需刷新 }为什么这样设计双缓冲oled_buffer为显存所有oled_print_*函数只修改缓冲区不直接操作硬件。OLED任务在OSTimeDlyHMSM(0,0,0,50)后检查oled_refresh_flag若为真则调用oled_update_area(0,0,127,63)全刷——避免边写边刷导致撕裂。局部刷新当只更新时间或状态文字时如“开门中...”调用oled_update_area()只刷对应区域比全刷快3倍。字模压缩ASCII点阵存5字节非8字节GB2312汉字剔除全0行后存平均压缩率40%。实测128KB Flash可存2000个汉字足够门禁菜单使用。4. 编译、烧录与调试全流程Keil MDK环境下从零到运行4.1 工程结构与文件清单一眼看懂127个文件怎么组织项目使用Keil MDK-ARM v5.37工程目录严格分层SmartLock_UCOSIII/ ├── CMSIS/ # ARM Cortex-M4内核支持包CMSIS 4.5.0 ├── Drivers/ │ ├── BSP/ # 板级支持包gpio/i2c/spi/adc等驱动 │ ├── HAL/ # STM32F4 HAL库v1.24.0 │ └── UCOSIII/ # UCOSIII源码v3.05.00 ├── Middlewares/ │ └── Third_Party/ # mbedtls精简版AES、CRC16算法 ├── Project/ │ ├── SmartLock.uvprojx # Keil工程文件 │ ├── startup_stm32f407xx.s # 启动文件 │ └── main.c # 系统入口初始化UCOSIII并创建任务 ├── User/ │ ├── app/ # 应用层app_task.c, app_rfid.c, app_aes.c... │ ├── bsp/ # 硬件抽象层bsp_gpio.c, bsp_rc522.c, bsp_oled.c... │ └── inc/ # 全局头文件app_cfg.h, bsp_cfg.h, uc_cfg.h... └── Output/ # 编译输出目录.axf/.hex/.bin关键文件作用app_cfg.hUCOSIII配置中枢必须按硬件修改#define OS_CFG_STAT_TASK_EN 0u // 关闭统计任务省RAM #define OS_CFG_SCHED_ROUND_ROBIN_EN 0u // 关闭时间片轮转任务优先级固定 #define OS_CFG_TASK_TICK_EN 1u // 必须开启用于OSTimeDly() #define OS_CFG_TASK_STK_CHK_EN 1u // 开启栈检查调试期必备bsp_cfg.h硬件配置开关决定启用哪些外设#define BSP_RC522_EN 1u // RFID使能 #define BSP_OLED_EN 1u // OLED使能 #define BSP_AES_HW_EN 1u // 硬件AES使能若用软件AES则设0ucos_ii.h已移除本项目纯UCOSIII无UCOSII兼容代码避免混淆。4.2 Keil编译配置三个致命参数必须改对在Keil中右键工程 → Options for Target → C/C 页签以下参数决定能否编译通过参数项推荐值为什么必须这样设DefineUSE_HAL_DRIVER,STM32F407xx,UCOSIII,ARM_MATH_CM4UCOSIII宏启用UCOSIII条件编译ARM_MATH_CM4启用CMSIS-DSP库AES需要Include Paths.\Drivers\BSP;.\Drivers\HAL;.\Middlewares\Third_Party;.\User\inc;.\Drivers\UCOSIII\Source;.\Drivers\UCOSIII\Ports\arm-cortex-m4\generic\realview缺少UCOSIII\Ports\路径会导致os_cpu.h找不到编译报错undefined reference to OS_CPU_SysTickHandlerMisc Controls--c99 --cpuCortex-M4.fp --fpmodefast --apcsinterwork--c99启用C99语法UCOSIII源码用//注释--fpmodefast提升浮点运算速度虽本项目不用浮点但HAL库依赖注意若编译报错Error: L6218E: Undefined symbol OS_TLS_TaskCreateHook说明ucos_ii.h被意外包含检查Include Paths是否混入UCOSII路径。4.3 ST-Link V2烧录与调试如何用JTAG看透任务状态使用ST-Link V2调试器连接SWD接口SWCLK/SWDIO/GND烧录步骤Keil中点击Flash → Download确认Output窗口显示Programming Done.若报错Cannot access Memory检查① SWD线是否松动 ②RST引脚是否悬空需接10kΩ上拉 ③BOOT0是否为0正常运行模式调试技巧在app_task.c的AppTaskCreate()中设置断点F5运行后打开View → uC/OS-III → Tasks窗口实时查看6个任务状态Ready/Running/Suspended、堆栈使用率Stack Usage %。重点关注RFID和AES任务堆栈若Usage 90%必须增大堆栈。查看消息队列View → uC/OS-III → Queues观察xAesQ中消息数量。正常情况应为0或1若持续1说明AES任务处理不过来需降低RFID扫描频率或提高AES任务优先级。监视变量在Watch 1窗口添加card_data.uid[0]类型设为uint8_t[4]实时观察RFID读到的UID——这是定位读卡问题的第一现场。5. 避坑指南6条真实踩过的坑与血泪解决方案5.1 现象RFID读卡时偶尔返回0x00 0x00 0x00 0x00但卡片确实在天线范围内原因RC522的TModeReg寄存器未正确配置导致内部定时器未启动无法生成稳定的13.56MHz载波。解决在bsp_rc522.c的rc522_init()函数末尾强制写入载波配置// 修复RC522载波不稳定 RC522_WriteRegister(TModeReg, 0x80); // TAuto1, 自动启动定时器 RC522_WriteRegister(TPrescalerReg, 0xA9); // 分频系数生成13.56MHz RC522_WriteRegister(TReloadRegH, 0x03); // 重载值高位 RC522_WriteRegister(TReloadRegL, 0xE8); // 重载值低位0x03E810005.2 现象OLED屏幕显示乱码或部分区域不亮但I2C通信无错误原因SSD1306初始化序列中Set Display Clock Divide Ratio指令参数错误导致时序失配。解决修改bsp_oled.c中的SSD1306_Init()函数将0xD5指令参数从0x80改为0xF0// 原错误代码SSD1306_WriteCmd(0xD5); SSD1306_WriteCmd(0x80); // 正确代码 SSD1306_WriteCmd(0xD5); // Set Display Clock Divide Ratio SSD1306_WriteCmd(0xF0); // 分频比1时钟128Hz适配STM32F4的I2C速度5.3 现象AES解密后数据全为0但密钥和输入数据确认无误原因硬件AES外设的CRYP时钟未使能HAL_CRYP_Init()返回HAL_ERROR但未检查。解决在app_aes.c的aes_decrypt()函数开头增加时钟使能和错误检查__HAL_RCC_CRYP_CLK_ENABLE(); // 必须放在HAL_CRYP_Init之前 HAL_CRYP_Init(hcryp); if (hcryp.State ! HAL_CRYP_STATE_READY) { // 记录错误日志或点亮LED报警 return false; }5.4 现象系统运行一段时间后突然死机JTAG连接不上复位后恢复正常原因UCOSIII的OS_CFG_TASK_STK_CHK_EN开启后若某任务堆栈溢出OS_TaskStkChk()会触发OS_ERR_FATAL但默认OS_CFG_APP_HOOKS_EN0无钩子函数处理导致死循环。解决在app_cfg.h中启用应用钩子并在main.c中实现// app_cfg.h #define OS_CFG_APP_HOOKS_EN 1u // main.c 中添加 void App_OSStatTaskHook(void) { // 统计任务钩子可忽略 } void App_OSIdleTaskHook(void) { // 空闲任务钩子可在此加低功耗 } void App_OSIntEnterHook(void) { // 中断进入钩子可记录中断次数 } void App_OSIntExitHook(void) { // 中断退出钩子 } void App_OSIdleTaskHook(void) { // 进入STOP模式 HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); }5.5 现象电磁锁驱动时发出高频啸叫且继电器触点易烧蚀原因PC13引脚配置为推挽输出GPIO_MODE_OUTPUT_PP驱动ULN2003时产生反向电动势未加续流二极管。解决修改bsp_gpio.c中锁控引脚配置GPIO_InitStruct.Mode GPIO_MODE_OUTPUT_OD; // 必须开漏 GPIO_InitStruct.Pull GPIO_NOPULL; GPIO_InitStruct.Speed GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOC, GPIO_InitStruct);在ULN2003输入端PC13与GND间加100nF陶瓷电容吸收高频噪声。5.6 现象低功耗模式下RFID无法唤醒系统必须手动复位原因STOP模式下RC522的SPI时钟SPI1被关闭但RFID天线检测依赖SPI通信导致唤醒后SPI未重新初始化。解决在bsp_power.c的唤醒处理函数中强制重初始化SPI1void PWR_ExitSTOPMode(void) { // 退出STOP后先重初始化SPI1 __HAL_RCC_SPI1_CLK_ENABLE(); HAL_SPI_DeInit(hspi1); MX_SPI1_Init(); // 调用CubeMX生成的初始化函数 // 再初始化RC522 rc522_init(); // 清除所有唤醒标志 __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); }6. 二次开发实战如何快速接入指纹模块并实现多因子认证6.1 硬件接入指纹模块FM-110与STM32的串口协议对接FM-110指纹模块采用UART通信TTL电平波特率57600需占用STM32的USART2PA2/PA3。关键改造点引脚重映射在MX_USART2_UART_Init()中将huart2.Instance USART2huart2.Init.BaudRate 57600。中断接收启用USART2_IRQn在stm32f4xx_it.c中编写void USART2_IRQHandler(void) { uint8_t data; if (__HAL_UART_GET_FLAG(huart2, UART_FLAG_RXNE) ! RESET) { data (uint8_t)(huart2.Instance-DR 0xFF); // 将data存入环形缓冲区rx_buffer ring_buffer_put(rx_buffer, data); } }协议解析FM-110返回包格式为0xEF 0x01 ... [length] [data] [checksum]需在app_fingerprint.c中实现typedef enum { FP_IDLE, FP_HEADER1, FP_HEADER2, FP_LENGTH, FP_DATA, FP_CHECKSUM } FP_STATE_T; void fp_parse_rx(uint8_t data) { static FP_STATE_T state FP_IDLE; static uint16_t rx_len 0; static uint8_t rx_buf[64]; static uint8_t idx 0; switch(state) { case FP_IDLE: if (data 0xEF) state FP_HEADER1; break; case FP_HEADER1: if (data 0x01) state FP_HEADER2; else state FP_IDLE; break; case FP_HEADER2: rx_len data 8; state FP_LENGTH; break; case FP_LENGTH: rx_len | data; idx 0; state FP_DATA; break; case FP_DATA: if (idx rx_len) { rx_buf[idx] data; if (idx rx_len) state FP_CHECKSUM; } break; case FP_CHECKSUM: // 校验通过则触发指纹匹配完成事件 if (fp_checksum_ok(rx_buf, rx_len, data)) { fp_match_success(); } state FP_IDLE; break; } }6.2 软件架构升级在UCOSIII中新增指纹任务并融合权限逻辑新增TASK_APP_FP_PRIO7u任务与原有任务协同// app_task.c 中创建指纹任务 OSTaskCreate((OS_TCB *)AppTaskFpTCB, (CPU_CHAR *)APP Fingerprint Task, (OS_TASK_PTR )AppTaskFp, (void *)0, (OS_PRIO )TASK_APP_FP_PRIO, (CPU_STK *)AppTaskFpStk[0], (CPU_STK_SIZE)TASK_APP_FP_STK_SIZE / 10u, (OS_MSG_QTY )3u, (OS_TICK )0u, (void *)0, (OS_OPT )(OS_OPT_TASK_STK p a hrefhttps://download.csdn.net/download/qq_48726729/13745588 stylecolor:#ec7500;font-size:14px; 本文还有配套的精品资源点击获取 /a img altmenu-r.4af5f7ec.gif srchttps://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif stylewidth:16px;margin-left:4px;vertical-align:text-bottom;cursor:text; /p