晟元协议指纹头,单片机开发踩坑指南

2023-11-03

一、硬件说明

1、接口

 注意:其中Touch_VCC 3.3V是需要常供电的,用于Touch_Out触摸唤醒供电,VDD3.3V可以检测到Touch_Out高电平信号再上电。如果不需要低功耗设计,可以忽略Touch_Out和Touch_VCC 3.3V引脚,悬空即可。

2、供电

注意: 需要考虑电路驱动能力,电压和电流稳定,避免指纹头运行异常。

3、串口配置

 注意:就算单片机和指纹头设置一样的波特率,但是也有可能有误差注意配置好单片机时钟。

 

 以华大32位单片机为例,可以看出4MHz和24MHz主频下误差率差别很大。

二、软件说明

1、协议格式

主要针对命令包,其他包格式没用过,不做说明,自查手册。

 注意:特别需要注意的是校验和的计算(校验和16bit = 包长度+指令+参数1+参数二+参数N)

每个命令都有应答包响应格式如下:

 2、简单指纹操作

相信使用指纹头做指纹识别,首先肯定是最基础的就是指纹的增删改查了,不过改就是覆盖,和添加指纹是一样,所以就是增删查了!

对指纹头来说,修改数据是高级操作,是需要权限的,所以就需要先验证密码,来获取权限。

2.1、验证口令FP_VfyPwd

 芯片地址一般默认0xffffffff,口令默认0x00000000,通过查询手册参数表可以得到。

 接下来就可以愉快的拼凑出通信报文进行通信了。

 2.2自动录入指纹

手册提供了指纹录入的一站式命令(自动注册模板 PS_AutoEnroll),命令格式和录入流程如下。

 

 注意:不同指纹头要求最少录入的次数不同,如果设置次数不够在验证指纹时可能无法识别,一般2-6次,如果不清楚6次最稳妥。

2.3 清空指纹

会添加指纹了,也要回删除指纹,先从最简单的清空指纹命令开始, 清空指纹库 PS_Empty

参数都不用设置,直接发,省事。 

2.3自动指纹验证

手册提供了,自动验证指纹的一站式命令(自动验证指纹 PS_AutoIdentify),格式和识别流程如下。 

注意:安全等级1-5,我使用的0x1,id号使用0xffff,参数使用0x0000 就好了,可以根据自己需求修改。

2.4 整体操作流程图

 注意:这里指纹识别只识别一次,如果不用触摸中断,可以在循环中使用PS_GetImage命令判断手指是否按下,另外由于我录入指纹是需要id自动累加的,所以先读取索引表计算空闲的id,发送休眠指令是为了识别完成给指纹头断电节能,断电之前要先发送休眠指令,直接断电指纹头可能会出现异常。

3、分步指纹操作

一站式命令固然好用,但是很多内部处理步骤我们看不到,使用起来也不够灵活,所以我们尝试手动一步一步来做识别。

为了方便我直接录入和识别的流程全部贴出来

 注意:一个空间存储的指纹是由多个指纹特征合成的,你甚至可以循环录入指纹的时候每次都按不同的手指,就可以一次添加多个手指了,但是识别准确度会下降,并不推荐。

另外PS_GetImage PS_GetEnrollImage作用差不多,PS_GetImage 用于识别, PS_GetEnrollImage用于录入,有些甚至可以串用,但是有些指纹头可能不行,不推荐串用

PS_GetImage是个很好用的命令,可以在循环中使用检测手指是否按下,检测到指纹再生成特征进行指纹识别。

录入指纹大致说来就是获取一次图像生成一个特征,然后将多个特征合并存储就好了。

识别指纹就是录入指纹生成特征,然后用特征去指纹库里检索。

三、代码片段

1、宏定义

