RT-Thread STM32F407 BMI088--SPI

BMI088是一款高性能6轴惯性传感器,由16位数字三轴±24g加速度计和16位数字三轴±2000°/ s陀螺仪组成。

这里用SPI来驱动BMI088进行数据解读

  • 第一步,首先在 RT-Thread Settings中进行配置
    在这里插入图片描述

  • 第二步,退出RT-Thread Settings,进入board.h,定义宏
    在这里插入图片描述

  • 第三步,**进入stm32f4xx_hal_conf.h **
    在这里插入图片描述

  • 第四步,STM32 CubeMX配置
    在这里插入图片描述

  • 第五步,添加驱动文件到application
    在这里插入图片描述
    bmi088.c

#include "bmi088.h"
#include <rtdbg.h> 
#include <rtdevice.h> 
#include <board.h>
#include "drv_spi.h"

#define BMI088_SPI_MAX_SPEED (10 * 1000 * 1000) // M
#define CSB1_Pin GET_PIN(B, 14)
#define CSB2_Pin GET_PIN(B, 15)

static rt_err_t _bmi088_spi_read(struct rt_spi_device *dev, rt_uint8_t reg_addr, const rt_uint8_t len, rt_uint8_t *buf)
{
    reg_addr |= 0x80;
    
    dev->bus->owner = dev;
    rt_spi_send_then_recv(dev, &reg_addr, 1, buf, len);    
    
    return RT_EOK;
}

static rt_err_t _bmi088_spi_write(struct rt_spi_device *dev, rt_uint8_t reg_addr, const rt_uint8_t len, rt_uint8_t *buf)
{   
    reg_addr &= 0x7f;
    
    dev->bus->owner = dev;
    rt_spi_send_then_send(dev, &reg_addr, 1, buf, len);
    
    return RT_EOK;
}

static rt_err_t _bmi088_get_accel_raw(struct bmi08x_dev *dev, struct bmi088_3axes *accel)
{
    rt_uint8_t buffer[10];
    uint8_t lsb, msb;
    rt_err_t res;

    struct rt_spi_device *spi_dev = (struct rt_spi_device *)(dev->accel_bus);
    res = _bmi088_spi_read(spi_dev, ACC_X_LSB_REG, 10, buffer);
    if (res != RT_EOK)
    {
        return res;
    }
    lsb = buffer[1];
    msb = buffer[2];
    accel->x = (rt_int16_t)((msb << 8) | lsb); /* X */
    
    lsb = buffer[3];
    msb = buffer[4];
    accel->y = (rt_int16_t)((msb << 8) | lsb);/* Y */

    lsb = buffer[5];
    msb = buffer[6];
    accel->z = (rt_int16_t)((msb << 8) | lsb);/* Z */

    return RT_EOK;
}

static rt_err_t _bmi088_get_gyro_raw(struct bmi08x_dev *dev, struct bmi088_3axes *gyro)
{
    rt_uint8_t buffer[6];
    uint8_t lsb, msb;
    rt_err_t res;
    
    struct rt_spi_device *spi_dev = (struct rt_spi_device *)(dev->gyro_bus);
    res = _bmi088_spi_read(spi_dev, RATE_X_LSB_REG, 6, buffer);
    if (res != RT_EOK)
    {
        return res;
    }
    lsb = buffer[0];
    msb = buffer[1];
    gyro->x = (rt_int16_t)((msb * 256) + lsb); /* X */

    lsb = buffer[2];
    msb = buffer[3];
    gyro->y = (rt_int16_t)((msb * 256) + lsb); /* Y */

    lsb = buffer[4];
    msb = buffer[5];
    gyro->z = (rt_int16_t)((msb * 256) + lsb); /* Z */

    return RT_EOK;
}

/**
* This function gets the data of the accelerometer, unit: m/ss
 *
 * @param dev the pointer of device driver structure
 * @param accel the pointer of 3axes structure for receive data
 *
 * @return the reading number.
 */
rt_size_t bmi088_get_accel(struct bmi08x_dev *dev, struct bmi088_data *buf)
{ 
    struct bmi088_3axes tmp;
    
    _bmi088_get_accel_raw(dev, &tmp);
    buf->x = ((float)tmp.x) /32768.0f * 6 * G;
    buf->y = ((float)tmp.y) /32768.0f * 6 * G;
    buf->z = ((float)tmp.z) /32768.0f * 6 * G;    

    return 1;// just support rw mode
}

/**
* This function gets the data of the gyroscope, unit: rad/s
 *
 * @param dev the pointer of device driver structure
 * @param gyro the pointer of 3axes structure for receive data
 *
 * @return the reading number.
 */
rt_size_t bmi088_get_gyro(struct bmi08x_dev *dev, struct bmi088_data *buf)
{
    struct bmi088_3axes tmp;
    
    _bmi088_get_gyro_raw(dev, &tmp);
    buf->x = (float)tmp.x / 32767.0f * 2000.0f;
    buf->y = (float)tmp.y / 32767.0f * 2000.0f;
    buf->z = (float)tmp.z / 32767.0f * 2000.0f;   
    
    return 1;
}

/**
 * This function software reset the accelerometer of bmi08x.
 *
 * @param dev the pointer of bmi08x driver structure
 *
 * @return the status of software reset, RT_EOK represents software reset successfully.
 */
static rt_err_t _bmi088a_soft_reset(struct bmi08x_dev *dev)
{
    uint8_t send_cmd = BMI08X_SOFT_RESET_CMD;
    struct rt_spi_device *spi_dev = (struct rt_spi_device *)(dev->accel_bus);
    if (_bmi088_spi_write(spi_dev, ACC_SOFTRESET_REG, 1, &send_cmd) == RT_EOK)
    {
        rt_thread_mdelay(BMI08X_ACCEL_SOFTRESET_DELAY_MS);
        return RT_EOK;
    }
    else
    {
        return RT_ERROR;    
    }
}

/**
 * This function software reset the gyroscope of bmi08x.
 *
 * @param dev the pointer of bmi08x driver structure
 *
 * @return the status of software reset, RT_EOK represents software reset successfully.
 */
static rt_err_t _bmi088g_soft_reset(struct bmi08x_dev *dev)
{
    uint8_t send_cmd = BMI08X_SOFT_RESET_CMD;
    struct rt_spi_device *spi_dev = (struct rt_spi_device *)(dev->gyro_bus);
    if (_bmi088_spi_write(spi_dev, GYRO_SOFTRESET_REG, 1, &send_cmd) == RT_EOK)
    {
        rt_thread_mdelay(BMI08X_GYRO_SOFTRESET_DELAY_MS);
        return RT_EOK;
    }
    else
    {
        return RT_ERROR;    
    }
}

