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

news2024/12/26 0:15:15

一、简介

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);        // 数据输出速度为100Hz
    ADXL345_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);        // 数据输出速度为100Hz
    ADXL345_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);        // 数据输出速度为100Hz
    ADXL345_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);        // 数据输出速度为100Hz
    ADXL345_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          2

void 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数据读取

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/842730.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

小研究 - MySQL 分区技术在海量系统日志中的应用

随着信息技术的飞速发展&#xff0c;系统的业务功能不断扩大&#xff0c;产生的日志与日俱增&#xff0c;导致应用软件的运行速度越来越慢&#xff0c;不能很好地满足用户对软件性能的需求。基于此&#xff0c;重点研究了 MySQL 分区技术在大数据量软件日志中的应用&#xff0c…

NamedParameterJdbcTemplate类的作用和使用

NamedParameterJdbcTemplate是Spring框架提供的一个类&#xff0c;用于简化在JDBC操作中使用命名参数的过程。它是对JdbcTemplate的扩展&#xff0c;通过使用命名参数而不是传统的问号占位符&#xff0c;使SQL语句更易读和维护。 NamedParameterJdbcTemplate的作用是&#xff…

cn.hutool.core.date.DateUtil.beginOfDay 方法的作用和使用

cn.hutool.core.date.DateUtil.beginOfDay 方法的作用是返回指定日期的开始时间&#xff0c;即将时、分、秒和毫秒部分设置为 0。 使用 beginOfDay 方法时&#xff0c;可以按照以下步骤进行操作&#xff1a; 导入 cn.hutool.core.date.DateUtil 类。创建一个 java.util.Date …

PPS Tester测量原理和实施方法

怿星科技发布了新品PPS Tester&#xff0c;这是一款基于1PPS方法的时间同步精度测试设备。PPS Tester由硬件模块ETS2110和上位机软件ePPSTester构成。本文将围绕此设备的应用场景&#xff0c;介绍相关概念和设备使用方法。 什么是时间同步&#xff1f; 时间同步就是采取某项技…

涂鸦智能获Matter Non-VID Scoped PAA资质 助力开发者拥抱Matter生态

今年5月&#xff0c;全球化IoT开发者平台涂鸦智能&#xff08;NYSE: TUYA&#xff0c;HKEX: 2391&#xff09;正式生成Tuya Matter PAA密钥根&#xff0c;并于7月&#xff0c;成功通过了连接标准联盟和第三方MA机构审查而上线。自此&#xff0c;涂鸦正式成为全球同时提供支持Ma…

考研算法38天:反序输出 【字符串的翻转】

题目 题目收获 很简单的一道题&#xff0c;但是还是有收获的&#xff0c;我发现我连scanf的字符串输入都忘记咋用了。。。。。我一开始写的 #include <iostream> #include <cstring> using namespace std;void deserve(string &str){int n str.size();int…

STM32 HAL 驱动PM2.5传感器(GP2Y10AU气体检测模块)

目录 1、简介 2、CubeMX初始化配置 2.1 基础配置 2.1.1 SYS配置 2.1.2 RCC配置 2.2 ADC外设配置 2.3 串口外设配置 2.4 项目生成 3、KEIL端程序整合 3.1 串口重映射 3.2 ADC数据采集 3.3 主函数代 3.4 效果展示 1、简介 本文通过STM32F103C8T6单片机通过HAL库方式对G…

Java实现Google cloud storage 文件上传,Google oss

storage 控制台位置 创建一个bucket 点进bucket里面&#xff0c;权限配置里&#xff0c;公开访问&#xff0c;在互联网上公开&#xff0c;需要配置角色权限 新增一个访问权限 &#xff0c;账号这里可以模糊搜索&#xff0c; 角色配置 给allUser配置俩角色就可以出现 在互联…

文水爱心帮扶开展——情系困境 高温天里“送关爱”

为了困境儿童有个健康、快乐、平等、和谐的成长环境&#xff0c;在社会组织党委的领导下&#xff0c;文水县妇联、县爱心帮扶志愿者协会及中志协应急委文水服务队联合开展新时代文明实践活动--为困境儿童送关爱。 8月6日上午九点&#xff0c;在文水火车站广场&#xff0c;文水县…