//晟元协议
#define DATA_SIZE_MAX		(256-2)		//数据区域最大值 减去校验和2字节
#define CMD_FLAG				1											//命令标志
#define	DATA_FLAG				2											//数据标志
#define	ACT_FLAG				7											//应答标志
#define DATA_END_FLAG			8											//数据包结束标志

typedef enum {
	CMD_VERIFY_PASSWORD = 1,
	CMD_VERIFY_DEFPASSWORD,
	CMD_SET_PASSWORD,
	CMD_SET_DEFPASSWORD,
	CMD_GET_IMAGE,
	CMD_GEN_TEMPLET1,
	CMD_GEN_TEMPLET2,
	CMD_GEN_TEMPLET3,
	CMD_SEARCH_FINGER,
	CMD_MERGE_TEMPLET,
	CMD_STORE_TEMPLET,
	CMD_GETENROLLIMAGE,
	CMD_CMP_TEMPLET,
	CMD_GET_NUMBERS,
	CMD_READINDEXTABLE,
	CMD_CONTROLLED,
	CMD_DEFINELED,
	CMD_READSYSPARA,
	CMD_SETBAUDRATE,
	CMD_SETDEFADDR,
	CMD_HANDSHAKE,
	CMD_READ_NOTE,
	CMD_CLEAR_NOTE,
	CMD_DELETCHAR,
	CMD_EMPTY,
	CMD_SLEEP,
	CMD_AUTOENROLL,
	CMD_AUTOIDENTIFY
}COMMON_CMD;

struct fp_package {
	uint16_t		header;
	uint32_t		addr;
	uint8_t			flag;
	uint16_t		length;
	uint8_t			data[DATA_SIZE_MAX];
	uint16_t		sum;
};

struct fp_send_package {
	uint16_t		header;
	uint32_t		addr;
	uint8_t			flag;
	uint16_t		length;
	uint8_t			code;
	uint8_t			data[DATA_SIZE_MAX-1];
	uint16_t		sum;
};

struct fp_recv_package {
	uint16_t		header;
	uint32_t		addr;
	uint8_t			flag;
	uint16_t		length;
	uint8_t			ret;
	uint8_t			data[DATA_SIZE_MAX-1];
	uint16_t		sum;
};

struct uart_rcbuf_s{
	uint8_t u8ResponeData[FP_USART_BUFF_MAX];
	uint16_t u8ResponeCnt;
	uint16_t u8finish;
};