/**
 * This function initialize the accelerometer of bmi08x.
 *
 * @param dev the pointer of bmi08x driver structure
 *
 * @return the status of initialization, RT_EOK represents initialize successfully.
 */
static rt_err_t _bmi088a_init(struct bmi08x_dev *dev)
{
	rt_err_t res = RT_EOK;
    uint8_t chip_acc_id[2] = {0};
    // config acc to spi mode
    rt_pin_write(dev->accel_id, PIN_LOW);
    rt_thread_mdelay(1);
    rt_pin_write(dev->accel_id, PIN_HIGH);
 
    struct rt_spi_device *spi_dev = (struct rt_spi_device *)(dev->accel_bus);
    _bmi088_spi_read(spi_dev, ACC_CHIP_ID_REG, 2, chip_acc_id);    /* Dummy read */
    if (chip_acc_id[1] != dev->accel_chip_id) 
    {
        LOG_E("Fail initialize acc");
        goto __exit;        
    }

    rt_thread_mdelay(10);
    res = _bmi088a_soft_reset(dev);
    
    // config acc to spi mode
    rt_pin_write(dev->accel_id, PIN_LOW);
    rt_thread_mdelay(1);
    rt_pin_write(dev->accel_id, PIN_HIGH);
    
    return res;

__exit:
    return RT_ERROR;    
}

/**
 * This function initialize the gyroscope of bmi08x.
 *
 * @param dev the pointer of bmi08x driver structure
 *
 * @return the status of initialization, RT_EOK represents initialize successfully.
 */
static rt_err_t _bmi088g_init(struct bmi08x_dev *dev)
{
	rt_err_t res = RT_EOK;
    rt_uint8_t id = 0;  
    
    struct rt_spi_device *spi_dev = (struct rt_spi_device *)dev->gyro_bus;
    _bmi088_spi_read(spi_dev, GYRO_CHIP_ID_REG, 1, &id);
    
    if (id != dev->gyro_chip_id) 
    {
        LOG_E("Fail initialize gyro");
        goto __exit;
    }
    rt_thread_mdelay(10);
    res = _bmi088g_soft_reset(dev);
    return res;
    
__exit:
    return RT_ERROR;
}

/**
 * This function set the power mode of accelerometer of bmi08x 
 *
 * @param dev the pointer of bmi08x driver structure
 *
 * @return the setting status, RT_EOK represents reading the data successfully.
 */
rt_err_t bmi088a_set_power_mode(struct bmi08x_dev *dev)
{
    uint8_t power_mode = dev->accel_cfg.power;
    uint8_t data[2];
    struct rt_spi_device *spi_dev = (struct rt_spi_device *)(dev->accel_bus);
    
    if (power_mode == BMI08X_ACCEL_PM_ACTIVE) 
    {
        data[0] = BMI08X_ACCEL_PWR_ACTIVE_CMD;
        data[1] = BMI08X_ACCEL_POWER_ENABLE_CMD;
    } 
    else if (power_mode == BMI08X_ACCEL_PM_SUSPEND) 
    {
        data[0] = BMI08X_ACCEL_PWR_SUSPEND_CMD;
        data[1] = BMI08X_ACCEL_POWER_DISABLE_CMD;
    } 
    else 
    {
        LOG_E("Invalid acc power mode!");
        goto __exit;          
    }

    if (_bmi088_spi_write(spi_dev, ACC_PWR_CONF_REG, 1, &data[0]) == RT_EOK)
    {
        rt_thread_mdelay(BMI08X_POWER_CONFIG_DELAY);
        data[1] = BMI08X_ACCEL_POWER_ENABLE_CMD;
        if (_bmi088_spi_write(spi_dev, ACC_PWR_CTRL_REG, 1, &data[1]) == RT_EOK)
        {
            rt_thread_mdelay(BMI08X_POWER_CONFIG_DELAY);
            return RT_EOK;
        }
        else
        {
            LOG_E("Failed write CTRL_REG");
            goto __exit;
        }
    }
    else
    {
        LOG_E("Failed write PWR_REG");
        goto __exit;
    }        
    
__exit:
    return RT_ERROR;
}

/**
 * This function set the power mode of gyroscope of bmi08x 
 *
 * @param dev the pointer of bmi08x driver structure
 *
 * @return the setting status, RT_EOK represents reading the data successfully.
 */
rt_err_t bmi088g_set_power_mode(struct bmi08x_dev *dev)
{
	uint8_t power_mode = dev->gyro_cfg.power;
    uint8_t read_data;
	uint8_t is_power_switching_mode_valid = 1;
    
    struct rt_spi_device *spi_dev = (struct rt_spi_device *)(dev->gyro_bus);
    _bmi088_spi_read(spi_dev, GYRO_LPM1_REG, 1, &read_data);
    
    if (power_mode == read_data) 
    {
        return RT_EOK;
    }
    else 
    {
        // only switching between normal mode and the suspend mode is allowed
        if ((power_mode == BMI08X_GYRO_PM_SUSPEND) && (read_data == BMI08X_GYRO_PM_DEEP_SUSPEND)) 
        {
            is_power_switching_mode_valid = 0;
        }  
        if ((power_mode == BMI08X_GYRO_PM_DEEP_SUSPEND) && (read_data == BMI08X_GYRO_PM_SUSPEND))
        {
            is_power_switching_mode_valid = 0;
        }
        
        if (is_power_switching_mode_valid) 
        {
            if (_bmi088_spi_write(spi_dev, GYRO_LPM1_REG, 1, &power_mode) == RT_EOK)
            {
                rt_thread_mdelay(BMI08X_GYRO_POWER_MODE_CONFIG_DELAY);
            }
        }
        else
        {
            LOG_E("Invalid gyro mode switch");
            goto __exit;        
        }
    
    }
    
__exit:
    return RT_ERROR;   
}

/**
 * This function set the bandwidth(bw), output data rate(odr) and range of accelerometer of bmi08x 
 *
 * @param dev the pointer of bmi08x driver structure
 *
 * @return the setting status, RT_EOK represents  reading the data successfully.
 */
