当前位置: 首页 > news >正文

ESP32学习笔记(52)————三轴加速度ADXL345使用(SPI方式)

一、简介

ADXL345 是一款 ADI 公司推出的基于 iMEMS 技术的超低功耗3轴加速度计,分辨率高(13位),测量范围达 ±16g。数字输出数据为 16 位二进制补码格式,可通过 SPI(3线或4线)I2C 数字接口访问。ADXL345 非常适合移动设备应用。它可以在倾斜检测应用中测量静态重力加速度,还可以测量运动或冲击导致的动态加速度。其高分辨率(3.9mg/LSB),能够测量不到 1.0° 的倾斜角度变化。

该器件提供多种特殊检测功能。活动和非活动检测功能通过比较任意轴上的加速度与用户设置的阈值来检测有无运动发生。敲击检测功能可以检测任意方向的单振和双振动作。自由落体检测功能可以检测器件是否正在掉落。这些功能可以独立映射到两个中断输出引脚中的一个。正在申请专利的集成式存储器管理系统采用一个32级先进先出(FIFO)缓冲器,可用于存储数据,从而将主机处理器负荷降至最低,并降低整体系统功耗。低功耗模式支持基于运动的智能电源管理,从而以极低的
功耗进行阈值感测和运动加速度测量。

官方数据手册:https://pan.baidu.com/s/1-UCkno6kQFugSy8NEhNhHg?pwd=tp7p 提取码:tp7p

二、硬件连接

功能口引脚
MISO17
MOSI18
SCLK20
CS19

三、添加SPI驱动

查看 ESP32学习笔记(19)——SPI(主机)接口使用

四、SPI通信注意事项

4.1 SPI模式

一般内置 SPI 功能的单片机上,都有两个寄存器配置位 CPOL 和 CPHA。
CPOL 就是决定 SCLK 这个时钟信号线,在没有数据传输的时候的电平状态。
CPHA 就是决定数据位传输是从第一个时钟 (SCLK) 边沿开始,还是第二个从二个时钟 (SCLK) 边沿开始。
因此 CPOL 和 CPHA 合体就形成了SPI四种模式。

  • 模式0(CPOL=0,CPHA=0)
    CPOL = 0:空闲时是低电平,第1个跳变沿是上升沿,第2个跳变沿是下降沿
    CPHA = 0:数据在第1个跳变沿(上升沿)采样

  • 模式1(CPOL=0,CPHA=1)
    CPOL = 0:空闲时是低电平,第1个跳变沿是上升沿,第2个跳变沿是下降沿
    CPHA = 1:数据在第2个跳变沿(下降沿)采样

  • 模式2(CPOL=1,CPHA=0)
    CPOL = 1:空闲时是高电平,第1个跳变沿是下降沿,第2个跳变沿是上升沿
    CPHA = 0:数据在第1个跳变沿(下降沿)采样

  • 模式3(CPOL=1,CPHA=1)
    CPOL = 1:空闲时是高电平,第1个跳变沿是下降沿,第2个跳变沿是上升沿
    CPHA = 1:数据在第2个跳变沿(上升沿)采样

查看ADXL345中文数据手册第15页,得知ADXL345 SPI模式应为 模式3(CPOL=1,CPHA=1)

4.2 SPI读写以及多字节读取指令的区别

查看ADXL345中文数据手册第14、15页,得知读的时候,地址的最高位为1;写的时候,地址的最高位为0;在进行多字节读取的时候,次高位为1,这样才可以多字节写和读

4.3 SPI时钟要求

查看ADXL345中文数据手册第14页,得知在设置读取速率的时候,要和SPI的时钟匹配起来,否则可能读到错误的数据,比如设置1600HZ,SPI时钟要大于2MHZ。SPI读取数据时钟最大5MHZ

4.4 器件ID寄存器

查看ADXL345中文数据手册第23页,得知寄存器0x00保存0xE5的固定器件ID代码,可用于校验SPI是否通信成功

五、移植文件

5.1 board_spi.c

