本次使用了海凌科生产的测试板,该测试板需要自行引线才能与stm32进行串口通信,需注意模块的引脚。串口TTL进行交叉通信,GND做共地处理。
u16 xbx_crc_calculate(u8 *addr ,u8 datalen)//CRC校验方式
{
u8 i,j;
u16 crc;
crc = 0xffff;
for(i = 0; i < datalen; i++)
{
crc ^= *addr++;
for(j=0;j<8;j++)
{
if(crc & 0x01)
crc = (crc >> 1) ^ 0x8408;
else
crc >>= 0x01;
}
}
return ~crc;
}
以下是主要的通信协议代码
u8 recv_date(u8 len,u16 wait_time) //中断接收
{
u16 time;
recv_cnt=0;
while(recv_cnt<=len){
delay_ms(1);
if(time++>wait_time)
return 1;
}
return 0;
}
void Send_Byte(uint8_t byte) //串口发送一个字节
{
while( USART_GetFlagStatus(USART3, USART_FLAG_TC) != SET);//等待发送完成 检测 USART_FLAG_TC 是否置1
USART_SendData(USART3, byte); //通过库函数发送数据
USART_ClearITPendingBit(USART3, USART_IT_TC);//清除串口3发送完成中断线路挂起位
}
void Send_String(uint8_t *string, u16 length)
{
static u16 i=0;
for(i = 0; i < length; i++)
Send_Byte(*string++);//发送一个字节
}
/* 数据包格式
起始标志 0x5a2c 2字节
保留 0x0000 2字节
数据包长度 N+10 2字节
命令类型 Cmd 2字节
数据 < 256字节 n字节
校验(CRC16) 除校验位的其他全部字节 2字节
*/
void add_head(u16 head1) //起始标志
{
send_buf[0]=head1>>8;
send_buf[1]=(u8)head1;
send_buf[2]=0x00;
send_buf[3]=0x00;
}
void add_date_len(u16 len) //数据
{
send_buf[4]=len>>8;
send_buf[5]=(u8)len;
}
void add_cmd(u16 cmd) //命令类型
{
send_buf[6]=cmd>>8;
send_buf[7]=(u8)cmd;
}
u16 add_face(u16 wait_time) //添加人脸特征
{
u16 crc,uid;
add_head(head); //0x5a2c
add_cmd(add_face_cmd); //0x030c
add_date_len(18);
send_buf[8]= 0x00;
send_buf[9]= 0x00;
send_buf[10]= 0x00;
send_buf[11]= 0x00;
send_buf[12]= wait_time>>8; //时间高8位
send_buf[13]= (u8)wait_time; //时间低8位
send_buf[14]= 0x00;
send_buf[15]= 0x00;
crc=xbx_crc_calculate(send_buf,16);
send_buf[16]=crc>>8;
send_buf[17]=(u8)crc;
Send_String(send_buf,18);
if(recv_date(18,300)==0)
{
if(recv_buf[15]==0) //启动人脸录入成功
{
printf("\r\nadd_face recv ok2\r\n");
if(recv_date(21,wait_time*1000)==0)
{
printf("\r\nadd_face recv ok3\r\n");
if(recv_buf[18]==0) //录入成功
{
uid = (recv_buf[16]<<8)+recv_buf[17];
printf("\r\nadd_face recv ok4\r\n");
}
}
else
{
printf("\r\nadd_face recv error3\r\n");
return 0xffff;
}
}
else
{
printf("\r\nadd_face recv error2\r\n");
return 0xffff;
}
}
else{
printf("\r\nadd_face recv error1\r\n");
return 0xffff;
}
recv_cnt=0;
return uid;
}
u16 add_face_ret() //添加人脸特征返回
{
u16 uid;
uid=0; //UID应该非0
if(recv_cnt>=20)
{
delay_ms(1);
recv_cnt=0;
if( (recv_buf[18]==0)&&(recv_buf[6]==(add_face_ret_cmd>>8))&&(recv_buf[7]==(u8)add_face_ret_cmd))
uid = (recv_buf[16]<<8)+recv_buf[17];
else
return 0;
}
return uid;
}
/*
D:1显示 0不显示
T:显示时间
x:0-240 横坐标
y:0-320 纵坐标
colour: RGB565格式颜色
str[]:待显示字符串 utf-8编码
*/
u16 set_lcd_showstring(u8 D,u16 T,u16 x,u16 y,u16 colour,u8 str[])
{
u16 crc;
u8 i=0;
add_head(head);
add_cmd(lcd_showsting_cmd);
send_buf[8]= D;
send_buf[9]= T>>8;
send_buf[10]= (u8)T;
send_buf[11]= x>>8;
send_buf[12]= (u8)x;
send_buf[13]= y>>8;
send_buf[14]= (u8)y;
send_buf[15]= colour>>8;
send_buf[16]= (u8)colour;
while(*str!=0)
{
send_buf[17+i]=*str++;
i++;
}
add_date_len(i+19);
crc=xbx_crc_calculate(send_buf,i+17);
send_buf[i+17]=crc>>8;
send_buf[i+18]=(u8)crc;
Send_String(send_buf,i+19);
if(recv_date(18,300)==0)
{
if(recv_buf[15]!=0) //
{
return 0xffff;
}
}
else
{
return 0xffff;
}
recv_cnt=0;
return 0;
人脸识别