rt_err_t bmi088a_set_meas_conf(struct bmi08x_dev *dev)
{
    uint8_t data[2] = {0};
    uint8_t reg_val[3] = {0};
    uint8_t bw = dev->accel_cfg.bw;
    uint8_t range = dev->accel_cfg.range;
    uint8_t odr = dev->accel_cfg.odr;
    uint8_t is_odr_invalid = 0, is_bw_invalid = 0, is_range_invalid = 0;
    
    if ((odr < BMI08X_ACCEL_ODR_12_5_HZ) || (odr > BMI08X_ACCEL_ODR_1600_HZ))
    {
        is_odr_invalid = 1;
    }
    if (bw > BMI08X_ACCEL_BW_NORMAL) 
    {
        is_bw_invalid = 1;
    }
    if (range > BMI088_ACCEL_RANGE_24G) 
    {
        is_range_invalid = 1;
    }
    
    if ((!is_odr_invalid) && (!is_bw_invalid) && (!is_range_invalid)) 
    {
        //dummy read
        struct rt_spi_device *spi_dev = (struct rt_spi_device *)(dev->accel_bus);
        if (_bmi088_spi_read(spi_dev, ACC_CONF_REG, 2, data) == RT_EOK)
        {
            data[0] = (1<<7) | (2<<4) | (0xB<<0);// bwp = normal, odr = 800
            _bmi088_spi_write(spi_dev, ACC_CONF_REG, 1, &data[0]);
            
            data[1] = 0x01;// range = 6G
            _bmi088_spi_write(spi_dev, ACC_RANGE_REG, 1, &data[1]);
            
            rt_thread_mdelay(10);
            _bmi088_spi_read(spi_dev, ACC_CONF_REG, 3, reg_val);// dummy read
            if ((reg_val[1] == 0xAB) && (reg_val[2] == 0x01)) 
            {
                return RT_EOK;
            }
        }
        
    }
    return RT_ERROR;
}

/**
 * This function set the bandwidth(bw), output data rate(odr) and range of gyroscope of bmi08x 
 *
 * @param dev the pointer of bmi08x driver structure
 *
 * @return the setting status, RT_EOK represents reading the data successfully.
 */
rt_err_t bmi088g_set_meas_conf(struct bmi08x_dev *dev)
{
    uint8_t data;
    uint8_t bw_odr = dev->gyro_cfg.bw, range = dev->gyro_cfg.range;
    uint8_t reg_val[2] = {0};
    uint8_t is_range_invalid = 0, is_odr_invalid = 0;

    if (bw_odr > BMI08X_GYRO_BW_32_ODR_100_HZ) 
    {
        is_odr_invalid = 1;
    }
    if (range > BMI08X_GYRO_RANGE_125_DPS) 
    {
        is_range_invalid = 1;
    } 
    if ((!is_odr_invalid) && (!is_range_invalid)) 
    {
//      data = BMI08X_SET_BITS_POS_0(data, BMI08X_GYRO_BW, odr);
        data = 0x01;// ODR = 2000Hz, Filter bandwidth = 230Hz
        struct rt_spi_device *spi_dev = (struct rt_spi_device *)(dev->gyro_bus);
        if (_bmi088_spi_write(spi_dev, GYRO_BANDWIDTH_REG, 1, &data) == RT_EOK)
        {
//          data = BMI08X_SET_BITS_POS_0(data, GYRO_RANGE_REG, range);
            data = 0x00;// range = 2000deg/s
            if (_bmi088_spi_write(spi_dev, GYRO_RANGE_REG, 1, &data) == RT_EOK) 
            {
                rt_thread_mdelay(10);
                _bmi088_spi_read(spi_dev, GYRO_RANGE_REG, 2, reg_val);
                if ((reg_val[0] == 0x00) && (reg_val[1] == 0x81))// 7 bit always 1
                {
                    return RT_EOK;
                }                
            }                
        }
    }
    return RT_ERROR;    
}

/**
 * This function initialize the bmi088 device.
 *
 * @param acc_spi_name the name of spi device(Accelerometer)
 * @param gyro_spi_name the name of spi device(Gyroscope)
 *
 * @return the pointer of bmi08x driver structure, RT_NULL represents initialization failed.
 */
struct bmi08x_dev *bmi088_init(const char *acc_spi_name, const char *gyro_spi_name)
{
    struct bmi08x_dev *dev = RT_NULL;
    rt_uint8_t res = RT_EOK;

    RT_ASSERT(acc_spi_name);
    RT_ASSERT(gyro_spi_name);

    dev = rt_calloc(1, sizeof(struct bmi08x_dev));
    if (dev == RT_NULL)
    {
        LOG_E("Can't allocate memory for bmi08x device on '%s' and '%s' ", acc_spi_name, gyro_spi_name);
        goto __exit;
    }
    
    dev->accel_bus = rt_device_find(acc_spi_name);
    dev->gyro_bus = rt_device_find(gyro_spi_name);
    
    
    if ((dev->accel_bus == RT_NULL) || (dev->gyro_bus == RT_NULL))
    {
        LOG_E("Can't find device:'%s' of '%s'", acc_spi_name, gyro_spi_name);
        goto __exit;
    }
    
    if (dev->accel_bus->type != dev->gyro_bus->type)
    {
        LOG_E("The bus type of '%s' and '%s' should same", acc_spi_name, gyro_spi_name);
        goto __exit;    
    }

    if (dev->accel_bus->type == RT_Device_Class_I2CBUS)
    {
        LOG_E("Bmi08x not support I2C temporarily");
        goto __exit;      
    }
    else if (dev->accel_bus->type == RT_Device_Class_SPIDevice)
    {
//#ifdef RT_USING_SPI
        struct rt_spi_configuration cfg;

        cfg.data_width = 8;
        cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB;
        cfg.max_hz = BMI088_SPI_MAX_SPEED; /* Set spi max speed */
        struct rt_spi_device *spi_dev = (struct rt_spi_device *)dev->accel_bus;
        spi_dev->bus->owner = spi_dev;
        rt_spi_configure(spi_dev, &cfg);
//#endif
    }
    else
    {
        LOG_E("Unsupported bus type:'%s'!", acc_spi_name);
        goto __exit;
    }
    
    // acc init
    {
        dev->accel_id = CSB1_Pin;
        dev->accel_chip_id = 0x1E;
        dev->accel_cfg.bw = BMI08X_ACCEL_BW_NORMAL;
        dev->accel_cfg.odr = BMI08X_ACCEL_ODR_800_HZ;
        dev->accel_cfg.power = BMI08X_ACCEL_PM_ACTIVE; 
        dev->accel_cfg.range = BMI088_ACCEL_RANGE_6G;
        res += _bmi088a_init(dev);
        res += bmi088a_set_power_mode(dev);
        res += bmi088a_set_meas_conf(dev);        
    }
    
    // gyro init
    {
        dev->gyro_id = CSB2_Pin;
        dev->gyro_chip_id = 0x0F;
        dev->gyro_cfg.bw = BMI08X_GYRO_BW_230_ODR_2000_HZ;
        dev->gyro_cfg.odr = BMI08X_GYRO_BW_230_ODR_2000_HZ;
        dev->gyro_cfg.power = BMI08X_GYRO_PM_NORMAL;
        dev->gyro_cfg.range = BMI08X_GYRO_RANGE_2000_DPS;
        res += _bmi088g_init(dev);
        res += bmi088g_set_power_mode(dev);
        res += bmi088g_set_meas_conf(dev);
    }
    