//一站式注册指纹
#define USE_AUTOENROLL(N)							{N.length=8;N.data[0]=0x31;N.data[1]=0x0;N.data[2]=0x01;N.data[3]=0x6;}
//自动采集指纹
#define USE_AUTOIDENTIFY(N)					{N.length=8;N.data[0]=0x32;N.data[1]=0x1;N.data[2]=0xff;N.data[3]=0xff;}
//验证设备握手口令
#define USE_VERIFY_PASSWORD(N)				{N.length=7;N.data[0]=0x13;N.data[1]=0x12;N.data[2]=0x34;N.data[3]=0x43;N.data[4]=0x21;}
#define USE_VERIFY_DEFPASSWORD(N)			{N.length=7;N.data[0]=0x13;N.data[1]=0;N.data[2]=0;N.data[3]=0;N.data[4]=0;}
//设置设备握手口令
#define USE_SET_PASSWORD(N)					{N.length=7;N.data[0]=0x12;N.data[1]=0x12;N.data[2]=0x34;N.data[3]=0x43;N.data[4]=0x21;}
#define USE_SET_DEFPASSWORD(N)				{N.length=7;N.data[0]=0x12;N.data[1]=0;N.data[2]=0;N.data[3]=0;N.data[4]=0;}
//探测手指并从传感器上读入图像
#define USE_GET_IMAGE(N)								{N.length=3;N.data[0]=0x1;}
//根据原始图像生成指纹特征1
#define USE_GEN_TEMPLET1(N)					{N.length=4;N.data[0]=0x2;N.data[1]=0x1;}
//根据原始图像生成指纹特征2
#define USE_GEN_TEMPLET2(N)					{N.length=4;N.data[0]=0x2;N.data[1]=0x2;}
//根据原始图像生成指纹特征3
#define USE_GEN_TEMPLET3(N)					{N.length=4;N.data[0]=0x2;N.data[1]=0x3;}
//以CharBufferA或CharBufferB中的特征文件搜索整个或部分指纹库
#define USE_SEARCH_FINGER(N)				{N.length=8;N.data[0]=0x04;N.data[1]=0x1;N.data[2]=0x0;N.data[3]=0x0;N.data[4]=0x00;N.data[5]=0x64;}
//将CharBufferA与CharBufferB中的特征文件合并生成模板,结果存于ModelBuffer
#define USE_MERGE_TEMPLET(N)				{N.length=3;N.data[0]=0x5;}
//将ModelBuffer中的文件储存到flash指纹库中
#define USE_STORE_TEMPLET(N)				{N.length=6;N.data[0]=0x6;N.data[1]=0x1;N.data[2]=0x0;N.data[3]=0x0;}
//GetEnrollImage
#define USE_GETENROLLIMAGE(N)					{N.length=3;N.data[0]=0x29;}
//cmp
#define USE_CMP_TEMPLET(N)					{N.length=3;N.data[0]=0x3;}
//GET NUMBERS
#define USE_GET_NUMBERS(N)					{N.length=3;N.data[0]=0x1d;}
//READ INDEXTABLE
#define USE_READINDEXTABLE(N)					{N.length=4;N.data[0]=0x1f;}
//set baudrate
#define USE_SETBAUDRATE(N)					{N.length=5;N.data[0]=0x0E;N.data[1]=0x04;N.data[2]=0x06;}
//Control LED
#define USE_CONTROLLED(N)					{N.length=4;N.data[0]=0x40;N.data[1]=0x0f;}
//Define LED
#define USE_DEFINELED(N)					{N.length=7;N.data[0]=0x3c;N.data[1]=0xf5;N.data[2]=0x0;N.data[3]=0x00;}
//读系统基本参数
#define USE_READSYSPARA(N)					{N.length=3;N.data[0]=0x0f;}
//设置默认地址
#define USE_SETDEFADDR(N)					{N.length=7;N.data[0]=0x15;N.data[1]=0xFF;N.data[2]=0xFF;N.data[3]=0xFF;N.data[4]=0xFF;}
//握手
#define USE_HANDSHAKE(N)					{N.length=3;N.data[0]=0x35;}
//Read Note
#define USE_READ_NOTE(N)					{N.length=4;N.data[0]=0x19;}
//Clear Note
#define USE_CLEAR_NOTE(N)					{N.length=36;N.data[0]=0x18;N.data[1]=0x2;}
//删除一个指纹
#define	USE_DELETCHAR(N) 	{N.length=7;N.data[0]=0x0C;N.data[4]=0x1;}
//清空指纹库
#define USE_EMPTY(N)		{N.length=3;N.data[0]=0x0D;}
//休眠
#define USE_SLEEP(N)		{N.length=3;N.data[0]=0x33;}
//错误标志

enum {
	FP_ERROR = -1,
	FP_OK = 0,
	FP_TIMEOUT = 1,
};