#include <math.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"#include "board_spi.h"
#include "board_adxl345.h"static void delayMs(uint32_t time);void ADXL345_Init(void)
{ADXL345_SPI_Init();while(ADXL345_GetDeviceId() != 0xE5){printf("ADXL345 Init Fail!\n");delayMs(1000);}ADXL345_WriteReg(DATA_FORMAT, 0x0B);    // 13位全分辨率,输出数据右对齐,16g量程ADXL345_WriteReg(BW_RATE, 0x0A);        // 数据输出速度为100HzADXL345_WriteReg(POWER_CTL, 0x08);      // 无链接,测量模式ADXL345_WriteReg(INT_ENABLE, 0x80);     // DATA_READY中断printf("ADXL345 Init Success!\n");
}uint8_t ADXL345_GetDeviceId(void)
{uint8_t ret = ADXL345_ReadReg(DEVICE_ID);return ret;
}void ADXL345_ReadXYZ(short *x, short *y, short *z)
{uint8_t x0,y0,z0;uint8_t x1,y1,z1;x0 = ADXL345_ReadReg(DATA_X0);y0 = ADXL345_ReadReg(DATA_Y0);z0 = ADXL345_ReadReg(DATA_Z0);x1 = ADXL345_ReadReg(DATA_X1);y1 = ADXL345_ReadReg(DATA_Y1);z1 = ADXL345_ReadReg(DATA_Z1);// printf("--------------x0:%d,y0:%d,z0:%d\tx1:%d,y1:%d,z1:%d", x0,y0,z0,x1,y1,z1);*x = (short)(((uint16_t)x1 << 8) + x0); // DATA_X1为高位有效字节*y = (short)(((uint16_t)y1 << 8) + y0); // DATA_Y1为高位有效字节*z = (short)(((uint16_t)z1 << 8) + z0); // DATA_Z1为高位有效字节// printf("--------------x%d,y%d,z%d",*x,*y,*z);
}/*读取ADXL345的数据并做滤波处理,读times次再取平均值*/
void ADXL345_ReadAverage(short *x, short *y, short *z, uint8_t times)
{if(0 == times){return;}uint8_t i;short x_temp,y_temp,z_temp;*x = 0;*y = 0;*z = 0;for(i = 0; i < times; i++){ADXL345_ReadXYZ(&x_temp, &y_temp, &z_temp);*x += x_temp;*y += y_temp;*z += z_temp;delayMs(5);}*x /= times;*y /= times;*z /= times;
}/*使用偏移寄存器,进行偏移校准*/
void ADXL345_AutoAdjust(void)
{uint8_t i;short x_temp,y_temp,z_temp;short x_offset = 0;short y_offset = 0;short z_offset = 0;char x_calib = 0;char y_calib = 0;char z_calib = 0;ADXL345_WriteReg(DATA_FORMAT, 0x0B);    // 13位全分辨率,输出数据右对齐,16g量程ADXL345_WriteReg(BW_RATE, 0x0A);        // 数据输出速度为100HzADXL345_WriteReg(POWER_CTL, 0x08);      // 无链接,测量模式ADXL345_WriteReg(INT_ENABLE, 0x80);     // DATA_READY中断delayMs(12);for(i = 0; i < 10; i++){ADXL345_ReadAverage(&x_temp, &y_temp, &z_temp, 10);x_offset += x_temp;y_offset += y_temp;z_offset += z_temp;}x_offset /= 10;y_offset /= 10;z_offset /= 10;x_calib =- x_offset / 4;y_calib =- y_offset / 4;z_calib =- (z_offset - 256) / 4;ADXL345_WriteReg(OFSX, x_calib);ADXL345_WriteReg(OFSY, y_calib);ADXL345_WriteReg(OFSZ, z_calib);
}/*计算ADXL345角度,x/y/表示各方向上的加速度分量,dir表示要获得的角度*/
short ADXL345_GetAngle(float x, float y, float z, uint8_t dir)
{float temp;float res = 0;	                        // 弧度值switch(dir){case 0:                             // 0表示与Z轴的角度temp = sqrt((x*x + y*y)) / z;res = atan(temp);break;case 1:                             // 1表示与X轴的角度temp = x / sqrt((y*y + z*z));res = atan(temp);break;case 2:                             // 2表示与Y轴的角度temp = y / sqrt((x*x + z*z));res = atan(temp);break;}return res * 180 / 3.14;                // 返回角度值// return res*180/3.14*10;      //乘以10是为了取一位小数,角度精确到0.1°所以要乘以10
}/**@brief 写寄存器@param addr -[in] 寄存器地址@param data -[in] 写入数据@return 无
*/
void ADXL345_WriteReg(uint8_t addr, uint8_t data)
{uint8_t send_data[2];uint32_t size = 2;addr &= 0x3F;send_data[0] = addr;send_data[1] = data;SPI_CS_LOW;ADXL345_SPI_Write(send_data, size);SPI_CS_HIGH;
}/**@brief 读寄存器@param addr -[in] 寄存器地址@return 读出一字节数据
*/
uint8_t ADXL345_ReadReg(uint8_t addr)
{uint8_t receive_data;uint32_t size = 1;addr &= 0x3F;addr |= 0x80;SPI_CS_LOW;ADXL345_SPI_Write(&addr, size);ADXL345_SPI_Read(&receive_data, size);SPI_CS_HIGH;return receive_data;
}/**@brief 毫秒级延时函数@param time -[in] 延时时间(毫秒)@return 无
*/
static void delayMs(uint32_t time)
{vTaskDelay(time / portTICK_PERIOD_MS);
}