    rt_thread_mdelay(20);
    
    if (res == RT_EOK)
    {
        LOG_I("Device init succeed!");
    }
    else
    {
        goto __exit;
    }

    return dev;

__exit:
    if (dev != RT_NULL)
    {
        rt_free(dev);
    }
    return RT_NULL;

}

/**
 * This function releases memory
 *
 * @param dev the pointer of bmi08x driver structure
 */
void bmi088_deinit(struct bmi08x_dev *dev)
{
    RT_ASSERT(dev);

    rt_free(dev);
}



bmi088.h

#ifndef __BMI088_H__
#define __BMI088_H__

#include <rtthread.h>
#include "sensor.h"


#define IMU_THREAD_STACK_SIZE 4086
/*************************** Common Macros for both Accel and Gyro *****************************/
// Bit #0  : Read/Write bit
// Bit #1-7: Address AD
#define BMI08X_SPI_RD_MASK                          UINT8_C(0x80)
#define BMI08X_SPI_WR_MASK                          UINT8_C(0x7F)

/* CMD: soft reset */
#define BMI08X_SOFT_RESET_CMD                       UINT8_C(0xB6)

/* CMD: accel power save */
#define BMI08X_ACCEL_PWR_ACTIVE_CMD                 UINT8_C(0x00)
#define BMI08X_ACCEL_PWR_SUSPEND_CMD                UINT8_C(0x03)

/* CMD: accel power control */ 
#define BMI08X_ACCEL_POWER_DISABLE_CMD              UINT8_C(0x00)
#define BMI08X_ACCEL_POWER_ENABLE_CMD               UINT8_C(0x04)

/* Accel Power Mode */
#define BMI08X_ACCEL_PM_ACTIVE                      UINT8_C(0x00)
#define BMI08X_ACCEL_PM_SUSPEND                     UINT8_C(0x03)

/* Gyro Power mode */
#define BMI08X_GYRO_PM_NORMAL                       UINT8_C(0x00)
#define BMI08X_GYRO_PM_DEEP_SUSPEND                 UINT8_C(0x20)
#define BMI08X_GYRO_PM_SUSPEND                      UINT8_C(0x80)

/* Accel Bandwidth */
#define BMI08X_ACCEL_BW_OSR4                        UINT8_C(0x00)
#define BMI08X_ACCEL_BW_OSR2                        UINT8_C(0x01)
#define BMI08X_ACCEL_BW_NORMAL                      UINT8_C(0x02)

/* Accel Output Data Rate */
#define BMI08X_ACCEL_ODR_12_5_HZ                    UINT8_C(0x05)
#define BMI08X_ACCEL_ODR_25_HZ                      UINT8_C(0x06)
#define BMI08X_ACCEL_ODR_50_HZ                      UINT8_C(0x07)
#define BMI08X_ACCEL_ODR_100_HZ                     UINT8_C(0x08)
#define BMI08X_ACCEL_ODR_200_HZ                     UINT8_C(0x09)
#define BMI08X_ACCEL_ODR_400_HZ                     UINT8_C(0x0A)
#define BMI08X_ACCEL_ODR_800_HZ                     UINT8_C(0x0B)
#define BMI08X_ACCEL_ODR_1600_HZ                    UINT8_C(0x0C)
/* Accel Range */
#define BMI088_ACCEL_RANGE_3G                       UINT8_C(0x00)
#define BMI088_ACCEL_RANGE_6G                       UINT8_C(0x01)
#define BMI088_ACCEL_RANGE_12G                      UINT8_C(0x02)
#define BMI088_ACCEL_RANGE_24G                      UINT8_C(0x03)

/* Gyro Range */
#define BMI08X_GYRO_RANGE_2000_DPS                  UINT8_C(0x00)
#define BMI08X_GYRO_RANGE_1000_DPS                  UINT8_C(0x01)
#define BMI08X_GYRO_RANGE_500_DPS                   UINT8_C(0x02)
#define BMI08X_GYRO_RANGE_250_DPS                   UINT8_C(0x03)
#define BMI08X_GYRO_RANGE_125_DPS                   UINT8_C(0x04)

/* Gyro Output data rate and bandwidth */
#define BMI08X_GYRO_BW_532_ODR_2000_HZ              UINT8_C(0x00)
#define BMI08X_GYRO_BW_230_ODR_2000_HZ              UINT8_C(0x01)
#define BMI08X_GYRO_BW_116_ODR_1000_HZ              UINT8_C(0x02)
#define BMI08X_GYRO_BW_47_ODR_400_HZ                UINT8_C(0x03)
#define BMI08X_GYRO_BW_23_ODR_200_HZ                UINT8_C(0x04)
#define BMI08X_GYRO_BW_12_ODR_100_HZ                UINT8_C(0x05)
#define BMI08X_GYRO_BW_64_ODR_200_HZ                UINT8_C(0x06)
#define BMI08X_GYRO_BW_32_ODR_100_HZ                UINT8_C(0x07)
#define BMI08X_GYRO_ODR_RESET_VAL                   UINT8_C(0x80)

#define BMI08X_ACCEL_DATA_SYNC_MODE_OFF 0x00
#define BMI08X_ACCEL_DATA_SYNC_MODE_400HZ 0x01
#define BMI08X_ACCEL_DATA_SYNC_MODE_1000HZ 0x02
#define BMI08X_ACCEL_DATA_SYNC_MODE_2000HZ 0x03

/* Wait Time */
#define BMI08X_ACCEL_SOFTRESET_DELAY_MS             UINT8_C(1)
#define BMI08X_GYRO_SOFTRESET_DELAY_MS              UINT8_C(30)
#define BMI08X_GYRO_POWER_MODE_CONFIG_DELAY         UINT8_C(30)
#define BMI08X_POWER_CONFIG_DELAY                   UINT8_C(50)

#define G (9.80f)
#define deg2rad (3.1415926 / 180.0f)
#define rad2deg (180.0f / 3.1415926)

