本次使用了海凌科生产的DEMO板,但是由于板子的客观因素,TTL串口没有设计好,需要自行引线才行,故需了解好模块的引脚。串口TTL进行交叉通信,GND做共地处理。如图所示,芯片模组的2引脚是RXD,连接到USB-TTL调试器的TXD或者单片机的TXD,模组的3引脚是TXD,接USB-TTL调试器的RXD或者单片机的RXD,波特率设置为115200(出厂默认,后期可自行更改)进行调试。USB-C口可以直接调试和供电,故不再说明C口,因本设计是自己焊接的板子,所以C口用起来不合适。注意的是供电部分一定要接稳点电压,1A以上,保持电源稳定才行。
根据手册和官方给的串口调试软件扩展部分的指令,比较容易的进行测试。需要注意的是自己做指令进行验证的话需要CRC校验位,那么可以通过在线网址进行生成,模型和网址如下。
本次仅仅只是个开头,做了人脸信息录入和识别的功能,其它功能以后有时间再去设计驱动,入门以后其实就不复杂了,框架基本已成,后面有时间会更新。
/**
* @说明 由燃烧电子于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
//模组返回的消息类型说明
#define HLK210_CTROK 0x00 // 操作成功
#define HLK210_CHECKEDFACE 0x01 // 检测到人脸
#define HLK210_LIVINGBODY 0x02 // 活体通过
#define HLK210_STRERROR 0x03 // 存储操作错误
#define HLK210_STRFULL 0x04 // 人脸库已满
#define HLK210_CHECKOUT 0x05 // 检测超时
#define HLK210_IDERROR 0x06 // 人脸编号ID不存在
#define HLK210_FORMERROR 0x07 // 参数或格式错误
#define HLK210_OTHERERROR 0x08 // 其他错误
#define HLK210_RAMERROR 0x09 // RAM中暂缓的模板不存在
#define HLK210_HAVEDFACE 0x0A // 此人脸已注册
typedef enum {NORMAL,INPUTFACEID,CHECKFACEID,DELETEFACEID}ENUM_HLK210;
#define HLK210_NORMALANSWERLEN 18 //命令发出应答长度
#define HLK210_FACEANSWERLEN 21 //人脸录入时反馈字节长度
#define HLK210_RECOANSWERLEN 22 //人类识别时反馈字节长度
#define HLK210_USART_REC_LEN 50
typedef struct SaveData
{
char HLK210_Buffer[HLK210_USART_REC_LEN];
char CmdDataLen;
ENUM_JUDGE isGetData; //是否获取到GPS数据
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}; //人脸识别指令
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}; //开补光灯指令
unsigned char HLK210_RECEICV_BUFFER[HLK210_USART_REC_LEN];
_HLK210_Data HLK210_Data;
u8 HLK210_point=0;
void HLK210_Receive_Byte(u8 res) //将此函数放到串口中断函数里,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); //保存数据
}
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); //开补光灯
while(HLK210_Data.isGetData == FALSE); //等待接收完应答数据
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); //等待接收完应答数据
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); //等待接收完应答数据
// HLK210_Data.isGetData = FALSE;
// for(i=0;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); //开补光灯
while(HLK210_Data.isGetData == FALSE); //等待接收完应答数据
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); //等待接收完应答数据
HLK210_Data.isGetData = FALSE;
for(i=0;i<HLK210_Data.CmdDataLen;i++)
{
USART3_SendByte(HLK210_Data.HLK210_Buffer[i]);
}
HLK210_Data.CmdDataLen = HLK210_RECOANSWERLEN;
}
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
// {
// 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();
}
}
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;
}
}
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]);
}
}