5.2 board_spi.h

#ifndef _BOARD_SPI_H_
#define _BOARD_SPI_H_/********************************************************************** INCLUDES*/
#include <stdint.h>
#include "driver/gpio.h"/********************************************************************** DEFINITIONS*/
#define ADXL345_SPI_MISO_PIN        GPIO_NUM_19
#define ADXL345_SPI_MOSI_PIN        GPIO_NUM_23
#define ADXL345_SPI_SCLK_PIN        GPIO_NUM_18
#define ADXL345_SPI_CS_PIN          GPIO_NUM_5#define DMA_CHAN                	2#define SPI_CS_LOW              	ADXL345_SPI_CS_Set(0)
#define SPI_CS_HIGH             	ADXL345_SPI_CS_Set(1)/********************************************************************** API FUNCTIONS*/
void ADXL345_SPI_Init(void);
void ADXL345_SPI_Write(uint8_t *pData, uint32_t dataLen);
void ADXL345_SPI_Read(uint8_t *pData, uint32_t dataLen);
void ADXL345_SPI_CS_Set(uint8_t level);#endif /* _BOARD_SPI_H_ */

5.3 board_adxl345.c

#include <math.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"#include "board_spi.h"
#include "board_adxl345.h"static void delayMs(uint32_t time);void ADXL345_Init(void)
{ADXL345_SPI_Init();while(ADXL345_GetDeviceId() != 0xE5){printf("ADXL345 Init Fail!\n");delayMs(1000);}ADXL345_WriteReg(DATA_FORMAT, 0x0B);    // 13位全分辨率,输出数据右对齐,16g量程ADXL345_WriteReg(BW_RATE, 0x0A);        // 数据输出速度为100HzADXL345_WriteReg(POWER_CTL, 0x08);      // 无链接,测量模式ADXL345_WriteReg(INT_ENABLE, 0x80);     // DATA_READY中断printf("ADXL345 Init Success!\n");
}uint8_t ADXL345_GetDeviceId(void)
{uint8_t ret = ADXL345_ReadReg(DEVICE_ID);return ret;
}void ADXL345_ReadXYZ(short *x, short *y, short *z)
{uint8_t x0,y0,z0;uint8_t x1,y1,z1;x0 = ADXL345_ReadReg(DATA_X0);y0 = ADXL345_ReadReg(DATA_Y0);z0 = ADXL345_ReadReg(DATA_Z0);x1 = ADXL345_ReadReg(DATA_X1);y1 = ADXL345_ReadReg(DATA_Y1);z1 = ADXL345_ReadReg(DATA_Z1);// printf("--------------x0:%d,y0:%d,z0:%d\tx1:%d,y1:%d,z1:%d", x0,y0,z0,x1,y1,z1);*x = (short)(((uint16_t)x1 << 8) + x0); // DATA_X1为高位有效字节*y = (short)(((uint16_t)y1 << 8) + y0); // DATA_Y1为高位有效字节*z = (short)(((uint16_t)z1 << 8) + z0); // DATA_Z1为高位有效字节// printf("--------------x%d,y%d,z%d",*x,*y,*z);
}/*读取ADXL345的数据并做滤波处理,读times次再取平均值*/
void ADXL345_ReadAverage(short *x, short *y, short *z, uint8_t times)
{if(0 == times){return;}uint8_t i;short x_temp,y_temp,z_temp;*x = 0;*y = 0;*z = 0;for(i = 0; i < times; i++){ADXL345_ReadXYZ(&x_temp, &y_temp, &z_temp);*x += x_temp;*y += y_temp;*z += z_temp;delayMs(5);}*x /= times;*y /= times;*z /= times;
}/*使用偏移寄存器,进行偏移校准*/
void ADXL345_AutoAdjust(void)
{uint8_t i;short x_temp,y_temp,z_temp;short x_offset = 0;short y_offset = 0;short z_offset = 0;char x_calib = 0;char y_calib = 0;char z_calib = 0;ADXL345_WriteReg(DATA_FORMAT, 0x0B);    // 13位全分辨率,输出数据右对齐,16g量程ADXL345_WriteReg(BW_RATE, 0x0A);        // 数据输出速度为100HzADXL345_WriteReg(POWER_CTL, 0x08);      // 无链接,测量模式ADXL345_WriteReg(INT_ENABLE, 0x80);     // DATA_READY中断delayMs(12);for(i = 0; i < 10; i++){ADXL345_ReadAverage(&x_temp, &y_temp, &z_temp, 10);x_offset += x_temp;y_offset += y_temp;z_offset += z_temp;}x_offset /= 10;y_offset /= 10;z_offset /= 10;x_calib =- x_offset / 4;y_calib =- y_offset / 4;z_calib =- (z_offset - 256) / 4;ADXL345_WriteReg(OFSX, x_calib);ADXL345_WriteReg(OFSY, y_calib);ADXL345_WriteReg(OFSZ, z_calib);
}/*计算ADXL345角度,x/y/表示各方向上的加速度分量,direction表示要获得的角度*/
short ADXL345_GetAngle(float x, float y, float z, uint8_t direction)
{float temp;float res = 0;	                        // 弧度值switch(direction){case 0:                             // 0表示与Z轴的角度temp = sqrt((x*x + y*y)) / z;res = atan(temp);break;case 1:                             // 1表示与X轴的角度temp = x / sqrt((y*y + z*z));res = atan(temp);break;case 2:                             // 2表示与Y轴的角度temp = y / sqrt((x*x + z*z));res = atan(temp);break;}return res * 180 / 3.14;                // 返回角度值// return res*180/3.14*10;      //乘以10是为了取一位小数,角度精确到0.1°所以要乘以10
}/**@brief 写寄存器@param addr -[in] 寄存器地址@param data -[in] 写入数据@return 无
*/
void ADXL345_WriteReg(uint8_t addr, uint8_t data)
{uint8_t send_data[2];uint32_t size = 2;addr &= 0x3F;send_data[0] = addr;send_data[1] = data;SPI_CS_LOW;ADXL345_SPI_Write(send_data, size);SPI_CS_HIGH;
}/**@brief 读寄存器@param addr -[in] 寄存器地址@return 读出一字节数据
*/
uint8_t ADXL345_ReadReg(uint8_t addr)
{uint8_t receive_data;uint32_t size = 1;addr &= 0x3F;addr |= 0x80;SPI_CS_LOW;ADXL345_SPI_Write(&addr, size);ADXL345_SPI_Read(&receive_data, size);SPI_CS_HIGH;return receive_data;
}/**@brief 毫秒级延时函数@param time -[in] 延时时间(毫秒)@return 无
*/
static void delayMs(uint32_t time)
{vTaskDelay(time / portTICK_PERIOD_MS);
}