enum FP_RES_CODE{			
	RES_OK = 0,			//		00H:表示指令执行完毕或 OK; 
	RES_RCERR,			//		01H:表示数据包接收错误; 
	RES_NOTOUCH,		//		02H:表示传感器上没有手指; 
	RES_TINERR,			//		03H:表示录入指纹图像失败; 
	RES_PTOOWATER,		//		04H:表示指纹图像太干、太淡而生不成特征; 
	RES_PTOODRY,		//		05H:表示指纹图像太湿、太糊而生不成特征; 
	RES_PTOOMESS,		//		06H:表示指纹图像太乱而生不成特征; 
	RES_PFTOOFEW,		//		07H:表示指纹图像正常,但特征点太少(或面积太小)而生不成特征; 
	RES_FPNOPASS,		//		08H:表示指纹不匹配; 
	RES_FPNOSEARCH,		//		09H:表示没搜索到指纹; 
	RES_FMERERR,		//		0aH:表示特征合并失败; 
	RES_IDXOVER,		//		0bH:表示访问指纹库时地址序号超出指纹库范围; 
	RES_RDMODERR,		//		0cH:表示从指纹库读模板出错或无效; 
	RES_ULFUERR,		//		0dH:表示上传特征失败; 
	RES_CNRDDPAK,		//		0eH:表示模块不能接收后续数据包; 
	RES_ULPICERR,		//		0fH:表示上传图像失败; 
	RES_DELMODERR,		//		10H:表示删除模板失败; 
	RES_ENPFPFAULT,		//		11H:表示清空指纹库失败; 
	RES_CNENLPMOD,		//		12H:表示不能进入低功耗状态; 
	RES_PWDERR,			//		13H:表示口令不正确; 
	RES_RESETFAULT,		//		14H:表示系统复位失败; 
	RES_BUFNORPIC,		//		15H:表示缓冲区内没有有效原始图而生不成图像; 
	RES_FPNOMOVE,		//		17H:表示残留指纹或两次采集之间手指没有移动过; 
	RES_RWFLAERR,		//		18H:表示读写 FLASH 出错; 
	RES_SHDPAK,			//		f0H:有后续数据包的指令,正确接收后用 0xf0 应答; 
	RES_SHCPAK,			//		f1H:有后续数据包的指令,命令包用 0xf1 应答; 
	RES_ENROLLERR,		//		1eH:自动注册(enroll)失败; 
	RES_FPLIBFULL,		//		1fH:指纹库满;
};

2、关键命令发送处理函数

//协议包接收和发送缓冲区
struct fp_package send_pack;
struct fp_recv_package recv_pack;

//高字节和低字节转换
void ConvByteToggleHL(uint8_t * dest,uint8_t * src,uint32_t size)
{
	uint32_t lidx;
	if(size<1 || dest==NULL || src==NULL){
		return ;
	}
	for(lidx=0;lidx<size;lidx++)
	{
		dest[lidx]=src[size-lidx-1];
	}
}

/**
*			Name:				FP_SendPack
*			Function:			发送包
*			Param:				void
*			Return:				int:错误代码
*/

int FP_SendPack(void)
{
	int lIdx;
	uint8_t lsendbuf[10]={0};
	send_pack.header = 0xEF01;
	send_pack.addr = 0xFFFFFFFF;	
	//计算校验和
	send_pack.sum = send_pack.flag + (uint16_t)(send_pack.length & 0xff) + (uint16_t)(send_pack.length >> 8);
	for (lIdx = 0; lIdx < send_pack.length-2 && lIdx < DATA_SIZE_MAX; lIdx++) {
		send_pack.sum += send_pack.data[lIdx];
	}
	rt_enter_critical();
	//发送头标志
	ConvByteToggleHL(lsendbuf,(uint8_t *)&send_pack.header,sizeof(send_pack.header));
	Uart0_SendBytes(lsendbuf,sizeof(send_pack.header));
	//发送地址
	ConvByteToggleHL(lsendbuf,(uint8_t *)&send_pack.addr,sizeof(send_pack.addr));
	Uart0_SendBytes(lsendbuf,sizeof(send_pack.addr));
	//发送标志位
	Uart0_SendBytes(&send_pack.flag,sizeof(send_pack.flag));
	//发送数据长度
	ConvByteToggleHL(lsendbuf,(uint8_t *)&send_pack.length,sizeof(send_pack.length));
	Uart0_SendBytes(lsendbuf,sizeof(send_pack.length));
	//发送数据
	Uart0_SendBytes(send_pack.data,send_pack.length-2);
	//发送校验和
	ConvByteToggleHL(lsendbuf,(uint8_t *)&send_pack.sum,sizeof(send_pack.sum));
	Uart0_SendBytes(lsendbuf,sizeof(send_pack.sum));
	rt_exit_critical();
	return 0;
}