typedef enum 
{
    ACC_CHIP_ID_REG             = 0x00,
    ACC_ERR_REG                 = 0x02,
    ACC_STATUS_REG              = 0x03,
    ACC_X_LSB_REG               = 0x12,
    ACC_X_MSB_REG               = 0x13,
    ACC_Y_LSB_REG               = 0x14,
    ACC_Y_MSB_REG               = 0x15,
    ACC_Z_LSB_REG               = 0x16,
    ACC_Z_MSB_REG               = 0x17,
    TEMP_MSB_REG                = 0x22,
    TEMP_LSB_REG                = 0x23,
    ACC_CONF_REG                = 0x40,
    ACC_RANGE_REG               = 0x41,
    INT1_IO_CTRL_REG            = 0x53,
    INT2_IO_CTRL_REG            = 0x54,
    ACC_SELF_TEST_REG           = 0x6D,
    ACC_PWR_CONF_REG            = 0x7C,
    ACC_PWR_CTRL_REG            = 0x7D,
    ACC_SOFTRESET_REG           = 0x7E
} bmi088a_reg_list_t;

typedef enum 
{
    GYRO_CHIP_ID_REG            = 0x00,
    RATE_X_LSB_REG              = 0x02,
    RATE_X_MSB_REG              = 0x03,
    RATE_Y_LSB_REG              = 0x04,
    RATE_Y_MSB_REG              = 0x05,
    RATE_Z_LSB_REG              = 0x06,
    RATE_Z_MSB_REG              = 0x07,
    GYRO_INT_STAT_1_REG         = 0x0A,
    GYRO_RANGE_REG              = 0x0F,
    GYRO_BANDWIDTH_REG          = 0x10,
    GYRO_LPM1_REG               = 0x11,
    GYRO_SOFTRESET_REG          = 0x14,
    GYRO_INT_CTRL_REG           = 0x15
} bmi088g_reg_list_t;

enum bmi08x_intf {
/*! I2C interface */
BMI08X_I2C_INTF,
/*! SPI interface */
BMI08X_SPI_INTF
};

struct bmi08x_cfg 
{
/*! power mode */
uint8_t power;
/*! range */
uint8_t range;
/*! bandwidth */
uint8_t bw;
/*! output data rate */
uint8_t odr;
};

/* bmi088 device structure */
struct bmi08x_dev 
{
/*! Accel chip Id */
uint8_t accel_chip_id;
/*! Gyro chip Id */
uint8_t gyro_chip_id;
/*! Accel device Id in I2C mode, can be used for chip select pin in SPI mode */
rt_base_t accel_id;
/*! Gyro device Id in I2C mode, can be used for chip select pin in SPI mode */
rt_base_t gyro_id;
/*! Device of accel bus*/
rt_device_t accel_bus;
/*! Device of gyro bus*/
rt_device_t gyro_bus;
/*! 0 - I2C , 1 - SPI Interface */
enum bmi08x_intf intf;
/*! Structure to configure accel sensor  */
struct bmi08x_cfg accel_cfg;
/*! Structure to configure gyro sensor  */
struct bmi08x_cfg gyro_cfg;
/*! Config stream data buffer address will be assigned*/
const uint8_t *config_file_ptr;
/*! Max read/write length (maximum supported length is 32).
To be set by the user */
uint8_t read_write_len;
};

struct bmi088_3axes
{
    rt_int16_t x;
    rt_int16_t y;
    rt_int16_t z;
};

struct bmi088_data
{
    float x;
    float y;
    float z;
};

struct bmi08x_dev *bmi088_init(const char *acc_name, const char *gyro_name);
void bmi088_deinit(struct bmi08x_dev *dev);
rt_err_t bmi088a_set_power_mode(struct bmi08x_dev *dev);
rt_err_t bmi088g_set_power_mode(struct bmi08x_dev *dev);
rt_err_t bmi088a_set_meas_conf(struct bmi08x_dev *dev);
rt_err_t bmi088g_set_meas_conf(struct bmi08x_dev *dev);
rt_size_t bmi088_get_accel(struct bmi08x_dev *dev, struct bmi088_data *buf);
rt_size_t bmi088_get_gyro(struct bmi08x_dev *dev, struct bmi088_data *buf);


#endif // BMI088_H

sensor_intf_bmi088.c

#include "sensor_intf_bmi088.h"
#include "bmi088.h"
#include <rtdbg.h>

static struct bmi08x_dev *bmi_dev;

static rt_err_t _bmi088_init(struct rt_sensor_intf *acc_intf, struct rt_sensor_intf *gyr_intf)
{
    bmi_dev = bmi088_init(acc_intf->dev_name, gyr_intf->dev_name);

    if (bmi_dev == RT_NULL)
    {
        return -RT_ERROR;
    }

    return RT_EOK;
}

static rt_err_t _bmi088_set_power_mode(rt_sensor_t sensor, rt_uint8_t power)
{   
    if (sensor->info.type == RT_SENSOR_CLASS_ACCE)
    {
        if (power == RT_SENSOR_POWER_DOWN) 
        {
            bmi_dev->accel_cfg.power = BMI08X_ACCEL_PM_SUSPEND;
        }
        else if (power == RT_SENSOR_POWER_NORMAL)
        {
            bmi_dev->accel_cfg.power = BMI08X_ACCEL_PM_ACTIVE;
        }
        else 
        {
            LOG_E("Unsupported power mode %d", power);
            return -RT_ERROR;        
        }
        
        bmi088a_set_power_mode(bmi_dev);
    }
    else if (sensor->info.type == RT_SENSOR_CLASS_GYRO)
    {
        if (power == RT_SENSOR_POWER_DOWN) 
        {
            bmi_dev->gyro_cfg.power = BMI08X_GYRO_PM_SUSPEND;
        }
        else if (power == RT_SENSOR_POWER_NORMAL)
        {
            bmi_dev->gyro_cfg.power = BMI08X_GYRO_PM_NORMAL;
        }
        else if (power == RT_SENSOR_POWER_NONE)
        {
            bmi_dev->gyro_cfg.power = BMI08X_GYRO_PM_DEEP_SUSPEND;
        }
        else 
        {
            LOG_E("Unsupported power mode %d", power);
            return -RT_ERROR;        
        }
        
        bmi088g_set_power_mode(bmi_dev);
    }
    else 
    {
        LOG_E("Unsupported type %d", sensor->info.type);
        return -RT_ERROR;
    }
    return RT_EOK;
}

/**
* This function get the data of bmi088 sensor, unit: mg, mdps
 *
 * @param sensor the pointer of rt_sensor_device.
 * @param data the pointer of rt_sensor_data
 * 
 * @return the reading number.
 */