5.4 board_adxl345.h

#ifndef _BOARD_ADXL345_H_
#define _BOARD_ADXL345_H_#ifdef __cplusplus
extern "C"
{
#endif#include <stdint.h>#define DEVICE_ID		0X00 	// 器件ID,0XE5
#define THRESH_TAP		0X1D   	// 敲击阀值寄存器
#define OFSX			0X1E
#define OFSY			0X1F
#define OFSZ			0X20
#define DUR				0X21
#define Latent			0X22
#define Window  		0X23
#define THRESH_ACT		0X24	// 运动阈值寄存器
#define THRESH_INACT	0X25 	// 静止阈值寄存器
#define TIME_INACT		0X26	// 静止时间			比例1 sec /LSB
#define ACT_INACT_CTL	0X27	// 启用运动/静止检测
#define THRESH_FF		0X28	// 自由下落阈值	建议采用300 mg与600 mg(0x05至0x09)之间的值 比例62.5 mg/LSB
#define TIME_FF			0X29 	// 自由下落时间	建议采用100 ms与350 ms(0x14至0x46)之间的值 比例5ms/LSB
#define TAP_AXES		0X2A
#define ACT_TAP_STATUS  0X2B
#define BW_RATE			0X2C
#define POWER_CTL		0X2D
#define INT_ENABLE		0X2E	// 设置中断配置
#define INT_MAP			0X2F
#define INT_SOURCE  	0X30
#define DATA_FORMAT	    0X31
#define DATA_X0			0X32
#define DATA_X1			0X33
#define DATA_Y0			0X34
#define DATA_Y1			0X35
#define DATA_Z0			0X36
#define DATA_Z1			0X37
#define FIFO_CTL		0X38
#define FIFO_STATUS		0X39#define Z_AXIS          0
#define X_AXIS          1
#define Y_AXIS          2void ADXL345_Init(void);
uint8_t ADXL345_GetDeviceId(void);
void ADXL345_ReadXYZ(short *x, short *y, short *z);
void ADXL345_ReadAverage(short *x, short *y, short *z, uint8_t times);
short ADXL345_GetAngle(float x, float y, float z, uint8_t direction);
void ADXL345_WriteReg(uint8_t addr, uint8_t data);
uint8_t ADXL345_ReadReg(uint8_t addr);#ifdef __cplusplus
}
#endif#endif /* _BOARD_ADXL345_H_ */