/**
*			Name:				FP_RecvPack
*			Function:			接收包
*			Param:				void
*			Return:				int:错误代码
*/

int FP_RecvPack(struct fp_recv_package * recv)
{
	int ret,lto,lIdx;
	uint16_t temp_sum;
	struct fp_package * recv_pack = (struct fp_package *)recv;
	uint8_t * u8SrcAddr = uart_rcbuf.u8ResponeData;
	memset(recv_pack,0,sizeof(struct fp_recv_package));
	if(!uart_rcbuf.u8finish){
		return FP_TIMEOUT;
	}
	uart_rcbuf.u8finish = 0;
	//接收包头
	ConvByteToggleHL((uint8_t *)&recv_pack->header,u8SrcAddr,sizeof(recv_pack->header));
	u8SrcAddr+=sizeof(recv_pack->header);
	if (recv_pack->header != 0xEF01) {
		goto FP_RC_ERROR;
	}
	//接收地址
	ConvByteToggleHL((uint8_t *)&recv_pack->addr,u8SrcAddr,sizeof(recv_pack->addr));
	u8SrcAddr+=sizeof(recv_pack->addr);
	if (recv_pack->addr != 0xFFFFFFFF) {
		goto FP_RC_ERROR;
	}
	//接收包类型标志
	ConvByteToggleHL((uint8_t *)&recv_pack->flag,u8SrcAddr,sizeof(recv_pack->flag));
	u8SrcAddr+=sizeof(recv_pack->flag);
	switch (recv_pack->flag)
	{
	case CMD_FLAG:
	case DATA_FLAG:
	case ACT_FLAG:
	case DATA_END_FLAG:
		break;
	default:
		goto FP_RC_ERROR;
	}
	//接收数据长度
	ConvByteToggleHL((uint8_t *)&recv_pack->length,u8SrcAddr,sizeof(recv_pack->length));
	u8SrcAddr+=sizeof(recv_pack->length);
	if (recv_pack->length > 256) {
		goto FP_RC_ERROR;
	}
	//接收数据
	memcpy(recv_pack->data,u8SrcAddr,recv_pack->length-2);
	//计算校验和
	temp_sum = recv_pack->flag + (recv_pack->length & 0xff) + (recv_pack->length >> 8);
	for (lIdx = 0; lIdx < (recv_pack->length-2); lIdx++) {
		temp_sum += u8SrcAddr[lIdx];
	}
	u8SrcAddr+=recv_pack->length-2;
	//接收校验和
	ConvByteToggleHL((uint8_t *)&recv_pack->sum,u8SrcAddr,sizeof(recv_pack->sum));
	if (recv_pack->sum != temp_sum) {
		goto FP_RC_ERROR;
	}
	return FP_OK;
	FP_RC_ERROR:
	return FP_ERROR;
}

/**
*			Name:							FP_SendCmdPack
*			Function:			发送常用命令包
*			Param:						cmd:命令名
*			Return:					int:错误代码
*/