static rt_size_t _bmi088_get_data(rt_sensor_t sensor, struct rt_sensor_data *data)
{
    rt_size_t len;
    if (sensor->info.type == RT_SENSOR_CLASS_ACCE)
    {
        struct bmi088_data acce_m_ss;
        len =  bmi088_get_accel(bmi_dev, &acce_m_ss);

        data->type = RT_SENSOR_CLASS_ACCE;
        data->data.acce.x = acce_m_ss.x * 1000;
        data->data.acce.y = acce_m_ss.y * 1000;
        data->data.acce.z = acce_m_ss.z * 1000;
        data->timestamp = rt_sensor_get_ts();
    }
    else if (sensor->info.type == RT_SENSOR_CLASS_GYRO)
    {
        struct bmi088_data gyro_rad_s;
        len = bmi088_get_gyro(bmi_dev, &gyro_rad_s);

        data->type = RT_SENSOR_CLASS_GYRO;
        data->data.gyro.x = gyro_rad_s.x * rad2deg * 1000;
        data->data.gyro.y = gyro_rad_s.y * rad2deg * 1000;
        data->data.gyro.z = gyro_rad_s.x * rad2deg * 1000;
        data->timestamp = rt_sensor_get_ts();
    }
    return len;
}

/**
* This function get the data of bmi088 sensor
 *
 * @param sensor the pointer of rt_sensor_device.
 * @param buf the pointer of data buffer.
 * @param len the length of data.
 * 
 * @return the reading number.
 */
static rt_size_t _bmi088_fetch_data(struct rt_sensor_device *sensor, void *buf, rt_size_t len)
{
    if (sensor->config.mode == RT_DEVICE_OFLAG_RDONLY)
    {
        return _bmi088_get_data(sensor, (struct rt_sensor_data *)buf);
    }
    else
    {
        return 0;
    }
}

/**
* This function control the bmi088 sensor
 *
 * @param sensor the pointer of rt_sensor_device.
 * @param cmd the type of command.
 * @param args the null pointer of commmand parameter, notice the pointer is four bytes.
 * 
 * @return the reading number.
 */
static rt_err_t _bmi088_control(struct rt_sensor_device *sensor, int cmd, void *args)//args��32λ(ָ�붼��4���ֽ�)
{
    rt_err_t result = RT_EOK;

    switch (cmd)
    {
    case RT_SENSOR_CTRL_GET_ID:
        if (sensor->info.type == RT_SENSOR_CLASS_ACCE) 
        {
            *(rt_uint8_t *)args = 0x1E;
        }
        else if (sensor->info.type == RT_SENSOR_CLASS_GYRO)
        {
            *(rt_uint8_t *)args = 0x0F;
        }
        break;
    case RT_SENSOR_CTRL_SET_ODR:
    case RT_SENSOR_CTRL_SET_RANGE:
        if (sensor->info.type == RT_SENSOR_CLASS_ACCE) 
        {
            result = bmi088a_set_meas_conf(bmi_dev);
        }
        else if (sensor->info.type == RT_SENSOR_CLASS_GYRO)
        {
            result = bmi088g_set_meas_conf(bmi_dev);
        }
        break;
    case RT_SENSOR_CTRL_SET_POWER:
        _bmi088_set_power_mode(sensor, (rt_uint32_t)args & 0xff);
        break;
    case RT_SENSOR_CTRL_SET_MODE:
        break;
    case RT_SENSOR_CTRL_SELF_TEST:
        /* TODO */
        result = -RT_EINVAL;
        break;
    default:
        return -RT_EINVAL;
    }
    return result;
}

static struct rt_sensor_ops sensor_ops =
{
    _bmi088_fetch_data, 
    _bmi088_control
};

/**
* This function initialize the bmi088
 *
 * @param name the name of bmi088, just first three characters will be used.
 * @param acc_cfg the pointer of configuration structure for accelarometer.
 * @param gyr_cfg the pointer of configuration structure for gyroscope.
 * 
 * @return the reading number.
 */
rt_err_t rt_hw_bmi088_init(const char *name, struct rt_sensor_config *acc_cfg, struct rt_sensor_config *gyr_cfg)
{   
    rt_int8_t result;
    rt_sensor_t sensor_acce = RT_NULL, sensor_gyro = RT_NULL;

//#ifdef PKG_USING_BMI088_ACCE
    /* accelerometer sensor register */
    {
        sensor_acce = rt_calloc(1, sizeof(struct rt_sensor_device));
        if (sensor_acce == RT_NULL)
        {
            return -1;
        }
            
        sensor_acce->info.type       = RT_SENSOR_CLASS_ACCE;
        sensor_acce->info.vendor     = RT_SENSOR_VENDOR_BOSCH;
        sensor_acce->info.model      = "bmi088_acc";
        sensor_acce->info.unit       = RT_SENSOR_UNIT_MG;
        sensor_acce->info.intf_type  = RT_SENSOR_INTF_SPI;
        sensor_acce->info.range_max  = 16000;
        sensor_acce->info.range_min  = 2000;
        sensor_acce->info.period_min = 5;

        rt_memcpy(&sensor_acce->config, acc_cfg, sizeof(struct rt_sensor_config));
        sensor_acce->ops = &sensor_ops;

        result = rt_hw_sensor_register(sensor_acce, name, RT_DEVICE_FLAG_RDWR, RT_NULL);
        if (result != RT_EOK)
        {
            LOG_E("device register err code: %d", result);
            goto __exit;
        }
    }
//#endif
//#ifdef PKG_USING_BMI088_GYRO
    /* gyroscope sensor register */
    {
        sensor_gyro = rt_calloc(1, sizeof(struct rt_sensor_device));
        if (sensor_gyro == RT_NULL)
        {
            goto __exit;
        }
            
        sensor_gyro->info.type       = RT_SENSOR_CLASS_GYRO;
        sensor_gyro->info.vendor     = RT_SENSOR_VENDOR_BOSCH;
        sensor_gyro->info.model      = "bmi088_gyro";
        sensor_gyro->info.unit       = RT_SENSOR_UNIT_MDPS;
        sensor_gyro->info.intf_type  = RT_SENSOR_INTF_SPI;
        sensor_gyro->info.range_max  = 2000000;
        sensor_gyro->info.range_min  = 250000;
        sensor_gyro->info.period_min = 5;

        rt_memcpy(&sensor_gyro->config, gyr_cfg, sizeof(struct rt_sensor_config));
        sensor_gyro->ops = &sensor_ops;

        result = rt_hw_sensor_register(sensor_gyro, name, RT_DEVICE_FLAG_RDWR, RT_NULL);
        if (result != RT_EOK)
        {
            LOG_E("device register err code: %d", result);
            goto __exit;
        }
    }
//#endif

    result = _bmi088_init(&acc_cfg->intf, &gyr_cfg->intf);
    if (result != RT_EOK)
    {
        LOG_E("_bmi088_init err code: %d", result);
        goto __exit;
    }

    LOG_I("sensor init success");
    return RT_EOK;

__exit:
    if (sensor_acce)
    {
        rt_free(sensor_acce);
    } 
    if (sensor_gyro)
    {
        rt_free(sensor_gyro);
    }  
    if (bmi_dev)
    {
        bmi088_deinit(bmi_dev);
    }
    return -RT_ERROR;
}