六、初始化流程

开机先等待 1.1ms——>设置数据格式——>设置功耗模式——>使能相应中断——>结束。

七、角度值转换公式

八、API调用

需包含头文件 board_adxl345.h

ADXL345_Init

功能ADXL345的初始化函数
函数定义void ADXL345_Init(void)
参数
返回

ADXL345_GetDeviceId

功能检查SPI通信,返回值为0xE5则通信正常
函数定义uint8_t ADXL345_GetDeviceId(void)
参数
返回固定器件ID值,0xE5

ADXL345_ReadXYZ

功能读取X、Y、Z轴加速度值
函数定义void ADXL345_ReadXYZ(short *x, short *y, short *z)
参数要读取的方向X,Y,Z轴返回值
返回

ADXL345_GetAngle

功能读取角度
函数定义short ADXL345_GetAngle(float x, float y, float z, uint8_t direction)
参数x,y,z:X、Y、Z轴加速度值
direction:要读取的方向X,Y,Z轴
返回角度数

九、使用例子

1)添加头文件

#include "board_adxl345.h"

2)添加初始化代码(main.c的main函数中)
首先调用 ADXL345_SPI_Init() 初始化 SPI 通信,最后调用 ADXL345_Init() 初始化加速度传感器模块功能。

#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>void app_main(void)
{ADXL345_Init();/*-------------------------- 创建线程 ---------------------------*/xTaskCreate(monitor_task, "monitor_task", 2048, NULL, 4, NULL);
}

3)添加任务,定时读取数据

static void monitor_task(void *arg)
{while(1)                                                                // 任务都是一个无限循环,不能返回{short x_value,y_value,z_value;short x_angle,y_angle,z_angle;ADXL345_ReadAverage(&x_value, &y_value, &z_value, 10);x_angle = ADXL345_GetAngle(x_value, y_value, z_value, X_AXIS);y_angle = ADXL345_GetAngle(x_value, y_value, z_value, Y_AXIS);z_angle = ADXL345_GetAngle(x_value, y_value, z_value, Z_AXIS);printf("x_ang:%d y_ang:%d z_ang:%d\n", x_angle, y_angle, z_angle);vTaskDelay(1000 / portTICK_PERIOD_MS);                                                        // 1s}
}

4)查看打印

十、测量方向


• 由 Leung 写于 2023 年 8 月 7 日

• 参考:STC8H开发(六): SPI驱动ADXL345三轴加速度检测模块
    STM32 HAL库学习笔记-(SPI驱动ADXL345)
    STM32CubeMX系列|ADXL345传感器
    ADXL345 三轴加速度数据SPI读取、多字节读取、DMA SPI读取和FIFO数据读取

相关文章:

ESP32学习笔记(52)————三轴加速度ADXL345使用(SPI方式)