int FP_SendCmdPack(COMMON_CMD cmd,uint32_t timeout) 
{
	rt_err_t rt_err;
	int ret,lto;
	if(timeout==0){
		timeout = FP_DEFAULT_TIMEOUT;
	}
	memset(&send_pack, 0, sizeof(send_pack));
	send_pack.flag = CMD_FLAG;
	switch (cmd)
	{
	case CMD_VERIFY_PASSWORD:
		USE_VERIFY_PASSWORD(send_pack);
		break;
	case CMD_VERIFY_DEFPASSWORD:
		USE_VERIFY_DEFPASSWORD(send_pack);
		break;
	case CMD_SET_PASSWORD:
		USE_SET_PASSWORD(send_pack);
		break;
	case CMD_SET_DEFPASSWORD:
		USE_SET_DEFPASSWORD(send_pack);
		break;
	case CMD_GET_IMAGE:
		USE_GET_IMAGE(send_pack);
		break;
	case CMD_GEN_TEMPLET1:
		USE_GEN_TEMPLET1(send_pack);
		break;
	case CMD_GEN_TEMPLET2:
		USE_GEN_TEMPLET2(send_pack);
		break;
	case CMD_GEN_TEMPLET3:
		USE_GEN_TEMPLET3(send_pack);
		break;
	case CMD_SEARCH_FINGER:
		USE_SEARCH_FINGER(send_pack);
		break;
	case CMD_MERGE_TEMPLET:
		USE_MERGE_TEMPLET(send_pack);
		break;
	case CMD_STORE_TEMPLET:
		USE_STORE_TEMPLET(send_pack);
		break;
	case CMD_GETENROLLIMAGE:
		USE_GETENROLLIMAGE(send_pack);
		break;
	case CMD_CMP_TEMPLET:
		USE_CMP_TEMPLET(send_pack);
		break;
	case CMD_GET_NUMBERS:
		USE_GET_NUMBERS(send_pack);
		break;
	case CMD_READINDEXTABLE:
		USE_READINDEXTABLE(send_pack);
		break;
	case CMD_CONTROLLED:
		USE_CONTROLLED(send_pack);
		break;
	case CMD_DEFINELED:
		USE_DEFINELED(send_pack);
		break;
	case CMD_READSYSPARA:
		USE_READSYSPARA(send_pack);
		break;
	case CMD_SETBAUDRATE:
		USE_SETBAUDRATE(send_pack);
		break;
	case CMD_SETDEFADDR:
		USE_SETDEFADDR(send_pack);
		break;
	case CMD_HANDSHAKE:
		USE_HANDSHAKE(send_pack);
		break;
	case CMD_READ_NOTE:
		USE_READ_NOTE(send_pack);
		break;
	case CMD_CLEAR_NOTE:
		USE_CLEAR_NOTE(send_pack);
		break;
	case CMD_DELETCHAR:
		USE_DELETCHAR(send_pack);
		break;
	case CMD_EMPTY:
		USE_EMPTY(send_pack);
		break;
	case CMD_SLEEP:
		USE_SLEEP(send_pack);
		break;
	case CMD_AUTOENROLL:
		USE_AUTOENROLL(send_pack);
		break;
	case CMD_AUTOIDENTIFY:
		USE_AUTOIDENTIFY(send_pack);
		break;
	default:
		return FP_ERROR;
	}
	memset(&uart_rcbuf,0,sizeof(struct uart_rcbuf_s));
	ret = FP_SendPack();
	rt_sem_detach(&usart_rcfi_sem);
	rt_sem_init(&usart_rcfi_sem,"rcfisem",0,RT_IPC_FLAG_FIFO);
	rt_err = rt_sem_take(&usart_rcfi_sem,rt_tick_from_millisecond(timeout));
	ret = FP_RecvPack(&recv_pack);
	return ret;
}

注意:请忽略我rt-thread的函数调用,主要就是为了等待指纹头串口的响应罢了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