sensor_intf_bmi088.h

#ifndef __SENSOR_INTF_BMI088_H__
#define __SENSOR_INTF_BMI088_H__

#include "sensor.h"
#include "BMI088.h"


rt_err_t rt_hw_bmi088_init(const char *name, struct rt_sensor_config *acc_cfg, struct rt_sensor_config *gyr_cfg);

#endif

  • 第六步,到main.c 配置bmi088
    ①配置spi,配置片选引脚
   
    rt_hw_spi_device_attach(BMI088_BUS_NAME, BMI088A_SPI_NAME, GPIOF, GPIO_PIN_3);
    rt_hw_spi_device_attach(BMI088_BUS_NAME, BMI088G_SPI_NAME, GPIOF, GPIO_PIN_4);

②初始化bmi

    struct rt_sensor_config acc_cfg = {0};
    struct rt_sensor_config gyr_cfg = {0};

    acc_cfg.intf.dev_name = BMI088A_SPI_NAME;
    gyr_cfg.intf.dev_name = BMI088G_SPI_NAME;

    rt_hw_bmi088_init("bmi", &acc_cfg, &gyr_cfg);

③查找 spi 设备获取设备句柄


    acce_device_t = rt_device_find("acce_bmi");
    if (acce_device_t == RT_NULL)
    {
        LOG_E("Can't find acce device\r\n");
    }
    else
    {
        rt_device_open(acce_device_t, RT_DEVICE_OFLAG_RDWR);
    }

    gyro_device_t = rt_device_find("gyro_bmi");
    if (gyro_device_t == RT_NULL)
    {
        LOG_E("Can't find gyro device\r\n");
    }
    else
    {
        rt_device_open(gyro_device_t, RT_DEVICE_OFLAG_RDWR);
    }

④读取姿态数据

    rt_device_read(acce_device_t, 0, &acc_test, 1);   //加速度
    rt_device_read(gyro_device_t, 0, &gyr_test, 1);   //陀螺仪

main.c

include <rtthread.h>
#include <rtdbg.h>
#include <rtdevice.h>
#include <board.h>
#include "bmi088.h"
#include "sensor_intf_bmi088.h"

#define DBG_TAG "main"
#define DBG_LVL DBG_LOG

#define SPI_DEVICE_NAME     "spi10"
#define SPI_BUS_NAME        "spi1"
#define BMI088_BUS_NAME "spi1"
#define BMI088A_SPI_NAME "spi10"
#define BMI088G_SPI_NAME "spi11"

static rt_device_t acce_device_t;
static rt_device_t gyro_device_t;
struct rt_sensor_data acc_test;
struct rt_sensor_data gyr_test;

int main(void)
{

    // 配置spi,配置片选引脚(要在acc、gyr初始化之前配置,因为器件初始化中涉及到引脚操作)
    rt_hw_spi_device_attach(BMI088_BUS_NAME, BMI088A_SPI_NAME, GPIOF, GPIO_PIN_3);
    rt_hw_spi_device_attach(BMI088_BUS_NAME, BMI088G_SPI_NAME, GPIOF, GPIO_PIN_4);

    // 注册传感器
    struct rt_sensor_config acc_cfg = {0};
    struct rt_sensor_config gyr_cfg = {0};

    acc_cfg.intf.dev_name = BMI088A_SPI_NAME;
    gyr_cfg.intf.dev_name = BMI088G_SPI_NAME;

    rt_hw_bmi088_init("bmi", &acc_cfg, &gyr_cfg);

    /* 查找 spi 设备获取设备句柄 */
    acce_device_t = rt_device_find("acce_bmi");
    if (acce_device_t == RT_NULL)
    {
        LOG_E("Can't find acce device\r\n");
    }
    else
    {
        rt_device_open(acce_device_t, RT_DEVICE_OFLAG_RDWR);
    }

    gyro_device_t = rt_device_find("gyro_bmi");
    if (gyro_device_t == RT_NULL)
    {
        LOG_E("Can't find gyro device\r\n");
    }
    else
    {
        rt_device_open(gyro_device_t, RT_DEVICE_OFLAG_RDWR);
    }

    while (1)
    {
        rt_device_read(acce_device_t, 0, &acc_test, 1);   //加速度
        rt_device_read(gyro_device_t, 0, &gyr_test, 1);   //陀螺仪

        rt_kprintf("x=%d  y=%d  z=%d\n",acc_test.data.acce.x,acc_test.data.acce.y,acc_test.data.acce.z);
        //rt_kprintf("x=%d  y=%d  z=%d\n",gyr_test.data.gyro.x,gyr_test.data.gyro.y,gyr_test.data.gyro.z);
        rt_thread_mdelay(500);
    }
}

如下为加速度计数据:
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数模建模竞赛——写作手三天速成(文末领取)

目录 第一天&#xff1a;准备论文模板&#xff0c;学习各类基础画图技巧 1、论文模板 2、基础画图能力 第二天&#xff1a;看按模型算法分类的优秀论文&#xff0c;学习其模型的写作方式 第三天&#xff1a;配合团队完成真题练习 第一天&#xff1a;准备论文模板&#xff…

【网络通信】探索UDP与TCP协议、IP地址和端口号的奥妙

&#x1f33a;个人主页&#xff1a;Dawn黎明开始 &#x1f380;系列专栏&#xff1a;网络奇幻之旅 ⭐每日一句&#xff1a;往前走&#xff0c;朝着光 &#x1f4e2;欢迎大家&#xff1a;关注&#x1f50d;点赞&#x1f44d;评论&#x1f4dd;收藏⭐️ 文章目录 &#x1f4cb;前…

嵌入式 Linux 移植与系统启动方法

1、Linux系统启动与U-Boot 所谓移植就是把程序代码从一种运行环境转移到另一种运行环境。对于内核移植来说&#xff0c;主要是从一种硬件平台转移到另一种硬件平台上运行。 体系结构级别的移植是指在不同体系结构平台上Linux内核的移植&#xff0c;例如&#xff0c;在ARM、MI…

【2023春李宏毅机器学习】生成式学习的两种策略

文章目录 1 各个击破2 一步到位3 两种策略的对比 生成式学习的两种策略&#xff1a;各个击破、一步到位 对于文本生成&#xff1a;把每一个生成的元素称为token&#xff0c;中文当中token指的是字&#xff0c;英文中的token指的是word piece。比如对于unbreakable&#xff0c;他…

【docker】iptables实现NAT

