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”。
七.小结
学会人脸识别模块编程,可以很方便应用到实际项目中,如门禁系统和考勤管理,可以实现人脸识别和打卡功能。