STM32驱动K210人脸识别模块经验汇总
本次是基于HLK-KT210 AI人臉識(shí)別模塊和STM32單片機(jī)進(jìn)行設(shè)計(jì)的人臉識(shí)別項(xiàng)目。主要是人臉識(shí)別功能的分析和使用。
1 模塊連接
本次使用了海凌科生產(chǎn)的DEMO板,但是由于板子的客觀因素,TTL串口沒(méi)有設(shè)計(jì)好,需要自行引線才行,故需了解好模塊的引腳。串口TTL進(jìn)行交叉通信,GND做共地處理。如圖所示,芯片模組的2引腳是RXD,連接到USB-TTL調(diào)試器的TXD或者單片機(jī)的TXD,模組的3引腳是TXD,接USB-TTL調(diào)試器的RXD或者單片機(jī)的RXD,波特率設(shè)置為115200(出廠默認(rèn),后期可自行更改)進(jìn)行調(diào)試。USB-C口可以直接調(diào)試和供電,故不再說(shuō)明C口,因本設(shè)計(jì)是自己焊接的板子,所以C口用起來(lái)不合適。注意的是供電部分一定要接穩(wěn)點(diǎn)電壓,1A以上,保持電源穩(wěn)定才行。
2 上位機(jī)調(diào)試
根據(jù)手冊(cè)和官方給的串口調(diào)試軟件擴(kuò)展部分的指令,比較容易的進(jìn)行測(cè)試。需要注意的是自己做指令進(jìn)行驗(yàn)證的話需要CRC校驗(yàn)位,那么可以通過(guò)在線網(wǎng)址進(jìn)行生成,模型和網(wǎng)址如下。
3 根據(jù)手冊(cè)和調(diào)試過(guò)程畫的人臉錄入和識(shí)別的流程
4 簡(jiǎn)單的STM32驅(qū)動(dòng)驗(yàn)證
本次僅僅只是個(gè)開頭,做了人臉信息錄入和識(shí)別的功能,其它功能以后有時(shí)間再去設(shè)計(jì)驅(qū)動(dòng),入門以后其實(shí)就不復(fù)雜了,框架基本已成,后面有時(shí)間會(huì)更新。
/*** @說(shuō)明 由燃燒電子于2022年3月24日做的初始版本V1.0* @TEL Q2772272579* @readme 僅供參考*/ #ifndef __HLK210_h #define __HLK210_h#include "stm32f10x.h" #include <string.h> #include <stdio.h> #include "Def_config.h" #include "delay.h"// #include "usart1.h" #define HLK210_SendByte USART1_SendByte //模組返回的消息類型說(shuō)明 #define HLK210_CTROK 0x00 // 操作成功 #define HLK210_CHECKEDFACE 0x01 // 檢測(cè)到人臉 #define HLK210_LIVINGBODY 0x02 // 活體通過(guò) #define HLK210_STRERROR 0x03 // 存儲(chǔ)操作錯(cuò)誤 #define HLK210_STRFULL 0x04 // 人臉庫(kù)已滿 #define HLK210_CHECKOUT 0x05 // 檢測(cè)超時(shí) #define HLK210_IDERROR 0x06 // 人臉編號(hào)ID不存在 #define HLK210_FORMERROR 0x07 // 參數(shù)或格式錯(cuò)誤 #define HLK210_OTHERERROR 0x08 // 其他錯(cuò)誤 #define HLK210_RAMERROR 0x09 // RAM中暫緩的模板不存在 #define HLK210_HAVEDFACE 0x0A // 此人臉已注冊(cè)typedef enum {NORMAL,INPUTFACEID,CHECKFACEID,DELETEFACEID}ENUM_HLK210;#define HLK210_NORMALANSWERLEN 18 //命令發(fā)出應(yīng)答長(zhǎng)度 #define HLK210_FACEANSWERLEN 21 //人臉錄入時(shí)反饋?zhàn)止?jié)長(zhǎng)度 #define HLK210_RECOANSWERLEN 22 //人類識(shí)別時(shí)反饋?zhàn)止?jié)長(zhǎng)度#define HLK210_USART_REC_LEN 50 typedef struct SaveData {char HLK210_Buffer[HLK210_USART_REC_LEN];char CmdDataLen; ENUM_JUDGE isGetData; //是否獲取到GPS數(shù)據(jù)ENUM_JUDGE isParseData; //是否解析完成ENUM_JUDGE isUsefull; //信息是否有效ENUM_HLK210 NowMode;char TimeCount; } _HLK210_Data; extern _HLK210_Data HLK210_Data;void HLK210_ClearDate(void); void HLK210_Receive_Byte(u8 res); void HLK210_InputFaceID(void); void HLK210_CheckFaceID(void);#endif #include "HLK210.h"#include "bsp_i2c_gpio.h" #include "bsp_i2c_OLED.h" #include "delay.h" #include "usart3.h" unsigned char HLK210_FaceStorageCmd[18] ={0x5A, 0x2C, 0x00, 0x00, 0x00, 0x12, 0x03, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xE5};//人臉錄入指令 unsigned char HLK210_FaceCheckCmd[18] = {0x5A, 0x2C, 0x00, 0x00, 0x00, 0x12, 0x02, 0x0C, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0xA8}; //人臉識(shí)別指令 unsigned char HLK210_FaceDelete[18] = {0x5A, 0x2C, 0x00, 0x00, 0x00, 0x12, 0x0D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x1E}; //人臉清空指令 unsigned char HLK210_LightOn[18] = {0x5A, 0x2C, 0x00, 0x00, 0x00, 0x12, 0x12, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0xAA, 0x15}; //開補(bǔ)光燈指令unsigned char HLK210_RECEICV_BUFFER[HLK210_USART_REC_LEN];_HLK210_Data HLK210_Data; u8 HLK210_point=0; void HLK210_Receive_Byte(u8 res) //將此函數(shù)放到串口中斷函數(shù)里,res形參放串口接收值。 {HLK210_RECEICV_BUFFER[HLK210_point++] = res;if(HLK210_point>1 && (HLK210_RECEICV_BUFFER[HLK210_point-2]==0x5a && HLK210_RECEICV_BUFFER[HLK210_point-1]==0x2c)){HLK210_RECEICV_BUFFER[0]=HLK210_RECEICV_BUFFER[HLK210_point-2];HLK210_RECEICV_BUFFER[1]=HLK210_RECEICV_BUFFER[HLK210_point-1];HLK210_point=2;}if(HLK210_point>=HLK210_Data.CmdDataLen){HLK210_Data.isGetData = TRUE;memset(HLK210_Data.HLK210_Buffer, 0, HLK210_USART_REC_LEN); //清空memcpy(HLK210_Data.HLK210_Buffer,HLK210_RECEICV_BUFFER, HLK210_point); //保存數(shù)據(jù)}if(HLK210_point>HLK210_USART_REC_LEN){HLK210_point=HLK210_USART_REC_LEN-1;} } void HLK210_ClearDate(void) {memset(HLK210_RECEICV_BUFFER, 0, HLK210_USART_REC_LEN); //清空HLK210_point=0;HLK210_Data.CmdDataLen = HLK210_NORMALANSWERLEN;memset(HLK210_Data.HLK210_Buffer, 0, HLK210_USART_REC_LEN); //清空HLK210_Data.isGetData = FALSE;HLK210_Data.isParseData = FALSE;HLK210_Data.isUsefull = FALSE;HLK210_Data.NowMode = NORMAL;HLK210_Data.TimeCount = 0; }void HLK210_Send_Cmd(u8 *cmd) {u8 i=0;for(i=0;i<18;i++){HLK210_SendByte(*cmd++); // == *(cmd++) 取cmd所指單元的值,cmd指向下一單元,即cmd自加1} } void HLK210_InputFaceID(void) {u8 i=0;HLK210_ClearDate();HLK210_Data.CmdDataLen = HLK210_NORMALANSWERLEN;HLK210_Data.NowMode = INPUTFACEID;HLK210_Send_Cmd(HLK210_LightOn); //開補(bǔ)光燈while(HLK210_Data.isGetData == FALSE); //等待接收完應(yīng)答數(shù)據(jù)HLK210_Data.isGetData = FALSE;for(i=0;i<HLK210_Data.CmdDataLen;i++){USART3_SendByte(HLK210_Data.HLK210_Buffer[i]);}HLK210_Send_Cmd(HLK210_FaceStorageCmd);while(HLK210_Data.isGetData == FALSE); //等待接收完應(yīng)答數(shù)據(jù)HLK210_Data.isGetData = FALSE;for(i=0;i<HLK210_Data.CmdDataLen;i++){USART3_SendByte(HLK210_Data.HLK210_Buffer[i]);}HLK210_Data.CmdDataLen = HLK210_FACEANSWERLEN; // while(HLK210_Data.isGetData == FALSE); //等待接收完應(yīng)答數(shù)據(jù) // HLK210_Data.isGetData = FALSE; // for(i=0;i<HLK210_Data.CmdDataLen;i++) // { // USART3_SendByte(HLK210_Data.HLK210_Buffer[i]); // } } void HLK210_CheckFaceID(void) {u8 i=0;HLK210_ClearDate();HLK210_Data.CmdDataLen = HLK210_NORMALANSWERLEN;HLK210_Data.NowMode = CHECKFACEID;HLK210_Send_Cmd(HLK210_LightOn); //開補(bǔ)光燈while(HLK210_Data.isGetData == FALSE); //等待接收完應(yīng)答數(shù)據(jù)HLK210_Data.isGetData = FALSE;for(i=0;i<HLK210_Data.CmdDataLen;i++){USART3_SendByte(HLK210_Data.HLK210_Buffer[i]);}HLK210_Send_Cmd(HLK210_FaceCheckCmd);while(HLK210_Data.isGetData == FALSE); //等待接收完應(yīng)答數(shù)據(jù)HLK210_Data.isGetData = FALSE;for(i=0;i<HLK210_Data.CmdDataLen;i++){USART3_SendByte(HLK210_Data.HLK210_Buffer[i]);}HLK210_Data.CmdDataLen = HLK210_RECOANSWERLEN; }調(diào)用人臉識(shí)別方法(本次沒(méi)有識(shí)別ID號(hào),只是做了有沒(méi)有識(shí)別成功的功能,后面再更新別的,數(shù)組19位存的就是有沒(méi)有成功標(biāo)識(shí),成功位0,否則為其他值,常見(jiàn)為0x02:檢測(cè)到人臉但未識(shí)別)
void Proc_CVHK210(void) {if(HLK210_Data.isGetData == TRUE && HLK210_Data.NowMode == CHECKFACEID){HLK210_Data.isGetData = FALSE;HLK210_Data.TimeCount = 0; // for(i=0;i<HLK210_Data.CmdDataLen;i++) // { // USART3_SendByte(HLK210_Data.HLK210_Buffer[i]); // }if(HLK210_Data.HLK210_Buffer[6]==0x02 && HLK210_Data.HLK210_Buffer[7]==0x0D && HLK210_Data.HLK210_Buffer[19]==0X00) {LCD_Show.personNum = 2;}if(HLK210_Data.HLK210_Buffer[6]==0x02 && HLK210_Data.HLK210_Buffer[7]==0x0D && HLK210_Data.HLK210_Buffer[19]!=0X00) {LCD_Show.personNum = 1;}LCD_Display();} }調(diào)用超時(shí)檢測(cè)方法,因沒(méi)有人臉時(shí)需要更新屏幕顯示為“無(wú)人”狀態(tài),故用定時(shí)器設(shè)定3秒時(shí)間,沒(méi)有收到人臉數(shù)據(jù)時(shí),設(shè)定為無(wú)人。
if(TIM4_FlagStatus.Flag_1000MS == TRUE) {HLK210_Data.TimeCount ++;if(HLK210_Data.isGetData == FALSE && HLK210_Data.TimeCount>2){LCD_Show.personNum = 0;LCD_Display();HLK210_Data.TimeCount = 3;} }串口1設(shè)定為和K210模塊通信串口,調(diào)試過(guò)程進(jìn)行串口3輸出串口1接收到的人臉識(shí)別模塊數(shù)據(jù),以驗(yàn)證接收設(shè)計(jì)程序是否有問(wèn)題。
HLK210_InputFaceID(); if(HLK210_Data.isGetData == TRUE && HLK210_Data.NowMode == INPUTFACEID) {HLK210_Data.isGetData = FALSE;for(i=0;i<HLK210_Data.CmdDataLen;i++){USART3_SendByte(HLK210_Data.HLK210_Buffer[i]);}if(HLK210_Data.HLK210_Buffer[6]==0x03 && HLK210_Data.HLK210_Buffer[7]==0x0D && HLK210_Data.HLK210_Buffer[18]==0X00) //錄入成功{HLK210_CheckFaceID();} } if(HLK210_Data.isGetData == TRUE && HLK210_Data.NowMode == CHECKFACEID) {HLK210_Data.isGetData = FALSE;for(i=0;i<HLK210_Data.CmdDataLen;i++){USART3_SendByte(HLK210_Data.HLK210_Buffer[i]);} }5 效果如下
總結(jié)
以上是生活随笔為你收集整理的STM32驱动K210人脸识别模块经验汇总的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: IGMP-Snooping协议原理
- 下一篇: 一款基于微信的小程序电商系统源码(前端+