晟元协议指纹头,单片机开发踩坑指南 的相关文章

  • ngrok搭建服务器(超级详细)

    前言 我一直都在usr local文件下操作 有不懂的同学给我留言 我没有修改源码 只是测试能否生成服务端文件 有需要的同学可以修改源码 使用 ip 做域名时 随机生成的子域名导致地址错误解决办法就是改源码 去掉随机生成 在ngrok目录下
  • WAIC2023:图像内容安全黑科技助力可信AI发展

    目录 0 写在前面 1 AI图像篡改检测 2 生成式图像鉴别 2 1 主干特征提取通道 2 2 注意力模块 2 3 纹理增强模块 3 OCR对抗攻击 4 助力可信AI向善发展 总结 0 写在前面 2023世界人工智能大会 WAIC 已圆满结
  • python insert插入新一列

    mydata insert 1 date data 日期 mydata 原有数据 1 插入第几列 data 插入列名 data 日期 插入列内容 原有数据插入一列 mydata insert 1 date data 日期 mydata 原有
  • 快速构建Kubesphere 3.0并设置Kubesphere 多集群联邦

    这里我们Host选择使用单节点All in One安装模式 可以零配置快速部署 KubeSphere和Kubernetes 我们安装联邦集群需要有一台节点进行管理 Member需要在Kubernetes中安装Kubesphere当作Memb
  • 目标检测pytorch版yolov3五——解码过程和可视化以及predict预测过程

    本篇博客是我学习某位up在b站讲的pytorch版的yolov3后写的 那位up主的b站的传送门 https www bilibili com video BV1A7411976Z 他的博客的传送门 https blog csdn net

