梁山派GD32F470驱动FR1002人脸识别模块:串口通信与活体检测移植指南
最近在做一个智能门禁的项目,需要用到本地的人脸识别功能,既要识别准确,还得能防照片、视频欺骗,也就是得有活体检测。我选用了FR1002这个模块,它自带双目摄像头,活体检测效果不错,而且接口简单,用串口就能控制。正好手头有块梁山派GD32F470开发板,今天我就来手把手教大家,怎么把FR1002模块接到梁山派上,并完成驱动移植,让你也能快速用起来。
这篇教程适合正在做物联网门禁、考勤机或者任何需要人脸识别功能的嵌入式开发者。哪怕你之前没接触过这个模块,跟着我的步骤走,从硬件连接到代码编写,再到调试,都能搞定。咱们的目标就是让梁山派通过串口“命令”FR1002模块工作,并正确读取它返回的人脸识别结果。
1. 准备工作:认识你的FR1002模块
在动手接线写代码之前,咱们得先了解一下FR1002这个“小伙伴”。它可不是一个简单的摄像头,而是一个完整的解决方案。
FR1002模块的核心特点:它内部集成了一颗高性能的应用处理器和一对双目传感器。双目的作用就是为了实现活体检测——通过两个稍微错开的“眼睛”来判断面前的是真人脸还是平面图像。官方资料说它具有金融级的识别能力,启动快,而且功耗超低,这对于用电池供电的设备来说非常友好。
关键规格参数:为了后续电路设计和代码编写不出错,下面这些参数你得记牢:
| 参数项 | 规格说明 |
|---|---|
| 工作电压 | 5.0V - 14V |
| 工作电流 | 低于 2W(按5V算,电流小于400mA) |
| 最大人脸库 | 100人 |
| 有效识别距离 | 0.4米 ~ 1.0米 |
| 通信接口 | 串口 (UART) |
| 数据格式 | 厂家自定义协议格式 |
| 物理接口 | 4 Pin 2.54mm间距排针 |
资料哪里找?模块的详细资料,尤其是最重要的《用户手册》,是开发的圣经。你可以通过下面的链接获取:
- 资料下载:
http://h.hlktech.com/Mobile/download/fdetail/215.html - 采购链接:可以在电商平台搜索“FR1002 人脸识别模块 3D 红外双目”。
注意:务必下载并仔细阅读《FR1002人脸识别模组用户手册》。里面包含了完整的通信协议、指令集、上电时序等关键信息,后续所有串口命令的解析都依赖它。原始文章里没有提供协议细节,所以这份手册是你成功移植的必备工具。
2. 硬件连接:把模块接到梁山派上
硬件连接是第一步,也是最容易出错的一步。接错了线,后面软件调死也没用。FR1002模块引出了4根线,颜色和功能很明确。
2.1 引脚定义与连接对照
模块的4Pin排针通常对应如下颜色的线:
- 黑线:GND(电源地)
- 黄线:RX(模块的接收引脚,接开发板的TX)
- 绿线:TX(模块的发送引脚,接开发板的RX)
- 红线:VCC(电源正极,5V)
根据原始资料,我们将其连接到梁山派GD32F470开发板的对应引脚上:
| FR1002模块引脚 | 连接线颜色 | 梁山派 GD32F470 引脚 |
|---|---|---|
| GND | 黑线 | 任意 GND 引脚 |
| RX | 黄线 | PA2(这个引脚将作为梁山派的TX使用) |
| TX | 绿线 | PA3(这个引脚将作为梁山派的RX使用) |
| VCC | 红线 | 5V电源输出引脚 |
2.2 连接原理与注意事项
为什么黄线(模块RX)要接PA2(板子TX)?这里有个串口通信的基本概念:对于通信双方,一方的发送端(TX)必须连接另一方的接收端(RX)。所以:
- 梁山派想要发送指令给模块,就需要使用自己的TX引脚(PA2)连接到模块的RX引脚(黄线)。
- 梁山派想要接收模块返回的数据,就需要使用自己的RX引脚(PA3)连接到模块的TX引脚(绿线)。
接线时务必注意:
- 电源电压:一定要接在梁山派的5V引脚上,不要接到3.3V,否则模块可能无法正常工作。
- 共地:GND必须连接,这是所有电路正常工作的基础。
- 接好后最好再检查一遍,避免接反。
3. 软件驱动移植:让代码跑起来
硬件通了,接下来就是软件部分。我们的核心任务就是让梁山派的串口按照FR1002模块规定的“语言”(协议)去对话。
3.1 串口初始化配置
根据资料,FR1002模块的默认通信参数是:波特率115200,8位数据位,1位停止位,无校验位。这个配置非常常见。
我们需要在梁山派的工程中,初始化一个串口(比如USART0)来匹配这个参数。这里假设我们使用PA2和PA3,它们对应的是GD32F470的USART0_TX和USART0_RX功能。
/** * @brief 初始化USART0,用于与FR1002模块通信 * @param 无 * @retval 无 */ void fr1002_uart_init(void) { // 1. 开启外设时钟 rcu_periph_clock_enable(RCU_GPIOA); // 开启GPIOA时钟 rcu_periph_clock_enable(RCU_USART0); // 开启USART0时钟 // 2. 配置GPIO引脚复用功能 // PA2 复用为 USART0_TX gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_2); gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_2); gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2); // PA3 复用为 USART0_RX gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_3); gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_3); // RX引脚通常不需要设置输出速度和类型 // 3. 配置USART参数 usart_deinit(USART0); usart_baudrate_set(USART0, 115200U); // 波特率115200 usart_word_length_set(USART0, USART_WL_8BIT); // 8位数据 usart_stop_bit_set(USART0, USART_STB_1BIT); // 1位停止位 usart_parity_config(USART0, USART_PM_NONE); // 无校验 usart_hardware_flow_rts_config(USART0, USART_RTS_DISABLE); // 禁用硬件流控 usart_hardware_flow_cts_config(USART0, USART_CTS_DISABLE); usart_receive_config(USART0, USART_RECEIVE_ENABLE); // 使能接收 usart_transmit_config(USART0, USART_TRANSMIT_ENABLE); // 使能发送 usart_enable(USART0); // 使能USART0 }3.2 关键一步:满足上电时序
这是原始资料里特别强调的一点,也是很多朋友容易忽略导致模块不响应的坑。手册要求“满足上电时序,才可进行初始化工作”。
这是什么意思呢?我理解并实践下来的流程是这样的:
- 先给模块稳定供电(接好5V和GND)。
- 等待一段时间(比如100-500ms),让模块内部的处理器和传感器完成自检和启动。这个时间最好参考手册。
- 模块启动完成后,才会开始监听串口指令。
- 然后,再初始化梁山派的串口,并开始发送指令。
所以,在你的main函数里,顺序应该是这样的:
int main(void) { // 系统时钟等初始化... // 1. 给FR1002模块上电(硬件连接好后,开发板上电即完成) // 2. 延时,等待模块启动 delay_ms(300); // 延时300毫秒,具体时间需参考手册 // 3. 初始化与模块通信的串口 fr1002_uart_init(); // 4. 此时才可以开始发送查询或配置指令 // fr1002_send_cmd(...); while(1) { // 主循环 } }3.3 通信协议解析与数据收发
模块使用“厂家自定义格式”的帧。这意味着你需要仔细阅读用户手册,找到指令帧和返回帧的格式。通常格式会包含帧头、指令字、数据长度、数据内容、校验和、帧尾这几个部分。
编写发送函数:你需要根据协议,拼装出一个完整的指令帧,然后通过串口发送出去。
void fr1002_send_data(uint8_t *pData, uint16_t len) { for(uint16_t i = 0; i < len; i++) { usart_data_transmit(USART0, pData[i]); // 发送一个字节 while(RESET == usart_flag_get(USART0, USART_FLAG_TBE)); // 等待发送完成 } } // 示例:拼装一条指令并发送(假设的协议,具体需看手册) void fr1002_query_status(void) { uint8_t cmd_frame[] = {0xAA, 0x01, 0x00, 0x00, 0xBB}; // 示例帧:头|指令|长度|校验|尾 // 实际需要根据手册计算长度和校验和 fr1002_send_data(cmd_frame, sizeof(cmd_frame)); }编写接收与解析函数:接收部分更关键,因为模块返回的数据(识别到谁、活体检测是否通过)都在这里面。通常我们会用中断方式接收,避免阻塞主程序。
// 串口接收中断服务函数 void USART0_IRQHandler(void) { if(RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE)) { // 读取接收到的字节 uint8_t rx_byte = usart_data_receive(USART0); // 将字节放入自定义的缓冲区 // 并调用协议解析函数,判断是否收到一个完整的有效数据包 // fr1002_protocol_parse(rx_byte); } }在解析函数fr1002_protocol_parse里,你需要按照手册定义的帧结构,逐个字节判断帧头、计算长度、验证校验和,最后提取出有效数据(比如用户ID、识别置信度、活体检测结果等)。
4. 功能集成与调试心得
当你完成了基础的发送和接收解析,就可以根据手册去实现具体功能了,比如:
- 录入人脸:发送录入指令,模块会提示等待人脸,然后将特征存入指定位置。
- 识别并活体检测:发送识别指令,模块会返回识别到的用户ID以及是否为活体的判断。
- 删除人脸:删除指定ID的人脸数据。
调试几个常见坑点:
- 模块无反应:首先检查上电时序和电源电压。用万用表量一下红线电压是不是5V,接上模块后电压会不会被拉低太多。然后确认串口线(TX/RX)有没有接反。
- 收到乱码:99%是波特率不匹配。确认代码里设置的波特率是不是115200,并且开发板的主频配置是否正确,这会影响波特率发生器的计算。
- 数据包解析错误:仔细核对协议手册。帧头帧尾对不对?校验和算法是加和、异或还是CRC?数据长度字段是包含自身还是只指数据域?这些细节一个都不能错。建议先用串口助手连接模块,手动发送标准指令,看看模块返回的完整数据包是什么,再对照手册分析。
- 活体检测不通过:确保环境光线不要太暗或有过强反光。让人脸保持在合适的距离(0.4-1米)内,并正对摄像头。
把FR1002模块成功驱动起来后,你就可以在梁山派上轻松实现本地的人脸识别+活体检测功能了。接下来,你可以把识别结果用来控制一个继电器模拟开门,或者通过4G/Wi-Fi上传到服务器,物联网门禁、智能考勤机这些项目的核心功能就都有了。动手试试吧,遇到问题多查手册,多调试,这个过程最能积累实战经验。