当前位置: 首页 > news >正文

STM32传感器模块编程实践(十三)人脸识别模块简介及驱动

文章目录

    • 一.概要
    • 二.BE5100模块主要技术指标
    • 三.BE5100模块接线说明
    • 四.BE5100模块通讯协议介绍
    • 五.人脸识别模块录入与识别流程
    • 六.STM32单片机与人脸识别模块录入与识别实验
      • 1.硬件准备
      • 2.软件工程
      • 3.软件主要代码
      • 3.实验效果
    • 七.小结

一.概要

BE5100模块应用广泛,只要涉及到授权、管理、开关等方面的功能,均可用 BE5100模块的人脸识别功能来代替 IC 卡、密码、硬件开关等,适合从低端到高端的所有系统,比如:
门锁、保险柜、金融等安全领域。
门禁系统、工控机、 驾培、考勤等身份领域;
私人会所、管理软件、授权许可等管理领域;
医保领取、养老领取、人脸支付等金融领域。
在这里插入图片描述

二.BE5100模块主要技术指标

在这里插入图片描述

三.BE5100模块接线说明

在这里插入图片描述

在这里插入图片描述

BE5100模块与单片机只要4根线就能连接

单片机开发板 人脸识别模块
3.3V-----------------------VDD
GND----------------------GND
PA9------------------------RX
PA10----------------------TX

四.BE5100模块通讯协议介绍

串口通讯参数:
在这里插入图片描述
指令格式:
在这里插入图片描述

以下对指令包中各域进行说明。
1:同步域(SyncWord):作为指令包开头的字节,固定为 EF AA。
2:消息类别(MsgID):消息类别主要分成 3 类,命令消息(Command)、应答消息(Reply)和通知消息(Note)。
3:数据域字节数(Size):数据域包含的字节数。
4:数据域(Data):需要传输的具体数据,如确认码、参数等。若无数据传输,数据域可为空。
5: 校验域(Check):对 MsgID、Size、Data 这三个区域所有字节按位进行异或运算(XOR)。

消息类别MsgID主要定义如下:
在这里插入图片描述

单片机发给模块命令帧格式如下:
在这里插入图片描述

模块返回给单片机命令帧如下:
在这里插入图片描述

例如人脸识别模块的复位命令消息:

单片机发送的数据帧格式:
在这里插入图片描述
模块返回的数据帧格式:
在这里插入图片描述
串口通讯示例:
单片机Send:EF AA 10 00 00 10
单片机Recv:EF AA 00 00 02 10 00 12

五.人脸识别模块录入与识别流程

人脸录入操作流程:
在这里插入图片描述
在录入过程中,人脸锁算法模组不限制录入方向的顺序,用户可以任意组合录入方向的顺序,上图是以其中一种顺序为例进行说明。
当主控下达录入某个方向的人脸的指令后,模组开始工作,并实时地返回人脸的状态、位置、姿态等信息(以NOTE 消息的形式返回),用户可根据该信息提醒录入人进行姿态位置的调整,当录入成功后,模组将以 REPLY 消息的形式返回录入结果,如果录入不成功,模组也会相应地返回失败的原因。值得注意的是,当模组采集到的第一帧图像就录入成功时,将直接以 REPLY 消息的形式返回结果。录入过程中可通过 FACE RESET 指令终止录入,先前的录入状态也会清零。如果在录入过程中突然断电,之前录入的人脸也不会保存。

人脸验证操作流程:
在这里插入图片描述

六.STM32单片机与人脸识别模块录入与识别实验

1.硬件准备

STLINK接STM32F103C8T6开发板,STLINK接电脑USB口,5V USB线接板子的USB口。

指纹模块与单片机开发板接线:
103C8T6 开发板
5V --------------------------------------模块 V
PA10-----------------------------------模块 T
PA9 ------------------------------------模块 R
GND------------------------------------模块 G

在这里插入图片描述

2.软件工程

采用STM32F103C8T6标准库软件工程方式。
在这里插入图片描述

3.软件主要代码

串口数据接收相关代码