iptables是一个Linux内核中的防火墙工具&#xff0c;可以被用来执行各种网络相关的任务&#xff0c;如过滤、NAT和端口转发等&#xff0c;可以监控、过滤和重定向网络流量。 iptables可以用于以下应用场景&#xff1a; 网络安全&#xff1a;iptables可以过滤网络流量&#xf…

潇洒郎: 小白一次性成功——小米红米手机解BL锁+ ROOT-刷面具

一、账号与设备绑定 手机登录账号,绑定账号,使用手机卡流量,等待7天后解BL锁。 二、解BL锁 下载工具 申请解锁小米手机 (miui.com) https://www.miui.com/unlock/index.html 1、登录账号-与绑定的账号一样 2、驱动检测安装 驱动安装进入Fastboot模式后,会自动识别已连接…

【数据结构】树与二叉树(二十):树获取大儿子、大兄弟结点的算法(GFC、GNB)

文章目录 5.1 树的基本概念5.1.1 树的定义5.1.2 森林的定义5.1.3 树的术语 5.2 二叉树5.3 树5.3.1 树的存储结构1. 理论基础2. 典型实例3. Father链接结构4. 儿子链表链接结构5. 左儿子右兄弟链接结构 5.3.2 获取结点的算法1. 获取大儿子结点的算法&#xff08;GFC&#xff09;…

Linux-top命令解释

Linux-top命令解释 常用参数查看所有逻辑核的运行情况&#xff1a;1查看指定进程的情况&#xff1a;-p pid显示进程的完整命令&#xff1a;-c 面板指标解释第一行top第二行tasks第三行%Cpu第四行Mem第五行Swap第六行各进程监控PID&#xff1a;进程IDUSER&#xff1a;进程所有者…

“流量为王”的时代一去不返!如何押注互联网下一个黄金十年

目录 1“流量为王”的时代一去不返&#xff01;如何押注互联网下一个黄金十年 2AI夺走的第一份工作竟是OpenAI CEO&#xff1f;阿尔特曼被“扫地出门”&#xff0c;网友热评&#xff1a;是被GPT-5取代了吗&#xff1f;马斯克更“毒”&#xff0c;挂出求职申请链接 3GPT-4V新玩…

cocos 构建发布没有对话框

控制台log输出为何频频失踪?   wxss代码为何频频失效?   wxml布局为何乱作一团?   究竟是道德的沦丧?还是人性的缺失?   让我们一起来 走 跑进科学 前言 游戏审核了六个月终于通过了 我说改点东西再构建发布一版 点半天没反应 正文 1.打开项目目录 2.关闭cocosC…

Linux网络ssh服务

目录 一.ssh服务基础 1.ssh服务简介 2.ssh服务原理 二.ssh服务应用 1.ssh配置文件 2.ssh连接验证 三.ssh服务端 1.修改默认端口号 2.免密连接登录 3.禁止root用户登录 4.ssh服务的最佳实践 一.ssh服务基础 1.ssh服务简介 SSH&#xff1a;是一种安全通道协议&#x…

qtpdfium的编译及读取pdf文件和一些简单操作

qtpdfium是谷歌的一款开源项目&#xff0c;它的内核是基于国内的福昕pdf&#xff0c;许可协议为 BSD 3-Clause&#xff0c;允许用于闭源商业行为 下载 我们可以从git上进行下载&#xff0c;github&#xff0c;如果嫌下载速度慢&#xff0c;可以从csdn进行下载csdn 下载完成之…

Ubuntu 22.04安装Rust编译环境并且测试

我参考的博客是《Rust使用国内Crates 源、 rustup源 |字节跳动新的 Rust 镜像源以及安装rust》 lsb_release -r看到操作系统版本是22.04,uname -r看到内核版本是uname -r。 sudo apt install -y gcc先安装gcc&#xff0c;要是结果给我的一样的话&#xff0c;那么就是安装好了…

[CISCN 2023 初赛]ezbyte

从字符串找到%100s&#xff0c;发现下面有个yes 跟踪yes 、 yes之前有个jmp 看上面的代码&#xff0c;要想跳转到含有yes这一块&#xff0c;需要r13等于r12 xor r13&#xff0c;r13说明r13是0&#xff0c;但是找不到r12的操作代码 实际着这个关键的操作r12的加密逻辑&…

java并发编程之基础与原理2

cpu缓存结构剖析 下面说一下概念与作用 CPU缓存即高速缓冲存储器&#xff0c;是位于CPU与主内存间的一种容量较小但速度很高的存储 器。由于CPU的速度远高于主内存&#xff0c;CPU直接从内存中存取数据要等待一定时间周期&#xff0c;Cache中 保存着CPU刚用过或循环使用的一部…

碳交易机制下考虑需求响应的综合能源系统优化运行程序代码!

本程序参考论文《碳交易机制下考虑需求响应的综合能源系统优化运行》&#xff0c;程序中算例丰富&#xff0c;注释清晰&#xff0c;下面对文章和程序简要介绍。 综合能源系统是实现“双碳”目标的有效途径&#xff0c;为进一步挖掘其需求侧可调节潜力对碳减排的作用&#xff0c…

二维码智慧门牌管理系统升级解决方案:高效运营,信息尽在掌握

文章目录 前言一、升级要点二、方案优势三、应用场景四、客户案例 前言 在这个日新月异的时代&#xff0c;二维码智慧门牌管理系统已经成为了各行各业的标配。为了更好地满足用户需求&#xff0c;提升运营效率&#xff0c;我们推出了全新的升级解决方案。这个方案将让你轻松掌…

可燃气体监测仪|燃气管网监测解决办法

可燃气体监测仪是城市生命线中&#xff0c;燃气监测运行系统的前端监测设备&#xff0c;其主要作用是对燃气管网的安全状况进行实时监测。燃气管道在使用过程中&#xff0c;由于老化、裂纹、锈蚀等问题&#xff0c;容易导致燃气出现泄漏问题&#xff0c;从而引发一系列的安全事…

【C++】类与对象 II 【深入浅出 万字详解】

类与对象 II 一、类的6个默认成员函数二、构造函数前言&#xff1a;构造函数产生的由来 及引入C语言中关于初始化会出现的问题总结&#xff1a;&#xff08;一&#xff09;构造函数的 概念&#xff08;二&#xff09;构造函数的 特性★ 构造函数 和 函数声明 的区分 三、析构函…

初识MongoDB及安装

文章目录 一、MongoDB核心概念1、库2、集合3、文档4、关系总结 二、MongoDB的安装总结 一、MongoDB核心概念 1、库 mongodb中的库就类似于传统关系型数据库中库的概念&#xff0c;用来通过不同库隔离不同应用数据。mongodb中可以建立多个数据库。每一个库都有自己的集合和权限…
最新文章