一、简介 ADXL345 是一款 ADI 公司推出的基于 iMEMS 技术的超低功耗3轴加速度计&#xff0c;分辨率高(13位)&#xff0c;测量范围达 16g。数字输出数据为 16 位二进制补码格式&#xff0c;可通过 SPI(3线或4线) 或 I2C 数字接口访问。ADXL345 非常适合移动设备应用。它可以在倾…...

Camunda 7.x 系列【4】 Camunda Modeler 功能介绍

有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot 版本 2.7.9 本系列Camunda 版本 7.19.0 源码地址:https://gitee.com/pearl-organization/camunda-study-demo 文章目录 1. 下载安装2. 功能介绍2.1 欢迎界面2.2 工具栏2.3 小地图2.4 流程配置2.5 小工具栏2.6 启动…...

呼叫中心系统管理和优化的关键指标

呼叫中心系统是企业客户服务的重要组成部分&#xff0c;通过电话、邮件、社交媒体等渠道与客户进行沟通和交互。如何管理和优化呼叫中心系统&#xff0c;提高客户满意度和工作效率&#xff0c;是每个企业都需要关注和解决的问题。以下是呼叫中心系统管理和优化的关键指标。 1. …...

UML箭头汇总

参考&#xff1a;http://www.cnblogs.com/damsoft/archive/2016/10/24/5993602.html 1.UML简介 Unified Modeling Language (UML)又称统一建模语言或标准建模语言。 简单说就是以图形方式表现模型&#xff0c;根据不同模型进行分类&#xff0c;在UML 2.0中有13种图&#xff…...

【STM32零基础入门教程03】GPIO输入输出之GPIO框图分析

本章节主要讲解点亮LED的基本原理&#xff0c;以及GPIO框图的讲解。 如何点亮LED&#xff08;输出&#xff09; 首先我们查看原理图&#xff0c;观察电路图中LED的连接情况&#xff0c;如下图可以看出我们的板子中LED一端通过限流电阻连接的PB0另一端连接的是高电平VCC&#xf…...

高效管理,PDM系统与BOM系统携手合作

在现代制造业中&#xff0c;PDM系统&#xff08;Product Data Management&#xff0c;产品数据管理&#xff09;和BOM系统&#xff08;Bill of Materials&#xff0c;物料清单管理&#xff09;都扮演着关键的角色。PDM系统负责产品数据的统一管理&#xff0c;而BOM系统则专注于…...

Elasticsearch 使用scroll滚动技术实现大数据量搜索、深度分页问题 和 search

基于scroll滚动技术实现大数据量搜索 如果一次性要查出来比如10万条数据&#xff0c;那么性能会很差&#xff0c;此时一般会采取用scroll滚动查询&#xff0c;一批一批的查&#xff0c;直到所有数据都查询完为止。 scroll搜索会在第一次搜索的时候&#xff0c;保存一个当时的视…...

了解Swarm 集群管理

Swarm 集群管理 简介 Docker Swarm 是 Docker 的集群管理工具。它将 Docker 主机池转变为单个虚拟 Docker 主机。 Docker Swarm 提供了标准的 Docker API&#xff0c;所有任何已经与 Docker 守护程序通信的工具都可以使用 Swarm 轻松地扩展到多个主机。 支持的工具包括但不限…...

【Docker】Docker私有仓库的使用

目录 一、搭建私有仓库 二、上传镜像到私有仓库 三、从私有仓库拉取镜像 一、搭建私有仓库 首先我们需要拉取仓库的镜像 docker pull registry 然后创建私有仓库容器 docker run -it --namereg -p 5000:5000 registry 这个时候我们可以打开浏览器访问5000端口看是否成功&…...

基于arcFace+faiss开发构建人脸识别系统

在上一篇博文《基于facenetfaiss开发构建人脸识别系统》中&#xff0c;我们实践了基于facenet和faiss的人脸识别系统开发&#xff0c;基于facenet后续提出来很多新的改进的网络模型&#xff0c;arcFace就是其中一款优秀的网络模型&#xff0c;本文的整体开发实现流程与前文相同…...

C#设计模式(15)命令模式(Command Pattern)

命令模式&#xff08;Command Pattern&#xff09; 命令模式是一种数据驱动的设计模式&#xff0c;属于行为型模式类别。请求被包装在一个对象中作为命令&#xff0c;并传递给调用对象。调用对象寻找可以处理该命令的合适对象&#xff0c;并将命令传递给相应的对象&#xff0c…...