解决Vue+Element UI使用el-dropdown(下拉菜单)国际化时菜单label信息没有刷新的情况

说明&#xff1a;该篇博客是博主一字一码编写的&#xff0c;实属不易&#xff0c;请尊重原创&#xff0c;谢谢大家&#xff01; 问题描述 在默认中文时&#xff0c;点击布局大小下拉菜单正常显示中文&#xff0c;此时切换至英文时&#xff0c;再次点击下拉菜单&#xff0c;还…

Linux安装mysql报错

用rpm安装mysql时报错如下&#xff1a; 解决&#xff1a; yum install -y libc.so.6 yum install -y libaio.so.1再次安装即可&#xff1a;

java,python,c++有什么区别,python java c c++区别

大家好&#xff0c;给大家分享一下java,python,c有什么区别&#xff0c;很多人还不知道这一点。下面详细解释一下。现在让我们来看看&#xff01; 从这四种语言的难度、受欢迎度还有作用以及优点缺点给楼主做一个全面的分析&#xff0c;我们可以从中了解其区别&#xff0c;以及…

如何查询多级菜单(采用递归的方法)

应用场景 1.京东 京东的页面就是这么显示的在家用电器下面有电视.空调.洗衣机然后再电视下面又有全面屏电视.教育电视等等 2.我们的后端管理系统 我们后端在页面上显示的很多也是通过层级目录的显示出来。 如何实现 1.准备数据库 我们这里parent_id为0的为我们的一级菜单 …

美国地区TikTok直播电商SOP(附下载)

关于报告的所有内容&#xff0c;公众【营销人星球】获取下载查看 核心观点 随着互联网的普及和社交媒体的兴起&#xff0c;网红直播已经成为了一种新型的娱乐方式和商 业模式。越来越多的人开始关注网红直播&#xff0c;希望通过这种方式获得更多的粉丝和商业机会。但是&…

防勒索病毒

随着勒索软件攻击在2023年的激增&#xff0c;网络安全已成为当今最重要的议题之一。根据区块链分析公司Chainaanalysis的最新报告&#xff0c;勒索软件攻击已成为唯一呈增长趋势的基于加密货币的犯罪行为&#xff0c;勒索金额更是比一年前增加了近1.758亿美元&#xff0c;达到4…

软件设计师(七)面向对象技术

面向对象&#xff1a; Object-Oriented&#xff0c; 是一种以客观世界中的对象为中心的开发方法。 面向对象方法有Booch方法、Coad方法和OMT方法等。推出了同一建模语言UML。 面向对象方法包括面向对象分析、面向对象设计和面向对象实现。 一、面向对象基础 1、面向对象的基本…

CentOS 7 构建 LVS-DR 群集 nginx负载均衡

1、基于 CentOS 7 构建 LVS-DR 群集。 DS&#xff08;Director Server&#xff09;&#xff1a;DIP 192.168.231.132 & VIP 192.168.231.200 [root132 ~]# nmcli c show NAME UUID TYPE DEVICE ens33 c89f4a1a-d61b-4f24-a260…

云曦暑期学习第四周——流量、日志分析

1 日志分析 1.1 What is 日志 日志&#xff0c;是作为记录系统与服务最直接有效的方法。在日志中&#xff0c;可以发现访问记录以及发现攻击线索。日志分析也是最常用的分析安全 事件所采用的途径。系统日志和 web 日志分别记录了不同内容&#xff0c;为分析攻击提供了有效证…

C#--设计模式之单例模式

单例模式大概是所有设计模式中最简单的一种&#xff0c;如果在面试时被问及熟悉哪些设计模式&#xff0c;你可能第一个答的就是单例模式。 单例模式的实现分为两种&#xff1a; 饿汉式&#xff1a;在静态构造函数执行时就立即实例化。懒汉式&#xff1a;在程序执行过程中第一…

RaabitMQ(三) - RabbitMQ队列类型、死信消息与死信队列、懒队列、集群模式、MQ常见消息问题

RabbitMQ队列类型 Classic经典队列 这是RabbitMQ最为经典的队列类型。在单机环境中&#xff0c;拥有比较高的消息可靠性。 经典队列可以选择是否持久化(Durability)以及是否自动删除(Auto delete)两个属性。 Durability有两个选项&#xff0c;Durable和Transient。 Durable表…