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 modert_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 modert_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 allowedif ((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 readstruct 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 readif ((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 = 230Hzstruct 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/sif (_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_SPIstruct 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;}}
//#endifresult = _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.mzph.cn/news/148498.shtml

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

相关文章

Linux|僵死进程

1.僵死进程产生的原因或者条件: 什么是僵死进程? 当子进程先于父进程结束,父进程没有获取子进程的退出码,此时子进程变成僵死进程. 简而言之,就是子进程先结束,并且父进程没有获取它的退出码; 那么僵死进程产生的原因或者条件就是:子进程先于父进程结束,并且父进程没有获取…

基于卡尔曼滤波实现行人目标跟踪

目录 1. 作者介绍2. 目标跟踪算法介绍2.1 目标跟踪背景2.2 目标跟踪任务分类2.3 目标跟踪遇到的问题2.4 目标跟踪方法 3. 卡尔曼滤波的目标跟踪算法介绍3.1 所用数据视频说明3.2 卡尔曼滤波3.3 单目标跟踪算法3.3.1 IOU匹配算法3.3.2 卡尔曼滤波的使用方法 3.4 多目标跟踪算法 …

rocketmq 安装dashboard1.0.0 mq消息控制台安装 rocketmq控制台安装 rocketmq-dashboard-1.0.0编译安装

1. 官网&#xff1a; 下载 | RocketMQ 2. dashboard安装包位置&#xff1a; 在连接最下面&#xff0c;点击download.zip即可 3. 需要安装maven, 编译命令&#xff1a; mvn clean install -U -Dmaven.test.skiptrue4. 启动jar: java -jar rocketmq-dashboard-1.0.0.jar &…

在线随机字符串生成工具

具体请前往&#xff1a;在线随机字符串生成器--通过该工具生成动态复杂随机密码,随机字符串等&#xff0c;加密盐等

Leetcode—141.环形链表【简单】

2023每日刷题&#xff08;三十三&#xff09; Leetcode—141.环形链表 快慢指针算法思想 关于快慢指针为什么能检测出环&#xff0c;可以这么思考。 假设存在一个环: 慢指针进入环后&#xff0c;快指针和慢指针之间相距为d&#xff0c;每一次移动&#xff0c;d都会缩小1&…

【项目设计】网络版五子棋游戏

文章目录 一、项目介绍1. 项目简介2. 开发环境3. 核心技术4. 开发阶段 二、环境搭建1. 安装 wget 工具2. 更换 yum 源3. 安装 lrzsz 传输工具4. 安装⾼版本 gcc/g 编译器5. 安装 gdb 调试器6. 安装分布式版本控制工具 git7. 安装 cmake8. 安装 boost 库9. 安装 Jsoncpp 库10. 安…

[AI]ChatGPT4 与 ChatGPT3.5 区别有多大

ChatGPT 3.5 注册已经不需要手机了&#xff0c;直接邮箱认证就可以&#xff0c;这可真算是好消息&#xff0c;坏消息是 ChatGPT 4 还是要收费。 那么 GPT-3.5 与 GPT-4 区别有多大呢&#xff0c;下面简单测试一下。 以从 TDengine 订阅数据为例&#xff0c;TDengine 算是不太小…

Appium自动化测试:通过appium的inspector功能无法启动app的原因

在打开appium-desktop程序&#xff0c;点击inspector功能&#xff0c;填写app的配置信息&#xff0c;启动服务提示如下&#xff1a; 报错信息&#xff1a; An unknown server-side error occurred while processing the command. Original error: Cannot start the cc.knowyo…

专业数据标注公司:景联文科技领航数据标注行业,满足大模型时代新需求

随着大模型的蓬勃发展和相关政策的逐步推进&#xff0c;为数据要素市场化配置的加速推进提供了有力的技术保障和政策支持。数据要素生产力度的不断提升&#xff0c;为数据标注产业带来了迅速发展的契机。 根据国家工信安全发展研究中心测算&#xff0c;2022年中国数据加工环节的…

c# 字符串转换为byte

c# 字符串转换为byte using System.Text; class proj {internal static void Main(string[] args){byte[] anew byte[3];Console.WriteLine("打印a");Console.WriteLine("a的长度{0}",a.Length);foreach (byte b in a){ Console.WriteLine(b); }a Encodi…

linux系统环境下mysql安装和基本命令学习

此篇文章为蓝桥云课--MySQL的学习记录 块引用部分为自己的实验部分&#xff0c;其余部分是课程自带的知识&#xff0c;链接如下&#xff1a; MySQL 基础课程_MySQL - 蓝桥云课 本课程为 SQL 基本语法及 MySQL 基本操作的实验&#xff0c;理论内容较少&#xff0c;动手实践多&am…

muduo源码剖析之TcpServer服务端

简介 TcpServer拥有Acceptor类&#xff0c;新连接到达时new TcpConnection后续客户端和TcpConnection类交互。TcpServer管理连接和启动线程池&#xff0c;用Acceptor接受连接。 服务端封装 - muduo的server端维护了多个tcpconnection 注意TcpServer本身不带Channel&#xff0…

国民技术Cortex-M0系列单片机IAP升级

考虑到设备部署到现场后有可能需要进行软件升级&#xff0c;之前做过PIC系列单片机的升级&#xff0c;现在想做个国民技术N32G031系列Cortex-M0内核的单片机IAP方案。 因为国民技术系列单片机在很多大程度上都模仿了STM32&#xff0c;所以我想其升级方案极有可能差不多。于是在…

视频封面:从视频中提取封面,轻松制作吸引人的视频

在当今的数字时代&#xff0c;视频已成为人们获取信息、娱乐和交流的重要方式。一个吸引人的视频封面往往能抓住眼球&#xff0c;提高点击率和观看率。今天将介绍如何从视频中提取封面&#xff0c;轻松制作吸引人的视频封面。 一、准备素材选择合适的视频片段 首先&#xff0…

ubuntu中用docker部署jenkins,并和码云实现自动化部署

1.部署jenkins docker network create jenkins docker run --name jenkins-docker --rm --detach \--privileged --network jenkins --network-alias docker \--env DOCKER_TLS_CERTDIR/certs \--volume jenkins-docker-certs:/certs/client \--volume jenkins-data:/var/jen…

Java面向对象(高级)-- 单例(Singleton)设计模式

文章目录 一、单例设计模式&#xff08;1&#xff09; 设计模式概述&#xff08;2&#xff09; 何为单例模式&#xff08;3&#xff09; 实现思路&#xff08;4&#xff09; 单例模式的两种实现方式1. 饿汉式2. 懒汉式3. 饿汉式 vs 懒汉式 &#xff08;5&#xff09; 单例模式的…

修完这个 Bug 后,MySQL 性能提升了 300%

最近 MySQL 官方在 8.0.35 上修复了一个 bug&#xff1a; 这个 bug 是由 Mark Callaghan 发现的。Mark 早年在 Google MySQL 团队&#xff0c;后来去了 Meta MySQL&#xff0c;也主导了 RocksDB 的开发。 Mark 在 #109595 的 bug report 给出了非常详细的复现步骤 在官方修复后…

Cross-View Transformers for Real-Time Map-View Semantic Segmentation 论文阅读

论文链接 Cross-View Transformers for Real-Time Map-View Semantic Segmentation 0. Abstract 提出了 Cross-View Transformers &#xff0c;一种基于注意力的高效模型&#xff0c;用于来自多个摄像机的地图视图语义分割使用相机感知的跨视图注意机制隐式学习从单个相机视…

MySQL数据库索引以及使用唯一索引实现幂等性

&#x1f4d1;前言 本文主要是MySQL数据库索引以及使用唯一索引实现幂等性的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是青衿&#x1f947; ☁️博客首页&#xff1a;CSDN主页放风讲故事 &#x1f30…

【LeetCode:2736. 最大和查询 | 贪心 + 二分 + 单调栈】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…