快速排序和qsort函数详解详解qsort函数

&#x1f495;是非成败转头空&#xff0c;青山依旧在&#xff0c;几度夕阳红&#x1f495; 作者&#xff1a;Mylvzi 文章主要内容&#xff1a;快速排序和qsort函数详解 前言&#xff1a; 我们之前学习过冒泡排序&#xff0c;冒泡排序尽管很方便&#xff0c;但也存在一些局限性…...

搭建 elasticsearch8.8.2 伪集群 windows

下载windows 版本 elasticsearch8.8.2 以下链接为es 历史版本下载地址&#xff1a; Past Releases of Elastic Stack Software | Elastic windows 单节点建立方案&#xff1a; 下载安装包 elasticsearch-8.8.2-windows-x86_64.zip https://artifacts.elastic.co/download…...

C++ 运算符重载为成员函数

运算符重载实质上就是函数重载&#xff0c;重载为成员函数&#xff0c;他就可以自由访问本类的数据成员。实际使用时&#xff0c;总是通过该类的某个对象来访问重载的运算符。 如果是双目运算符&#xff0c;左操作数是对象本身的数据&#xff0c;由this指针指出&#xff0c;右…...

51单片机程序烧录教程

STC烧录步骤 &#xff08;1&#xff09;STC单片机烧录方式采用串口进行烧录程序&#xff0c;连接的方式如下图&#xff1a; &#xff08;2&#xff09;所以需要先确保USB转串口驱动是识别到&#xff0c;且驱动运行正常&#xff1b;是否可通过电脑的设备管理器查看驱动是否正常…...

Linux C++ 链接数据库并对数据库进行一些简单的操作

一.引言&#xff08;写在之前&#xff09; 在我们进行网络业务代码书写的时候&#xff0c;我们总是避免对产生的数据进行增删改查&#xff0c;为此&#xff0c;本小博主在这里简历分享一下自己在Linux中C语言与数据之间交互的代码的入门介绍。 二.代码书写以及一些变量和函数的…...

Linux进程间通信--msgsnd函数的作用

msgsnd函数用于将消息发送到消息队列中。它的原型如下&#xff1a; int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); 参数解释&#xff1a; msqid&#xff1a;消息队列标识符&#xff0c;由msgget函数返回。msgp&#xff1a;指向要发送的消息的指针&…...

P1629 邮递员送信(最短路)(内附封面)

邮递员送信 题目描述 有一个邮递员要送东西&#xff0c;邮局在节点 1 1 1。他总共要送 n − 1 n-1 n−1 样东西&#xff0c;其目的地分别是节点 2 2 2 到节点 n n n。由于这个城市的交通比较繁忙&#xff0c;因此所有的道路都是单行的&#xff0c;共有 m m m 条道路。这…...

网络安全--原型链污染

目录 1.什么是原型链污染 2.原型链三属性 1&#xff09;prototype 2)constructor 3)__proto__ 4&#xff09;原型链三属性之间关系 3.JavaScript原型链继承 1&#xff09;分析 2&#xff09;总结 3)运行结果 4.原型链污染简单实验 1&#xff09;实验一 2&#xff0…...

Harbor企业镜像仓库部署

目录 一、Harbor 架构构成 二、部署harbor环境 1、安装docker-ce&#xff08;所有主机&#xff09; 2、阿里云镜像加速器 3、部署Docker Compose 服务 4、部署 Harbor 服务 5、启动并安装 Harbor 6、创建一个新项目 三、客户端上传镜像 1、在 Docker 客户端配置操作如下…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 操作步…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

条件运算符

C中的三目运算符&#xff08;也称条件运算符&#xff0c;英文&#xff1a;ternary operator&#xff09;是一种简洁的条件选择语句&#xff0c;语法如下&#xff1a; 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true&#xff0c;则整个表达式的结果为“表达式1”…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

什么是Ansible Jinja2

理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具&#xff0c;可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板&#xff0c;允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板&#xff0c;并通…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

基于Java+MySQL实现(GUI)客户管理系统

客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息&#xff0c;对客户进行统一管理&#xff0c;可以把所有客户信息录入系统&#xff0c;进行维护和统计功能。可通过文件的方式保存相关录入数据&#xff0c;对…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的

修改bug思路&#xff1a; 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑&#xff1a;async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...