//接收标志函数,返回0说明没收据接收,返回1说明有数据收到
uint8_t Uart_RecvFlag(void)
{if(UartRxOKFlag==0x55){UartRxOKFlag=0;UartRxLen=UartIntRxLen;memcpy(Usart1Data.Uart_RxBuff,UartIntRxbuf,UartIntRxLen);//把缓冲区的数据,放入需要解析的数组UartIntRxLen=0;Usart1Data.Rx_Len  = UartRxLen; //取出最后的接收长度Usart1Data.receive_flag = SET; //进定时器就是接收完成 设置完成标志位。return 1;}return 0;
}
//串口2在1字节接收完成回调函数
void HAL_UART_RxCpltCallback(void)
{UartRxFlag=0x55;//接收标志置位UartIntRxbuf[UartRxIndex]=USART_ReceiveData(USART1);//数据写入缓冲区UartRxIndex++;//记载数目加1if(UartRxIndex>=sizeof(UartIntRxbuf))//缓冲区是10字节,如果存满,归零{UartRxIndex=0;}USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//接收中断打开
}
//1ms调用一次,用来判断是否收完一帧
void UART_RecvDealwith(void)
{if(UartRxFlag==0x55){if(UartIntRxLen<UartRxIndex)//UartIntRxLen小于UartRxIndex,说明有收到新的数据,把接收长度增加{UartIntRxLen=UartRxIndex;}else{UartRxTimer++;if(UartRxTimer>=50)//50ms,等待,没收到新数据,说明已经收完一帧{UartRxTimer=0;UartRxFlag=0;UartRxOKFlag=0x55;UartRxIndex=0;}}}
}/*以上是串口 的通用接收 判断 回调  接收完成等函数*/

main函数代码

//主函数,采用外部8M晶振,72M系统主频,可以在void SetSysClock(void)函数中选择主频率设置
int main(void){	int i;delay_init();	    	//延时函数初始化,通过Systick中断实现1ms延时功能  RCC_Configuration();//USART1时钟使能,GPIO时钟使能NVIC_Configuration();//中断接收使能GPIO_Config_Init();	//USART1管脚PA9,PA10初始化USART_Config_Init();//USART1配置,波特率115200,8位数据,1位停止位,无校验OLED_Init();//OLED初始化  OLED_Clear();//OLED清屏 OLED_ShowCHinese(18,0,0);//显示中文(光)OLED_ShowCHinese(36,0,1);//显示中文(子)OLED_ShowCHinese(54,0,2);//显示中文(物)OLED_ShowCHinese(72,0,3);//显示中文(联)OLED_ShowCHinese(90,0,4);//显示中文(网)OLED_ShowString(6,3,(uint8_t *)"Face Detection");//显示字符OLED_ShowString(6,6,(uint8_t *)"STM32F103 Demo");//显示字符  Uart1_Send_Reset();//模组复位命令。while (1){OLED_DISPLAY();//显示函数KEY_SCAN();	//按键扫描函数。Uart1_Deal();//与人脸识别模块通讯 /* USER CODE END WHILE *//* USER CODE BEGIN 3 */}}

人脸识别配置相关

/**复位命令。。。*/
void Uart1_Send_Reset(void)      
{uint8_t i;i = 0;Usart1Data.Uart_TxBuff[i++] = 0xEF;   //固定的消息开头同步字 0xEF 0xAAUsart1Data.Uart_TxBuff[i++] = 0xAA;		//固定的消息开头同步字 0xEF 0xAAUsart1Data.Uart_TxBuff[i++] = 0x10;		//消息 ID   0X10复位信息Usart1Data.Uart_TxBuff[i++] = 0x00;		//数据大小 几个字节。高8位 数据位 高字节Usart1Data.Uart_TxBuff[i++] = 0x00;		//数据大小 几个字节。低8位   后边没数据位了  数据位低字节。Usart1Data.Uart_TxBuff[i++] = 0x10;		//没有数据位了 这位就是校验位UART1_Send(i);
//delay_ms(100); //删除等待
}/**核实发送识别。**/
void Uart1_Send_Verify(void)   //串口1给 屏幕识别的信息 。  解锁 开始 识别人脸 开始比对。  开始识别。。。。
{uint8_t i;i = 0;Usart1Data.Uart_TxBuff[i++] = 0xEF;//固定的消息开头同步字 0xEF 0xAAUsart1Data.Uart_TxBuff[i++] = 0xAA;//固定的消息开头同步字 0xEF 0xAAUsart1Data.Uart_TxBuff[i++] = 0x12;//消息 ID   0X12复位信息, 解锁。 解锁后断电。?????Usart1Data.Uart_TxBuff[i++] = 0x00; //数据大小 高8位Usart1Data.Uart_TxBuff[i++] = 0x02;//数据大小 低8位Usart1Data.Uart_TxBuff[i++] = 0x00; //数据Usart1Data.Uart_TxBuff[i++] = 0x05;	//数据 超时时间Usart1Data.Uart_TxBuff[i++] = 0x15;  //异或校验   异或校验是 从 EF AA 的后边 开始的  最后一位是异或校验UART1_Send(i);}
/*删除人员的ID*/ //这个是删除指定人员的ID
void Uart1_Send_Delete_User_ID(uint16_t  ID)
{uint8_t i;i = 0;Usart1Data.Uart_TxBuff[i++] = 0xEF;Usart1Data.Uart_TxBuff[i++] = 0xAA;Usart1Data.Uart_TxBuff[i++] = 0x20;  //删除用户   //删除指定的用户。Usart1Data.Uart_TxBuff[i++] = 0x00;		//数据长度高字节Usart1Data.Uart_TxBuff[i++] = 0x02;		//数据长度低字节Usart1Data.Uart_TxBuff[i++] = (ID >> 8) &0XFF;  //取高8位Usart1Data.Uart_TxBuff[i++] = ID & 0XFF;				//取低8位Usart1Data.Uart_TxBuff[i++] = Check_Sum_Xor(&Usart1Data.Uart_TxBuff[2],5);UART1_Send(i);}/**读取模组内所有的 ID的命令协议不同单独处理。**/
void Uart1_Send_Get_All_User_ID(void) //读取模组内部所有用户数量和用户ID列表  
{uint8_t i;i = 0;Usart1Data.Uart_TxBuff[i++] = 0xEF;Usart1Data.Uart_TxBuff[i++] = 0xAA;Usart1Data.Uart_TxBuff[i++] = 0x24; //读取模组内部所有用户数量和用户ID列表,Usart1Data.Uart_TxBuff[i++] = 0x00; //高字节Usart1Data.Uart_TxBuff[i++] = 0x01; //低字节 Usart1Data.Uart_TxBuff[i++] = 0x00; //低字节  Usart1Data.Uart_TxBuff[i++] = 0x25;  //异或校验。。。。。。UART1_Send(i);
}//**删除所有命令。
void	Uart1_Delete_all_User_ID(void)
{uint8_t i;i = 0;Usart1Data.Uart_TxBuff[i++] = 0xEF;Usart1Data.Uart_TxBuff[i++] = 0xAA;Usart1Data.Uart_TxBuff[i++] = 0x21; //读取模组内部所有用户数量和用户ID列表,Usart1Data.Uart_TxBuff[i++] = 0x00; //高字节Usart1Data.Uart_TxBuff[i++] = 0x00; //低字节  Usart1Data.Uart_TxBuff[i++] = 0x21;  //异或校验。。。。。。UART1_Send(i);}///***删除指定人员的ID 
void Uart1_Send_Delete_Point_User_ID(uint8_t H_D,uint8_t L_D)
{uint8_t i;i = 0;Usart1Data.Uart_TxBuff[i++] = 0xEF;Usart1Data.Uart_TxBuff[i++] = 0xAA;Usart1Data.Uart_TxBuff[i++] = 0x20;  //删除用户   //删除指定的用户。Usart1Data.Uart_TxBuff[i++] = 0x00;		//数据长度高字节Usart1Data.Uart_TxBuff[i++] = 0x02;		//数据长度低字节Usart1Data.Uart_TxBuff[i++] = H_D;//取高8位Usart1Data.Uart_TxBuff[i++] =	L_D;//取低8位Usart1Data.Uart_TxBuff[i++] = Check_Sum_Xor(&Usart1Data.Uart_TxBuff[2],5);UART1_Send(i);
}/**手动单帧 添加人脸命令**/
void Uart1_Send_EnrollSingleWithID_Point_User_ID(void)
{uint8_t i;i = 0;Usart1Data.Uart_TxBuff[i++] = 0xEF;Usart1Data.Uart_TxBuff[i++] = 0xAA;Usart1Data.Uart_TxBuff[i++] = 0x1D;  //录入用户。Usart1Data.Uart_TxBuff[i++] = 0x00;		//数据长度高字节Usart1Data.Uart_TxBuff[i++] = 0x23;		//数据长度低字节Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] = 0x00;Usart1Data.Uart_TxBuff[i++] =	0x0A;Usart1Data.Uart_TxBuff[i++] = Check_Sum_Xor(&Usart1Data.Uart_TxBuff[2],Usart1Data.Uart_TxBuff[4]+3);UART1_Send(i);
}
if(Usart1Data.receive_flag == SET) //接收完成标志位。   在中断里设置的接收完备{Usart1Data.receive_flag = RESET; //重新复位
//接收判断是什么状态。switch(Usart1Data.Uart_RxBuff[5]) //收到模块发送了过来的数据{case 0x10:    //这个是异或校验值。  {//复位成功///复位命令  Usart1Data.Uart_RxBuff[5] = 0;break;}case 0x01:    {//通知包/////*****/////备用未使用Usart1Data.Uart_RxBuff[5] = 0;break;}case 0x12: //识别{if(Usart1Data.Uart_RxBuff[6] == 0x00 &&((Usart1Data.Uart_RxBuff[7] << 8) + Usart1Data.Uart_RxBuff[8]) < 101) //ID最大的值是1----100   //识别成功后有数据。   {/*识别成功后的ID*/Face_ID =	Usart1Data.Uart_RxBuff[7]<<8 |Usart1Data.Uart_RxBuff[8];Display_Cmd = 0x02;//识别成功////人脸识别成功   // 显示人脸识别成功。//去显示识别成功}else if(Usart1Data.Uart_RxBuff[6] == 0x08 && Usart1Data.Uart_RxBuff[7] == 0x18) //没有已录入的用户  未检测到人脸  {Display_Cmd = 0x04;//显示未注册}//如果都不是识别到的数据。都不是识别到的IDelse  ///    EF AA 00 00 26 12 08 FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3C  //对应的识别失败。Uart_RxBuff[7]  Uart_RxBuff[8]  是 FF FF 就是识别失败 成功会返回识别到的正确ID。{//识别失败Display_Cmd = 0x03;//显示识别失败}break;   //正常switch识别到然后退出。。。。//去显示识别成功。}case 0x1D:	 //这个是 添加人脸特征值返回的数据。{if(Usart1Data.Uart_RxBuff[6] == 0x00)//注册成功{Face_ID =	Usart1Data.Uart_RxBuff[7]<<8 |Usart1Data.Uart_RxBuff[8];//添加成功后返回添加的ID值是多少。Display_Cmd = 0x07;//去显示录入成功}			else if(Usart1Data.Uart_RxBuff[6]==0x0A) //杭州模组不适用。{Display_Cmd = 0x08;}else if(Usart1Data.Uart_RxBuff[6]==0x0D) //杭州模组录入超时  录入的时候没有人脸的情况下。{Display_Cmd = 0x09;//显示录入失败}else{Display_Cmd = 0x09;//显示录入失败}break;}case 0x21:  // 删除所有人脸 回复命令  {	Display_Cmd = 0x0A; //显示清除人脸中 然后显示清除成功。break;}default:{	break;}}

3.实验效果

按下 KEY 按键,1 秒松手,液晶上提示“开始识别”
在这里插入图片描述
第一次使用,还未录入人脸,液晶上会提示“未注册”
在这里插入图片描述
按住 KEY 按键,10 秒~19 秒之间时效即可,松手,液晶上会提示“录入人脸中”
在这里插入图片描述
拿起人脸识别模块,对准人脸,进行录入。人脸识别模块上的指示灯会闪烁红灯,直到指示灯停止闪烁,液晶上会显示“录入成功 Face_ID: 1”

在这里插入图片描述

按下 KEY 按键,1 秒松手,液晶上提示“开始识别”,把人脸识别模块对准已录入过的人脸,模块上的指示灯会闪烁一下,然后液晶上会提示“识别成功 Face_ID: 1”。
在这里插入图片描述

七.小结

学会人脸识别模块编程,可以很方便应用到实际项目中,如门禁系统和考勤管理,可以实现人脸识别和打卡功能。

http://www.dtcms.com/a/321893.html

相关文章:

  • Redis缓存击穿、穿透雪崩
  • ADB 命令执行模块开发:双模式(普通模式Shell交互模式)实现、线程安全与资源管理优化
  • Linux系统层IO
  • Node.js 》》数据验证 Joi 、express-joi
  • 【数字图像处理系列笔记】Ch06:图像压缩
  • 数据结构5-哈希表
  • 板卡如何安装在主机系统(刀片服务器或计算节点)
  • Linux之shell脚本入门
  • Unity基于Recoder的API写了一个随时录屏的工具
  • http状态码403,404,500等是什么意思?
  • Cursor CLI 来了,准备 Build anything
  • Sum of Three Values(sorting and searching)
  • 全面了解selenium
  • RSA非对称加密
  • 除了腾讯会议,私有化有哪些选择?
  • 安科瑞EMS3.0源网荷储一体化解决方案 全面助力零碳园区建设
  • FreeSWITCH parse-all-invite-headers
  • 记一次lombok链式调用引发EasyExcel兼容性的问题
  • 记录网站突然报错503
  • 第六章第四节 PWM驱动LED呼吸灯 PWM驱动舵机 PWM驱动直流电机
  • 计算机网络:到底什么是可变长子网掩码VLSM?
  • win11中Qt5.14.0+msvc2019+opencv4.9配置
  • 全方位无限随机地图实现指南
  • 模块 PCB 技术在未来通信领域的创新突破方向
  • Docker 创建镜像错误记录
  • Java技术栈/面试题合集(21)-Docker篇
  • 如何动态执行 JS 脚本
  • 揭秘Java synchronize:轻量级锁升级与偏向锁
  • Java-注解
  • 重新 mybatis plus 的 撒着OrUpdate 方法,实现根据自定义字段插入或者修改