随机推荐

  • c/c++linux后台服务器开发如何提升?(路线图已备好)

    随着业务市场的不断壮大 更便捷的开发语言也越来越受到市场的欢迎 Java python还有新贵golang 那c c 语言的开发者市场在哪里 虽然说没有活干说的可能过于夸张 但是面临的事实就是比不了 可能初学一点Java python等等就
  • 将NFA变成最小化DFA的方法

    学习的时候总感觉这个遇到新的题目不会做 这里总结一下 整个流程是这样的 我们直接来看一个例子 使用上面的算法来实现我们最后的目标 a b ba ab 我们先来画NFA 明确 开始状态和接受状态 终结状态要画两个圈 值得注意的是 由于 也可以
  • netron可视化

    1 netron简介 在很多项目中 经常会遇到各种网络模型 在学习的过程中 我们需要快速去了解这些结构 若只是单纯的看模型文件 很难了解其结构 netron可视化工具 可以清晰的看看见每一层的输入输出 网络总体的架构 而且还能支持各种网络框
  • API接口安全加密,防止接口被黑客攻击

    API接口安全加密的主要目的是为了防止黑客攻击 保护敏感数据不被泄露 以下是一些常用的API接口安全加密方式 HTTPS协议 使用HTTPS协议可以对数据进行传输加密 防止数据在传输过程中被窃听或篡改 API密钥认证 API密钥认证是指在每
  • 关键字constexpr(C++)

    关键字constexpr是在C 11中引入的 并且在C 14中得到了改进 像const一样 它可以应用于变量 当任何代码试图去修改该值时 都会引发编译器错误 与const不同 constexpr也可以应用于函数和类构造函数 constexp
  • 第13届CCF-CSP题解

    文章目录 Less 1 出现最多的数 Less 2 ISBN号码 Less 3 最大矩形 Less 4 有趣的数 Less 5 dfs Less 1 出现最多的数 直接根据题意模拟 include
  • 【yolov6系列一】深度解析网络架构

    在yolov5霸屏计算机视觉领域很久时 六月处美团开源了yolov6 并号称在精度和速度上均超越其他同量级的计算机视觉模型 刚刚瞅了一眼 star已经超过2 8k 脑子里莫名冒出一个词 国货之光 网上基于yolov6的解读有很多 文末会附上
  • Kmeans简单实现

    一 KMeans算法实现代码 class KMeans def init self data k clustres self data data self k clustres k clustres def train self max i
  • 基于 python 的数据库简单开发实验

    基于 python 的简单数据库应用程序开发总结 前言 在大三上数据库课时需要做基于数据库的 C S 和 B S 的简单应用 对之前一直接触命令行黑框框的笔者来说 需要临时学习不少新的技术 实际最后的开发非常简单 只是在前期选定技术和查找文
  • (1)密码学之RSA算法

    开始前先讲一下对称加密算法和公钥加密算法 我不喜欢叫非对称加密算法 这使我想起那个被问MD5算法属于对称还是非对称的恐惧 对称加密算法 1 甲方选择某一种加密规则 对信息进行加密 2 乙方使用同一种规则 对信息进行解密 公钥加密算法 1 乙
  • oracle 整理表 碎片,Oracle数据库表空间碎片的查询和整理方法

    一 查看表空间碎片的方法 1 查看fsfi值 select a tablespace name trunc sqrt max blocks sum blocks 100 sqrt sqrt count blocks 2 fsfi from
  • php+redis实现消息队列

    个人理解在项目中使用消息队列一般是有如下几个原因 把瞬间服务器的请求处理换成异步处理 缓解服务器的压力 实现数据顺序排列获取 redis实现消息队列步骤如下 1 redis函数rpush lpop 2 建议定时任务入队列 3 创建定时任务出
  • 目标检测mAP计算详解

    首先说明计算mAP有多个版本 每个数据集和比赛用的版本和方式也不同 下以VOC与COCO举例说明 精确度 precision 召回率 recall 分别为 常规的mAP计算为 这是一个N类检测任务 1 计算单张图片中class1的精度P V
  • Mac启动磁盘已满怎么办?Mac启动磁盘已满怎么清理?

    如果你的Mac电脑经常弹出窗口 您的启动盘几乎已经满了 这说明你的Mac硬盘空间严重不足了 清理各种不必要的垃圾可以释放一些空间 那么Mac启动磁盘已满怎么清理 下面为大家带来几点非常实用的Mac启动磁盘清理技巧 学会这些对你使用Mac电脑
  • 若依(ruoyi)代码生成树表结构的那些坑

    相信许多做后端开发的同学 一定用过若依这款框架 这款框架易上手 适合用来做后台管理系统 但是其中也存在一些坑 稍不注意就会中招 大佬可以忽略 今天 我们说的是若依的代码生成 树结构表 话不多说 直接看图说话 1 项目正常运行 成功登录之后
  • JS 对象和函数

    目录 一 对象 创建对象的四种方式 构造函数原型对象prototype和对象原型 proto 二 函数 创建函数的3种方式 一 对象 创建对象的四种方式 第一种方式 字面量 var o1 name o1 var o2 new Object
  • STM32F103C8用内部Flash做一个优盘(USB+MSC+FATFS)

    STM32F103C8用内部Flash做一个优盘 USB MSC FATFS 轻松实现APP升级 数据存储 基本工程生成 直接使用STM32CubeMX生成基本的工程 省得我们去调底层 时钟配置为外部8MHz晶振 这个需要根据自己开发板的晶
  • Python爬虫教程:爬取800多所大学学校排名、星级等

    前言 国内大学最新排名 北大反超 浙大仅第四 中科大跌至第八 时隔五年 双一流 大学即将迎来首次大考 这也是继改变高校评断标准之后 第一次即将以官方对外发布 自然是引来了许多人的关注 最近 有许多不同机构发布的国内高校排名 但彼此之间的差异
  • 自我理解:TCP和UDP、HTTP、进程和线程

    一 TCP和UDP 1 什么是TCP和UDP TCP是面向连接的协议 发送数据前要建立连接 TCP提供的是可靠传输 UDP是无连接的协议 发送数据前不需要建立连接 是不可靠传输 2 TCP和UDP的区别 TCP是面向连接的协议 发送数据前要
  • 晟元协议指纹头,单片机开发踩坑指南

    一 硬件说明 1 接口 注意 其中Touch VCC 3 3V是需要常供电的 用于Touch Out触摸唤醒供电 VDD3 3V可以检测到Touch Out高电平信号再上电 如果不需要低功耗设计 可以忽略Touch Out和Touch VC