LSM6DSMTR(陀螺仪)

概述

LSM6DSMTR 是一款3轴加速度计3轴角速度计的陀螺仪

LGA-14 封装 超小体积

image-20250721194201672

电路设计

采用I2C通信,基本上外部电路只用I2C的上拉和电源滤波即可

1号脚接3V3时 I2C地址为:0xD6 (直接或即可无需右移)

2/3号脚可以接其他I2C器件 如磁力计

两个可编程中断 根据情况使用

image-20250721195825908

CubeMX

两个GPIO 开漏上拉最高等级输出

image-20250721205209338

根据需要设定外部中断
设为上升沿 浮空

image-20250721205306712

I2C

这里使用软件I2C 之前封装过集成库 这里不多介绍了

这里重新封装下

头文件和宏定义

#include "HZ_I2C.h"

#define IMU_IIC_Soft
// #define IMU_LSM6DS_IIC_Hard

#ifdef IMU_IIC_Soft
#define IMU_SDA_GPIOx GPIOA
#define IMU_SDA_Pin GPIO_PIN_4
#define IMU_SCL_GPIOx GPIOA
#define IMU_SCL_Pin GPIO_PIN_5
#define IMU_IIC_Delay 0x1
#endif // IMU_IIC_Soft

#define IMU_LSM6DS_Addr 0xD6

句柄定义

#ifdef IMU_IIC_Soft
HZ_I2C_typedef IMU_I2C_h;
#endif // IMU_IIC_Soft

初始化I2C

/**
 * @brief 初始化I2C
 * @author HZ12138
 * @date 2025-07-15 17:50:23
 */
void IMU_I2C_Init(void)
{
#ifdef IMU_IIC_Soft
    // 使用软件IIC 绑定地址
    // 绑定SDA和SCL到IIC句柄
    I2C_Init_Channel(&IMU_I2C_h,
                     IMU_SDA_GPIOx, IMU_SDA_Pin,
                     IMU_SCL_GPIOx, IMU_SCL_Pin,
                     IMU_IIC_Delay); // addr D6

#endif // IMU_IIC_Soft
}

读寄存器

/**
 * @brief 读8bits寄存器
 * @param reg 寄存器地址
 * @return 读取的数据
 * @author HZ12138
 * @date 2025-07-15 17:49:51
 */
uint8_t IMU_LSM6DS_I2C_Read_Reg8(uint8_t reg)
{
#ifdef IMU_IIC_Soft
    return I2C_Read_Reg8(IMU_I2C_h, IMU_LSM6DS_Addr, reg);
#endif // IMU_IIC_Soft
}

写寄存器

/**
 * @brief 写8bits寄存器
 * @param reg:寄存器地址 8bit
 * @param data:数据
 * @return 状态 0成功 其他失败
 * @author HZ12138
 * @date 2025-07-15 19:22:28
 */
uint8_t IMU_LSM6DS_I2C_Write_Reg8(uint8_t reg, uint8_t data)
{
#ifdef IMU_IIC_Soft
    return I2C_Write_Reg8(IMU_I2C_h, IMU_LSM6DS_Addr, reg, data);
#endif // IMU_IIC_Soft
}

连续读寄存器

/**
 * @brief I2C连续读寄存器
 * @param reg 寄存器地址
 * @param len 长度
 * @param buf 缓冲区地址
 * @author HZ12138
 * @date 2025-07-16 17:19:58
 */
uint8_t IMU_LSM6DS_I2C_Read_Len_Reg8(uint8_t reg, uint8_t len, uint8_t *buf)
{
#ifdef IMU_IIC_Soft
    return I2C_Read_Len_Reg8(IMU_I2C_h, IMU_LSM6DS_Addr, reg, len, buf);
#endif // IMU_IIC_Soft
}

延迟函数(为了兼容rtos这个函数可以外部重定义)

/**
 * @brief IMU使用的延迟 可以外部重定义
 * @param time 时间 ms
 * @author HZ12138
 * @date 2025-07-15 19:56:18
 */
__weak void IMU_Delay(uint32_t time)
{
    HAL_Delay(time);
}

初始化

复位

本函数有两步操作
首先是复位,之后进入高性能模式

需要操作这个寄存器

bit7 写1 内存复位

bit0 写1 软件复位

image-20250721212036792

  1. bit7 写1 复位
  2. 延迟15ms以上
  3. bit0 写1 软件复位
  4. 延迟15ms以上
#define IMU_LSM6DS_REG_CTRL3_C 0x12         // 控制寄存器3

/**
 * @brief 软件复位LSM6DS
 * @author HZ12138
 * @date 2025-07-15 19:23:26
 */
void IMU_LSM6DS_ReStart(void)
{
    uint8_t temp;

    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL3_C, 0x80); // 复位
    IMU_Delay(20);

    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL3_C); // 读取控制寄存器3
    // SW_RESET 写1
    temp |= 0x01;
    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL3_C, temp);

    IMU_Delay(20);
}

设置BDU

块数据更新

数据会将高8bit和低8bit分别存在不同寄存器

打开这个选项会让这两数据同时更新

需要操作这个寄存器

bit6 写1

image-20250721212036792

  1. 读取寄存器
  2. 写入数据
  3. 再次读取验证
#define IMU_LSM6DS_REG_CTRL3_C 0x12         // 控制寄存器3

/**
 * @brief 设置BDU(块数据更新)
 * @param flag 0禁用 1启用
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-15 20:41:47
 */
int IMU_LSM6DS_SetBDU(uint8_t flag)
{
    uint8_t temp;

    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL3_C); // 读取控制寄存器3

    // 写入寄存器
    if (flag)
        temp |= 0x40; // bit 6 写1
    else
        temp &= 0xBF; // bit 6 清零
    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL3_C, temp);

    // 读取验证是否成功
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL3_C);
    if (temp & 0x40)
    {
        if (!flag) // 读取的是1 期望的是0
            return -1;
    }
    else
    {
        if (flag) // 读取的是0 期望的是1
            return -1;
    }
    return 0;
}

设置加速度计(a)速率

设置加速度计的采样速率

需要修改以下寄存器的bit[7:4]

未标题-1

#define IMU_LSM6DS_REG_CTRL1_XL 0x10        // 控制寄存器1

/* 加速度/角速度 速率选项 */
#define IMU_LSM6DS_w_a_RATE_PowerDown 0x00
#define IMU_LSM6DS_w_a_RATE_1Hz6 0xB0
#define IMU_LSM6DS_w_a_RATE_12Hz5 0x10
#define IMU_LSM6DS_w_a_RATE_26Hz 0x20
#define IMU_LSM6DS_w_a_RATE_52Hz6 0x30
#define IMU_LSM6DS_w_a_RATE_104Hz6 0x40
#define IMU_LSM6DS_w_a_RATE_208Hz6 0x50
#define IMU_LSM6DS_w_a_RATE_416Hz6 0x60
#define IMU_LSM6DS_w_a_RATE_833Hz6 0x70
#define IMU_LSM6DS_w_a_RATE_1KHz66 0x80
#define IMU_LSM6DS_w_a_RATE_3KHz33 0x90
#define IMU_LSM6DS_w_a_RATE_6KHz66 0xA0
/**
 * @brief  设置加速度(a)速率
 * @param opt 设置选项(IMU_LSM6DS_w_a_RATE_PowerDown/...)
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-16 09:47:25
 */
int IMU_LSM6DS_Set_a_Rate(uint8_t opt)
{
    uint8_t temp;
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL1_XL); // 读取控制寄存器1

    // 高4位清零后 写入OPT数据
    temp &= 0x0f;
    temp |= opt;
    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL1_XL, temp); // 写入数据

    // 读取后检测 是否正确
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL1_XL);
    if ((temp & 0xf0) != opt)
        return -1;
    return 0;
}

设置角速度计(w)速率

设置加速度计的采样速率

需要修改以下寄存器的bit[7:4]

未标题-1

#define IMU_LSM6DS_REG_CTRL2_G 0x11         // 控制寄存器2

/* 加速度/角速度 速率选项 */
#define IMU_LSM6DS_w_a_RATE_PowerDown 0x00
#define IMU_LSM6DS_w_a_RATE_1Hz6 0xB0
#define IMU_LSM6DS_w_a_RATE_12Hz5 0x10
#define IMU_LSM6DS_w_a_RATE_26Hz 0x20
#define IMU_LSM6DS_w_a_RATE_52Hz6 0x30
#define IMU_LSM6DS_w_a_RATE_104Hz6 0x40
#define IMU_LSM6DS_w_a_RATE_208Hz6 0x50
#define IMU_LSM6DS_w_a_RATE_416Hz6 0x60
#define IMU_LSM6DS_w_a_RATE_833Hz6 0x70
#define IMU_LSM6DS_w_a_RATE_1KHz66 0x80
#define IMU_LSM6DS_w_a_RATE_3KHz33 0x90
#define IMU_LSM6DS_w_a_RATE_6KHz66 0xA0
/**
 * @brief  设置角速度(w)速率
 * @param opt 设置选项(IMU_LSM6DS_w_a_RATE_PowerDown/...)
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-16 10:15:05
 */
int IMU_LSM6DS_Set_w_rate(uint8_t opt)
{
    uint8_t temp;
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL2_G); // 读取控制寄存器2

    // 高4位清零后 写入OPT数据
    temp &= 0x0f;
    temp |= opt;

    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL2_G, temp); // 写入数据

    // 读取后检测 是否正确
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL2_G);
    if ((temp & 0xf0) != opt)
        return -1;
    return 0;
}

设置加速度计(a)量程

修改以下寄存器的bit[3:2]

未标题-1

#define IMU_LSM6DS_REG_CTRL1_XL 0x10        // 控制寄存器1

/*加速度 量程选项*/
#define IMU_LSM6DS_a_Full_2g 0x00
#define IMU_LSM6DS_a_Full_4g 0x08
#define IMU_LSM6DS_a_Full_8g 0x0C
#define IMU_LSM6DS_a_Full_16g 0x04
/**
 * @brief 设置加速度(a)量程
 * @param opt 设置选项(IMU_LSM6DS_a_Full_2g/...)
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-16 10:40:04
 */
int IMU_LSM6DS_Set_a_Full(uint8_t opt)
{
    uint8_t temp;
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL1_XL); // 读取控制寄存器1

    // bit 2 3清零后写入opt
    temp &= 0xF3;
    temp |= opt;

    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL1_XL, temp); // 写入数据

    // 读取后检测 是否正确
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL1_XL);
    if ((temp & 0x0C) != opt)
        return -1;

    IMU_LSM6DS_a_Full = opt; // 保存参数

    return 0;
}

注意这里要把参数保存下来以便后面计算数据时使用

设置角速度计(w)量程

修改以下寄存器的bit[3:1]

未标题-1

#define IMU_LSM6DS_REG_CTRL2_G 0x11         // 控制寄存器2

/*角速度 量程选项*/
#define IMU_LSM6DS_w_Full_125dps 0x02
#define IMU_LSM6DS_w_Full_245dps 0x00
#define IMU_LSM6DS_w_Full_500dps 0x04
#define IMU_LSM6DS_w_Full_1000dps 0x08
#define IMU_LSM6DS_w_Full_2000dps 0x0C
/**
 * @brief 设置角速度(w)量程
 * @param opt 设置选项(IMU_LSM6DS_w_Full_125dps/...)
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-16 10:57:25
 */
int IMU_LSM6DS_Set_w_Full(uint8_t opt)
{
    uint8_t temp;
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL2_G); // 读取控制寄存器2

    // bit 1 2 3 清零后写入opt
    temp &= 0xf1;
    temp |= opt;
    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL2_G, temp); // 写入数据

    // 读取后检测 是否正确
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL2_G);
    if ((temp & 0x0E) != opt)
        return -1;

    IMU_LSM6DS_w_Full = opt; // 保存参数

    return 0;
}

注意这里要把参数保存下来以便后面计算数据时使用

设置加速度计带宽

修改以下寄存器的bit0

建议采样率>1.67KHz时选 1.5KHz 其余选400Hz

未标题-1

#define IMU_LSM6DS_REG_CTRL1_XL 0x10        // 控制寄存器1

/* 加速度带宽 选项*/
#define IMU_LSM6DS_a_BW_1KHz5 0x00
#define IMU_LSM6DS_a_BW_400Hz 0x01
/**
 * @brief 设置加速度计带宽 建议采样率>1.67KHz时选 1.5KHz 其余选400Hz
 * @param opt 设置选项(IMU_LSM6DS_a_BW_1KHz5/...)
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-16 12:58:04
 */
int IMU_LSM6DS_Set_a_BW(uint8_t opt)
{
    uint8_t temp;
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL1_XL); // 读取控制寄存器1

    // bit 0清零后写入opt
    temp &= 0xFE;
    temp |= opt;

    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL1_XL, temp); // 写入数据

    // 读取后检测 是否正确
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL1_XL);
    if ((temp & 0x01) != opt)
        return -1;
    return 0;
}

设置加速度计低通滤波

设置以下寄存器以设置加速度计低通滤波

image-20250721223800103

#define IMU_LSM6DS_REG_CTRL8_XL 0x17        // 控制寄存器8

/* 加速度计低通滤波 选项 */
#define IMU_LSM6DS_a_LOW_PASS_ODR_9 0xC8
#define IMU_LSM6DS_a_LOW_PASS_ODR_50 0x88
#define IMU_LSM6DS_a_LOW_PASS_ODR_100 0xA8
#define IMU_LSM6DS_a_LOW_PASS_ODR_400 0xE8
/**
 * @brief 设置加速度计低通滤波
 * @param opt 设置选项(IMU_LSM6DS_a_LOW_PASS_ODR_9/...)
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-16 13:47:23
 */
int IMU_LSM6DS_Set_a_LowPass(uint8_t opt)
{
    uint8_t temp;

    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL8_XL, opt); // 写入数据

    // 读取后检测 是否正确
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL8_XL);
    if (temp != opt)
        return -1;
    return 0;
}

设置角速度计高通滤波

设置以下寄存器

bit6 写1启动角速度计高通滤波

bit[5:4] 设置截止频率

image-20250721224235607

#define IMU_LSM6DS_REG_CTRL7_G 0x16         // 控制寄存器7

/*角速度计 高通滤波器 选项 */
#define IMU_LSM6DS_w_HP_DISABLE 0x00
#define IMU_LSM6DS_w_HP_ENABLE 0x40
/*角速度计 高通滤波器截止频率 选项 */
#define IMU_LSM6DS_w_HPM_16MHz 0x00
#define IMU_LSM6DS_w_HPM_65MHz 0x10
#define IMU_LSM6DS_w_HPM_260MHz 0x20
#define IMU_LSM6DS_w_HPM_1Hz04 0x30
/**
 * @brief 设置角速度计高通滤波
 * @param en 启用/禁用 (IMU_LSM6DS_w_HP_ENABLE/IMU_LSM6DS_w_HP_DISABLE)
 * @param opt 设置选项(IMU_LSM6DS_w_HPM_16MHz/...)
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-16 15:34:18
 */
int IMU_LSM6DS_Set_w_HighPass(uint8_t en, uint8_t opt)
{
    uint8_t temp;
    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL7_G, en | opt); // 写入数据

    // 读取后检测 是否正确
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL7_G);
    if (temp != (en | opt))
        return -1;
    return 0;
}

设置角速度计低通滤波带宽

设置bit[1:0]来设置低通滤波带宽

image-20250721225309427

#define IMU_LSM6DS_REG_CTRL6_C 0x15         // 控制寄存器6

/*角速度计 低通滤波带宽 选项 */
#define IMU_LSM6DS_w_CTRL6_C_FTYPE_1 0x00
#define IMU_LSM6DS_w_CTRL6_C_FTYPE_2 0x01
#define IMU_LSM6DS_w_CTRL6_C_FTYPE_3 0x02
#define IMU_LSM6DS_w_CTRL6_C_FTYPE_4 0x03
/**
 * @brief 设置角速度计低通滤波带宽
 * @param en 0关 1开
 * @param opt 设置选项(IMU_LSM6DS_w_CTRL6_C_FTYPE_1/...)
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-16 15:53:05
 */
int IMU_LSM6DS_Set_w_LowPassBW(uint8_t en, uint8_t opt)
{
    uint8_t temp;
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL6_C); // 读取控制寄存器6

    // 清除后2位 写入参数
    temp &= 0xFC;
    temp |= opt;
    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL6_C, temp); // 写入数据

    // 读取后检测 是否正确
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL6_C);
    if ((temp & 0x03) != opt)
        return -1;

    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL4_C); // 读取控制寄存器4

    // 清除 bit 1  写入参数
    temp &= 0xFD;
    if (en)
        temp |= 0x02;
    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL4_C, temp); // 写入数据

    // 读取后检测 是否正确
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL4_C);

    if (temp & 0x02)
    {
        if (!en) // 读取的是1 期望的是0
            return -2;
    }
    else
    {
        if (en) // 读取的是0 期望的是1
            return -2;
    }
    return 0;
}

进入总线直通模式

直通功能示意图

image-20250721231018103

bit2 写入1启用

image-20250721231417882

#define IMU_LSM6DS_REG_MASTER_CONFIG 0x1A   // 主机配置寄存器
/**
 * @brief 进入总线直通模式
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-20 18:41:30
 */
int IMU_LSM6DS_Enter_Pass_mood(void)
{
    uint8_t temp;
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_MASTER_CONFIG); // 读取主机配置寄存器

    // bit 2 置1
    temp |= 0x04;

    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_MASTER_CONFIG, temp); // 写入数据

    // 读取后检测 是否正确
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_MASTER_CONFIG);
    if (temp & 0x04)
        return 0;

    return -1;
}

设置中断1

中断设置为脉冲模式,当加速度计和角速度计数据就位后触发中断

以下寄存器的bit[1:0]=11b 设置加速度计和角速度计数据就位后触发中断

image-20250721231904349

以下寄存器bit7写1 启用脉冲模式

image-20250721232125361

#define IMU_LSM6DS_REG_INT1_CTRL 0x0D       // IN1 控制寄存器
#define IMU_LSM6DS_REG_DRDY_PULSE_CFG 0x0B  // 数据就绪寄存器
/**
 * @brief 设置中断1
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-21 22:27:32
 */
int IMU_LSM6DS_Set_Int1(void)
{
    uint8_t temp;

    // 设置数据a,w更新中断
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_INT1_CTRL); // 读取中断控制寄存器
    temp |= 0x03;
    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_INT1_CTRL, temp); // 写入数据

    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_INT1_CTRL);
    if ((temp & 0x03) != 0x03)
        return -1;

    // 脉冲模式
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_DRDY_PULSE_CFG);
    temp |= 0x80;

    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_DRDY_PULSE_CFG, temp); // 写入数据
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_DRDY_PULSE_CFG);

    if (!(temp & 0x80))
        return -1;

    return 0;
}

初始化

/**
 * @brief LSM6DS 初始化
 * @return 0成功 <0失败
 * @exception -1 ID错误
 * @author HZ12138
 * @date 2025-07-15 17:50:41
 */
int IMU_LSM6DS_Init(void)
{
    IMU_I2C_Init(); // 初始化IIC

    if (IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_ID) != 0x6A) // 检测ID
        return -1;

    IMU_LSM6DS_ReStart(); // 软复位

    if (IMU_LSM6DS_SetBDU(1)) // 设置BDU
        return -2;
    if (IMU_LSM6DS_Set_a_Rate(IMU_LSM6DS_w_a_RATE_1KHz66)) // 设置加速度计速率
        return -3;
    if (IMU_LSM6DS_Set_w_rate(IMU_LSM6DS_w_a_RATE_1KHz66)) // 设置角速度计速率
        return -4;
    if (IMU_LSM6DS_Set_a_Full(IMU_LSM6DS_a_Full_8g)) // 设置加速度计量程
        return -5;
    if (IMU_LSM6DS_Set_w_Full(IMU_LSM6DS_w_Full_1000dps)) // 设置角速度计量程
        return -6;
    if (IMU_LSM6DS_Set_a_BW(IMU_LSM6DS_a_BW_400Hz)) // 设置加速度计带宽
        return -7;
    if (IMU_LSM6DS_Set_a_LowPass(IMU_LSM6DS_a_LOW_PASS_ODR_50)) // 设置加速度计低通滤波
        return -8;
    if (IMU_LSM6DS_Set_w_HighPass(IMU_LSM6DS_w_HP_ENABLE, IMU_LSM6DS_w_HPM_260MHz)) // 设置角速度计高通滤波
        return -9;
    if (IMU_LSM6DS_Set_w_LowPassBW(1, IMU_LSM6DS_w_CTRL6_C_FTYPE_1)) // 设置角速度计低通滤波带宽
        return -10;
    if (IMU_LSM6DS_Enter_Pass_mood()) // 进入总线直通模式
        return -11;
    if (IMU_LSM6DS_Set_Int1()) // 设置Int1
        return -12;
    return 0;
}

获取数据状态

读取以下寄存器的bit[2:0] 分别获取温度,角速度,加速度的数据状态

image-20250721232419820

#define IMU_LSM6DS_REG_STATUS 0x1E          // 数据状态寄存器
/**
 * @brief 获取数据状态(加速度a)
 * @return 0 已准备完成 <0 未完成w
 * @author HZ12138
 * @date 2025-07-16 16:38:08
 */
int8_t IMU_LSM6DS_GetState_a(void)
{
    uint8_t temp;
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_STATUS);

    if (temp & 0x01)
        return 0;

    return -1;
}
/**
 * @brief 获取数据状态(角速度w)
 * @return 0 已准备完成 <0 未完成
 * @author HZ12138
 * @date 2025-07-16 16:41:34
 */
int8_t IMU_LSM6DS_GetState_w(void)
{
    uint8_t temp;
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_STATUS);

    if (temp & 0x02)
        return 0;

    return -1;
}
/**
 * @brief 获取数据状态(温度T)
 * @return 0 已准备完成 <0 未完成
 * @author HZ12138
 * @date 2025-07-16 16:41:56
 */
int8_t IMU_LSM6DS_GetState_t(void)
{
    uint8_t temp;
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_STATUS);

    if (temp & 0x04)
        return 0;

    return -1;
}

获取数据

加速度

x/y/z 的高8bit和低8bit 存在以0x28开始的6个寄存器中

image-20250721233128368

image-20250721233152807

拼接数据后根据量程乘上系数即可

image-20250721233303336


/**
 * @brief 获取加速度(a)
 * @param ax x方向加速度(单位mg g是重力加速度)
 * @param ay y方向加速度(单位mg g是重力加速度)
 * @param az z方向加速度(单位mg g是重力加速度)
 * @author HZ12138
 * @date 2025-07-16 21:30:13
 */
int8_t IMU_LSM6DS_Get_a(float *ax, float *ay, float *az)
{

    uint8_t buf[6];
    int16_t acc[3];

    IMU_LSM6DS_I2C_Read_Len_Reg8(0x28, 6, buf);

    acc[0] = buf[1] << 8 | buf[0];
    acc[1] = buf[3] << 8 | buf[2];
    acc[2] = buf[5] << 8 | buf[4];

    switch (IMU_LSM6DS_a_Full)
    {
    case IMU_LSM6DS_a_Full_2g:
        *ax = ((float)acc[0] * 0.061f);
        *ay = ((float)acc[1] * 0.061f);
        *az = ((float)acc[2] * 0.061f);
        break;
    case IMU_LSM6DS_a_Full_4g:
        *ax = ((float)acc[0] * 0.122f);
        *ay = ((float)acc[1] * 0.122f);
        *az = ((float)acc[2] * 0.122f);
        break;
    case IMU_LSM6DS_a_Full_8g:
        *ax = ((float)acc[0] * 0.244f);
        *ay = ((float)acc[1] * 0.244f);
        *az = ((float)acc[2] * 0.244f);
        break;
    case IMU_LSM6DS_a_Full_16g:
        *ax = ((float)acc[0] * 0.488f);
        *ay = ((float)acc[1] * 0.488f);
        *az = ((float)acc[2] * 0.488f);
        break;
    default:
        return -1;
    }
    return 0;
}

角速度

x/y/z 的高8bit和低8bit 存在以0x22开始的6个寄存器中

image-20250721233415009

image-20250721233424088

image-20250721233432357

根据量程乘上系数即可

image-20250721233511465

/**
 * @brief 获取角速度(w)
 * @param wx x方向角速度(mdps 毫度每秒)
 * @param wy y方向角速度(mdps 毫度每秒)
 * @param wz z方向角速度(mdps 毫度每秒)
 * @return 0 成功 <0失败
 * @author HZ12138
 * @date 2025-07-17 09:43:45
 */
int8_t IMU_LSM6DS_Get_w(float *wx, float *wy, float *wz)
{

    uint8_t buf[6];
    int16_t gry[3];
    IMU_LSM6DS_I2C_Read_Len_Reg8(0x22, 6, buf);

    gry[0] = buf[1] << 8 | buf[0];
    gry[1] = buf[3] << 8 | buf[2];
    gry[2] = buf[5] << 8 | buf[4];

    switch (IMU_LSM6DS_w_Full)
    {
    case IMU_LSM6DS_w_Full_245dps:
        *wx = ((float)gry[0] * 8.750f);
        *wy = ((float)gry[1] * 8.750f);
        *wz = ((float)gry[2] * 8.750f);
        break;
    case IMU_LSM6DS_w_Full_500dps:
        *wx = ((float)gry[0] * 17.50f);
        *wy = ((float)gry[1] * 17.50f);
        *wz = ((float)gry[2] * 17.50f);
        break;
    case IMU_LSM6DS_w_Full_1000dps:
        *wx = ((float)gry[0] * 35.00f);
        *wy = ((float)gry[1] * 35.00f);
        *wz = ((float)gry[2] * 35.00f);
        break;
    case IMU_LSM6DS_w_Full_2000dps:
        *wx = ((float)gry[0] * 70.00f);
        *wy = ((float)gry[1] * 70.00f);
        *wz = ((float)gry[2] * 70.00f);
        break;
    default:
        return -1;
    }
    return 0;
}

温度

温度存在 0x20和0x21里

image-20250721233550133

经过偏移(没找到为啥,根据例程反推的)

/**
 * @brief 获取温度
 * @return 温度(℃)
 * @author HZ12138
 * @date 2025-07-17 09:50:08
 */
float IMU_LSM6DS_Get_t(void)
{
    uint8_t buf[2];
    int16_t temp;

    IMU_LSM6DS_I2C_Read_Len_Reg8(0x20, 2, buf);

    temp = buf[1] << 8 | buf[0];

    return (((float)temp / 256.0f) + 25.0f);
}

LIS2MDLTR(磁力计)

概述

LIS2MDLTR 是一款地磁计

LGA-12 超小封装

image-20250722104928105

电路设计

将LIS2MDLTR的I2C口接到LSM6DSMTR 的 SDX/SCX 上

LSM6DSMTR 启用总线直通

I2C地址为:0x3C (直接 或 即可无需右移)

image-20250722105214441

CubeMX

两个GPIO 开漏上拉最高等级输出

image-20250721205209338

根据需要设定外部中断
设为上升沿 浮空

image-20250721205306712

I2C

这里使用软件I2C 之前封装过集成库 这里不多介绍了

这里重新封装下

头文件和宏定义

#include "HZ_I2C.h"

#define IMU_IIC_Soft
// #define IMU_LSM6DS_IIC_Hard

#ifdef IMU_IIC_Soft
#define IMU_SDA_GPIOx GPIOA
#define IMU_SDA_Pin GPIO_PIN_4
#define IMU_SCL_GPIOx GPIOA
#define IMU_SCL_Pin GPIO_PIN_5
#define IMU_IIC_Delay 0x1
#endif // IMU_IIC_Soft

#define IMU_LIS2MD_Addr 0x3C

句柄定义

#ifdef IMU_IIC_Soft
HZ_I2C_typedef IMU_I2C_h;
#endif // IMU_IIC_Soft

初始化I2C

/**
 * @brief 初始化I2C
 * @author HZ12138
 * @date 2025-07-15 17:50:23
 */
void IMU_I2C_Init(void)
{
#ifdef IMU_IIC_Soft
    // 使用软件IIC 绑定地址
    // 绑定SDA和SCL到IIC句柄
    I2C_Init_Channel(&IMU_I2C_h,
                     IMU_SDA_GPIOx, IMU_SDA_Pin,
                     IMU_SCL_GPIOx, IMU_SCL_Pin,
                     IMU_IIC_Delay); // addr D6

#endif // IMU_IIC_Soft
}

读寄存器

/**
 * @brief 读8bits寄存器
 * @param reg 寄存器地址
 * @return 读取的数据
 * @author HZ12138
 * @date 2025-07-15 17:49:51
 */
uint8_t IMU_LIS2MD_I2C_Read_Reg8(uint8_t reg)
{
#ifdef IMU_IIC_Soft
    return I2C_Read_Reg8(IMU_I2C_h, IMU_LIS2MD_Addr, reg);
#endif // IMU_IIC_Soft
}

写寄存器

/**
 * @brief 写8bits寄存器
 * @param reg:寄存器地址 8bit
 * @param data:数据
 * @return 状态 0成功 其他失败
 * @author HZ12138
 * @date 2025-07-15 19:22:28
 */
uint8_t IMU_LIS2MD_I2C_Write_Reg8(uint8_t reg, uint8_t data)
{
#ifdef IMU_IIC_Soft
    return I2C_Write_Reg8(IMU_I2C_h, IMU_LIS2MD_Addr, reg, data);
#endif // IMU_IIC_Soft
}

连续读寄存器

/**
 * @brief I2C连续读寄存器
 * @param reg 寄存器地址
 * @param len 长度
 * @param buf 缓冲区地址
 * @author HZ12138
 * @date 2025-07-16 17:19:58
 */
uint8_t IMU_LIS2MD_I2C_Read_Len_Reg8(uint8_t reg, uint8_t len, uint8_t *buf)
{
#ifdef IMU_IIC_Soft
    return I2C_Read_Len_Reg8(IMU_I2C_h, IMU_LIS2MD_Addr, reg, len, buf);
#endif // IMU_IIC_Soft
}

延迟函数(为了兼容rtos这个函数可以外部重定义)

/**
 * @brief IMU使用的延迟 可以外部重定义
 * @param time 时间 ms
 * @author HZ12138
 * @date 2025-07-15 19:56:18
 */
__weak void IMU_Delay(uint32_t time)
{
    HAL_Delay(time);
}

初始化

复位

设置0x60寄存器

bit5 写1 复位

复位后延迟至少15ms

image-20250722113642127

#define IMU_LIS2MD_REG_CFG_A 0x60  // 控制寄存器A
/**
 * @brief LIS2MD复位
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-18 13:58:46
 */
int IMU_LIS2MD_Restart(void)
{
    uint8_t temp;
    temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A);

    temp |= 0x20;
    if (IMU_LIS2MD_I2C_Write_Reg8(IMU_LIS2MD_REG_CFG_A, temp))
        return -1;
    IMU_Delay(20);
    return 0;
}

设置BDU

块数据更新

数据会将高8bit和低8bit分别存在不同寄存器

打开这个选项会让这两数据同时更新

设置0x62寄存器

bit4 写1 启动

image-20250722114841342

#define IMU_LIS2MD_REG_CFG_C 0x62  // 控制寄存器C
/**
 * @brief 设置BDU(块数据更新)
 * @param flag 0禁用 1启用
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-18 14:15:28
 */
int IMU_LIS2MD_Set_BDU(uint8_t flag)
{
    uint8_t temp;

    temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_C); // 读取控制寄存器C

    // 写入寄存器
    if (flag)
        temp |= 0x10; // bit 4 写1
    else
        temp &= 0xEF; // bit 4 清零
    IMU_LIS2MD_I2C_Write_Reg8(IMU_LIS2MD_REG_CFG_C, temp);

    // 读取验证是否成功
    temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_C);
    if (temp & 0x10)
    {
        if (!flag) // 读取的是1 期望的是0
            return -1;
    }
    else
    {
        if (flag) // 读取的是0 期望的是1
            return -1;
    }
    return 0;
}

读取ID

ID为 0x40

读取0x4F寄存器获取ID

#define IMU_LIS2MD_REG_ID 0x4F // ID寄存器
/**
 * @brief 读取ID
 * @return ID
 * @author HZ12138
 * @date 2025-07-18 13:35:33
 */
uint8_t IMU_LIS2MD_Read_ID(void)
{
    return IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_ID);
}

设置输出速率

设置0x60寄存器

设置bit[3:2]设置输出速率

image-20250722113642127

#define IMU_LIS2MD_REG_CFG_A 0x60  // 控制寄存器A

/* 数据输出 选项 */
#define IMU_LIS2MD_ODR_10Hz 0x00
#define IMU_LIS2MD_ODR_20Hz 0x04
#define IMU_LIS2MD_ODR_50Hz 0x08
#define IMU_LIS2MD_ODR_100Hz 0x0C
/**
 * @brief 设置输出速率
 * @param opt 选项( IMU_LIS2MD_ODR_10Hz /...)
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-18 15:35:04
 */
int IMU_LIS2MD_Set_ODR(uint8_t opt)
{
    uint8_t temp;
    temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A);

    temp |= opt;
    IMU_LIS2MD_I2C_Write_Reg8(IMU_LIS2MD_REG_CFG_A, temp);

    temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A);

    if ((temp & 0x0C) != opt)
        return -1;
    return 0;
}

设置偏移消除

0x61寄存器

bit1 写1启动

image-20250722115907502

#define IMU_LIS2MD_REG_CFG_B 0x61  // 控制寄存器B
/**
 * @brief 设置偏移消除
 * @param flag 0禁用 1启用
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-18 16:39:28
 */
int IMU_LIS2MD_Set_Offset_CANC(uint8_t flag)
{
    uint8_t temp;

    temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_B); // 读取控制寄存器B

    // 写入寄存器
    if (flag)
        temp |= 0x02; // bit 1 写1
    else
        temp &= 0xFD; // bit 1 清零
    IMU_LIS2MD_I2C_Write_Reg8(IMU_LIS2MD_REG_CFG_B, temp);

    // 读取验证是否成功
    temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_B);
    if (temp & 0x02)
    {
        if (!flag) // 读取的是1 期望的是0
            return -1;
    }
    else
    {
        if (flag) // 读取的是0 期望的是1
            return -1;
    }
    return 0;
}

设置温度补偿

设置0x60寄存器

bit7 写1 启动

image-20250722113642127

#define IMU_LIS2MD_REG_CFG_A 0x60  // 控制寄存器A
/**
 * @brief 设置温度补偿
 * @param flag 0禁用 1启用
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-18 16:45:30
 */
int IMU_LIS2MD_Set_TempComp(uint8_t flag)
{
    uint8_t temp;

    temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A); // 读取控制寄存器A

    // 写入寄存器
    if (flag)
        temp |= 0x80; // bit 1 写1
    else
        temp &= 0x7F; // bit 1 清零
    IMU_LIS2MD_I2C_Write_Reg8(IMU_LIS2MD_REG_CFG_A, temp);

    // 读取验证是否成功
    temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A);
    if (temp & 0x80)
    {
        if (!flag) // 读取的是1 期望的是0
            return -1;
    }
    else
    {
        if (flag) // 读取的是0 期望的是1
            return -1;
    }
    return 0;
}

设置输出模式

设置0x60寄存器

bit[1:0]设置

image-20250722113642127

#define IMU_LIS2MD_REG_CFG_A 0x60  // 控制寄存器A

/* 模式设置 选项 */
#define IMU_LIS2MD_MODE_Idle 0x11
#define IMU_LIS2MD_MODE_Single 0x01
#define IMU_LIS2MD_MODE_Continuous 0x00
/**
 * @brief 设置模式
 * @param opt 选项(IMU_LIS2MD_MODE_Continuous/...)
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-18 17:10:08
 */
int IMU_LIS2MD_Set_Mode(uint8_t opt)
{
    uint8_t temp;

    temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A); // 读取控制寄存器A

    temp &= 0xFC;
    temp |= opt;

    IMU_LIS2MD_I2C_Write_Reg8(IMU_LIS2MD_REG_CFG_A, temp);

    // 读取验证是否成功
    temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A);
    if ((temp & 0x03) != opt)
        return -1;
    return 0;
}

初始化

/**
 * @brief 初始化LIS2MD
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-18 13:32:30
 */
int IMU_LIS2MD_Init(void)
{

    if (IMU_LIS2MD_Read_ID() != 0x40) // 验证ID
        return -1;
    if (IMU_LIS2MD_Restart() != 0) // 复位
        return -2;
    if (IMU_LIS2MD_Set_BDU(1) != 0) // 设置块数据更新
        return -3;
    if (IMU_LIS2MD_Set_ODR(IMU_LIS2MD_ODR_50Hz) != 0) // 设置数据更新速率
        return -4;
    if (IMU_LIS2MD_Set_Offset_CANC(1) != 0) // 设置偏移消除
        return -5;
    if (IMU_LIS2MD_Set_TempComp(1) != 0) // 设置温度补偿
        return -6;
    HAL_Delay(10);
    if (IMU_LIS2MD_Set_Mode(IMU_LIS2MD_MODE_Continuous) != 0) // 启动连续模式
        return -7;
    return 0;
}

获取数据状态

读取0x67寄存器

bit3 为1时代表数据准备完成

image-20250722121707852

#define IMU_LIS2MD_REG_STATUS 0x67 // 状态寄存器
/**
 * @brief 获取数据状态
 * @return 0 没有准备好 1 准备完成
 * @author HZ12138
 * @date 2025-07-18 21:01:46
 */
uint8_t IMU_LIS2MD_Get_State(void)
{
    uint8_t temp;

    temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_STATUS); // 读取状态寄存器

    if (temp & 0x08)
        return 1;
    return 0;
}

获取磁场数据

x/y/z 的高8bit和低8bit 存在以0x68开始的6个寄存器中

image-20250722121926923

image-20250722121947115

image-20250722121956683

/**
 * @brief 获取磁场数据 单位 mG(毫高斯)
 * @param mx x方向磁场
 * @param my y方向磁场
 * @param mz z方向磁场
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-18 21:01:44
 */
int IMU_LIS2MD_Get_Magnetic(float *mx, float *my, float *mz)
{
    uint8_t buf[6];
    int16_t temp_mx, temp_my, temp_mz;

    if (IMU_LIS2MD_I2C_Read_Len_Reg8(0x68, 6, buf))
        return -1;

    temp_mx = (buf[1] << 8) | buf[0];
    temp_my = (buf[3] << 8) | buf[2];
    temp_mz = (buf[5] << 8) | buf[4];

    *mx = (float)temp_mx * 1.5f;
    *my = (float)temp_my * 1.5f;
    *mz = (float)temp_mz * 1.5f;

    return 0;
}

获取温度

温度存在0x6E和0x6F寄存器中

image-20250722122229535

/**
 * @brief 获取温度
 * @return 温度 (℃)
 * @author HZ12138
 * @date 2025-07-18 21:20:59
 */
float IMU_LIS2MD_Get_T(void)
{
    uint8_t buf[2];
    int16_t temp;
    IMU_LIS2MD_I2C_Read_Len_Reg8(0x6E, 2, buf);

    temp = (buf[1] << 8 | buf[0]);

    return (((float)temp / 8.0f) + 25.0f);
}

文件

IMU_LSM6DS.c

#include "IMU.h"
uint8_t IMU_LSM6DS_a_Full, IMU_LSM6DS_w_Full;
/**
 * @brief IMU使用的延迟 可以外部重定义
 * @param time 时间 ms
 * @author HZ12138
 * @date 2025-07-15 19:56:18
 */
__weak void IMU_Delay(uint32_t time)
{
    HAL_Delay(time);
}
/**
 * @brief 软件复位LSM6DS
 * @author HZ12138
 * @date 2025-07-15 19:23:26
 */
void IMU_LSM6DS_ReStart(void)
{
    uint8_t temp;

    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL3_C, 0x80); // 复位
    IMU_Delay(20);

    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL3_C); // 读取控制寄存器3
    // SW_RESET 写1
    temp |= 0x01;
    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL3_C, temp);

    IMU_Delay(20);
}

/**
 * @brief 设置BDU(块数据更新)
 * @param flag 0禁用 1启用
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-15 20:41:47
 */
int IMU_LSM6DS_SetBDU(uint8_t flag)
{
    uint8_t temp;

    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL3_C); // 读取控制寄存器3

    // 写入寄存器
    if (flag)
        temp |= 0x40; // bit 6 写1
    else
        temp &= 0xBF; // bit 6 清零
    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL3_C, temp);

    // 读取验证是否成功
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL3_C);
    if (temp & 0x40)
    {
        if (!flag) // 读取的是1 期望的是0
            return -1;
    }
    else
    {
        if (flag) // 读取的是0 期望的是1
            return -1;
    }
    return 0;
}

/**
 * @brief  设置加速度(a)速率
 * @param opt 设置选项(IMU_LSM6DS_w_a_RATE_PowerDown/...)
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-16 09:47:25
 */
int IMU_LSM6DS_Set_a_Rate(uint8_t opt)
{
    uint8_t temp;
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL1_XL); // 读取控制寄存器1

    // 高4位清零后 写入OPT数据
    temp &= 0x0f;
    temp |= opt;
    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL1_XL, temp); // 写入数据

    // 读取后检测 是否正确
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL1_XL);
    if ((temp & 0xf0) != opt)
        return -1;
    return 0;
}

/**
 * @brief  设置角速度(w)速率
 * @param opt 设置选项(IMU_LSM6DS_w_a_RATE_PowerDown/...)
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-16 10:15:05
 */
int IMU_LSM6DS_Set_w_rate(uint8_t opt)
{
    uint8_t temp;
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL2_G); // 读取控制寄存器2

    // 高4位清零后 写入OPT数据
    temp &= 0x0f;
    temp |= opt;

    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL2_G, temp); // 写入数据

    // 读取后检测 是否正确
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL2_G);
    if ((temp & 0xf0) != opt)
        return -1;
    return 0;
}

/**
 * @brief 设置加速度(a)量程
 * @param opt 设置选项(IMU_LSM6DS_a_Full_2g/...)
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-16 10:40:04
 */
int IMU_LSM6DS_Set_a_Full(uint8_t opt)
{
    uint8_t temp;
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL1_XL); // 读取控制寄存器1

    // bit 2 3清零后写入opt
    temp &= 0xF3;
    temp |= opt;

    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL1_XL, temp); // 写入数据

    // 读取后检测 是否正确
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL1_XL);
    if ((temp & 0x0C) != opt)
        return -1;

    IMU_LSM6DS_a_Full = opt; // 保存参数

    return 0;
}
/**
 * @brief 设置角速度(w)量程
 * @param opt 设置选项(IMU_LSM6DS_w_Full_125dps/...)
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-16 10:57:25
 */
int IMU_LSM6DS_Set_w_Full(uint8_t opt)
{
    uint8_t temp;
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL2_G); // 读取控制寄存器2

    // bit 1 2 3 清零后写入opt
    temp &= 0xf1;
    temp |= opt;
    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL2_G, temp); // 写入数据

    // 读取后检测 是否正确
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL2_G);
    if ((temp & 0x0E) != opt)
        return -1;

    IMU_LSM6DS_w_Full = opt; // 保存参数

    return 0;
}
/**
 * @brief 设置加速度计带宽 建议采样率>1.67KHz时选 1.5KHz 其余选400Hz
 * @param opt 设置选项(IMU_LSM6DS_a_BW_1KHz5/...)
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-16 12:58:04
 */
int IMU_LSM6DS_Set_a_BW(uint8_t opt)
{
    uint8_t temp;
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL1_XL); // 读取控制寄存器1

    // bit 0清零后写入opt
    temp &= 0xFE;
    temp |= opt;

    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL1_XL, temp); // 写入数据

    // 读取后检测 是否正确
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL1_XL);
    if ((temp & 0x01) != opt)
        return -1;
    return 0;
}

/**
 * @brief 设置加速度计低通滤波
 * @param opt 设置选项(IMU_LSM6DS_a_LOW_PASS_ODR_9/...)
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-16 13:47:23
 */
int IMU_LSM6DS_Set_a_LowPass(uint8_t opt)
{
    uint8_t temp;

    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL8_XL, opt); // 写入数据

    // 读取后检测 是否正确
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL8_XL);
    if (temp != opt)
        return -1;
    return 0;
}
/**
 * @brief 设置角速度计高通滤波
 * @param en 启用/禁用 (IMU_LSM6DS_w_HP_ENABLE/IMU_LSM6DS_w_HP_DISABLE)
 * @param opt 设置选项(IMU_LSM6DS_w_HPM_16MHz/...)
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-16 15:34:18
 */
int IMU_LSM6DS_Set_w_HighPass(uint8_t en, uint8_t opt)
{
    uint8_t temp;
    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL7_G, en | opt); // 写入数据

    // 读取后检测 是否正确
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL7_G);
    if (temp != (en | opt))
        return -1;
    return 0;
}
/**
 * @brief 设置角速度计低通滤波带宽
 * @param en 0关 1开
 * @param opt 设置选项(IMU_LSM6DS_w_CTRL6_C_FTYPE_1/...)
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-16 15:53:05
 */
int IMU_LSM6DS_Set_w_LowPassBW(uint8_t en, uint8_t opt)
{
    uint8_t temp;
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL6_C); // 读取控制寄存器6

    // 清除后2位 写入参数
    temp &= 0xFC;
    temp |= opt;
    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL6_C, temp); // 写入数据

    // 读取后检测 是否正确
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL6_C);
    if ((temp & 0x03) != opt)
        return -1;

    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL4_C); // 读取控制寄存器4

    // 清除 bit 1  写入参数
    temp &= 0xFD;
    if (en)
        temp |= 0x02;
    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_CTRL4_C, temp); // 写入数据

    // 读取后检测 是否正确
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_CTRL4_C);

    if (temp & 0x02)
    {
        if (!en) // 读取的是1 期望的是0
            return -2;
    }
    else
    {
        if (en) // 读取的是0 期望的是1
            return -2;
    }
    return 0;
}
/**
 * @brief 进入总线直通模式
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-20 18:41:30
 */
int IMU_LSM6DS_Enter_Pass_mood(void)
{
    uint8_t temp;
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_MASTER_CONFIG); // 读取主机配置寄存器

    // bit 2 置1
    temp |= 0x04;

    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_MASTER_CONFIG, temp); // 写入数据

    // 读取后检测 是否正确
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_MASTER_CONFIG);
    if (temp & 0x04)
        return 0;

    return -1;
}
/**
 * @brief 设置中断1
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-21 22:27:32
 */
int IMU_LSM6DS_Set_Int1(void)
{
    uint8_t temp;

    // 设置数据a,w更新中断
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_INT1_CTRL); // 读取中断控制寄存器
    temp |= 0x03;
    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_INT1_CTRL, temp); // 写入数据

    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_INT1_CTRL);
    if ((temp & 0x03) != 0x03)
        return -1;

    // 脉冲模式
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_DRDY_PULSE_CFG);
    temp |= 0x80;

    IMU_LSM6DS_I2C_Write_Reg8(IMU_LSM6DS_REG_DRDY_PULSE_CFG, temp); // 写入数据
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_DRDY_PULSE_CFG);

    if (!(temp & 0x80))
        return -1;

    return 0;
}
/**
 * @brief LSM6DS 初始化
 * @return 0成功 <0失败
 * @exception -1 ID错误
 * @author HZ12138
 * @date 2025-07-15 17:50:41
 */
int IMU_LSM6DS_Init(void)
{
    IMU_I2C_Init(); // 初始化IIC

    if (IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_ID) != 0x6A) // 检测ID
        return -1;

    IMU_LSM6DS_ReStart(); // 软复位

    if (IMU_LSM6DS_SetBDU(1)) // 设置BDU
        return -2;
    if (IMU_LSM6DS_Set_a_Rate(IMU_LSM6DS_w_a_RATE_1KHz66)) // 设置加速度计速率
        return -3;
    if (IMU_LSM6DS_Set_w_rate(IMU_LSM6DS_w_a_RATE_1KHz66)) // 设置角速度计速率
        return -4;
    if (IMU_LSM6DS_Set_a_Full(IMU_LSM6DS_a_Full_8g)) // 设置加速度计量程
        return -5;
    if (IMU_LSM6DS_Set_w_Full(IMU_LSM6DS_w_Full_1000dps)) // 设置角速度计量程
        return -6;
    if (IMU_LSM6DS_Set_a_BW(IMU_LSM6DS_a_BW_400Hz)) // 设置加速度计带宽
        return -7;
    if (IMU_LSM6DS_Set_a_LowPass(IMU_LSM6DS_a_LOW_PASS_ODR_50)) // 设置加速度计低通滤波
        return -8;
    if (IMU_LSM6DS_Set_w_HighPass(IMU_LSM6DS_w_HP_ENABLE, IMU_LSM6DS_w_HPM_260MHz)) // 设置角速度计高通滤波
        return -9;
    if (IMU_LSM6DS_Set_w_LowPassBW(1, IMU_LSM6DS_w_CTRL6_C_FTYPE_1)) // 设置角速度计低通滤波带宽
        return -10;
    if (IMU_LSM6DS_Enter_Pass_mood()) // 进入总线直通模式
        return -11;
    if (IMU_LSM6DS_Set_Int1()) // 设置Int1
        return -12;
    return 0;
}
/**
 * @brief 获取数据状态(加速度a)
 * @return 0 已准备完成 <0 未完成w
 * @author HZ12138
 * @date 2025-07-16 16:38:08
 */
int8_t IMU_LSM6DS_GetState_a(void)
{
    uint8_t temp;
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_STATUS);

    if (temp & 0x01)
        return 0;

    return -1;
}
/**
 * @brief 获取数据状态(角速度w)
 * @return 0 已准备完成 <0 未完成
 * @author HZ12138
 * @date 2025-07-16 16:41:34
 */
int8_t IMU_LSM6DS_GetState_w(void)
{
    uint8_t temp;
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_STATUS);

    if (temp & 0x02)
        return 0;

    return -1;
}
/**
 * @brief 获取数据状态(温度T)
 * @return 0 已准备完成 <0 未完成
 * @author HZ12138
 * @date 2025-07-16 16:41:56
 */
int8_t IMU_LSM6DS_GetState_t(void)
{
    uint8_t temp;
    temp = IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_STATUS);

    if (temp & 0x04)
        return 0;

    return -1;
}

/**
 * @brief 获取加速度(a)
 * @param ax x方向加速度(单位mg g是重力加速度)
 * @param ay y方向加速度(单位mg g是重力加速度)
 * @param az z方向加速度(单位mg g是重力加速度)
 * @author HZ12138
 * @date 2025-07-16 21:30:13
 */
int8_t IMU_LSM6DS_Get_a(float *ax, float *ay, float *az)
{

    uint8_t buf[6];
    int16_t acc[3];

    IMU_LSM6DS_I2C_Read_Len_Reg8(0x28, 6, buf);

    acc[0] = buf[1] << 8 | buf[0];
    acc[1] = buf[3] << 8 | buf[2];
    acc[2] = buf[5] << 8 | buf[4];

    switch (IMU_LSM6DS_a_Full)
    {
    case IMU_LSM6DS_a_Full_2g:
        *ax = ((float)acc[0] * 0.061f);
        *ay = ((float)acc[1] * 0.061f);
        *az = ((float)acc[2] * 0.061f);
        break;
    case IMU_LSM6DS_a_Full_4g:
        *ax = ((float)acc[0] * 0.122f);
        *ay = ((float)acc[1] * 0.122f);
        *az = ((float)acc[2] * 0.122f);
        break;
    case IMU_LSM6DS_a_Full_8g:
        *ax = ((float)acc[0] * 0.244f);
        *ay = ((float)acc[1] * 0.244f);
        *az = ((float)acc[2] * 0.244f);
        break;
    case IMU_LSM6DS_a_Full_16g:
        *ax = ((float)acc[0] * 0.488f);
        *ay = ((float)acc[1] * 0.488f);
        *az = ((float)acc[2] * 0.488f);
        break;
    default:
        return -1;
    }
    return 0;
}
/**
 * @brief 获取角速度(w)
 * @param wx x方向角速度(mdps 毫度每秒)
 * @param wy y方向角速度(mdps 毫度每秒)
 * @param wz z方向角速度(mdps 毫度每秒)
 * @return 0 成功 <0失败
 * @author HZ12138
 * @date 2025-07-17 09:43:45
 */
int8_t IMU_LSM6DS_Get_w(float *wx, float *wy, float *wz)
{

    uint8_t buf[6];
    int16_t gry[3];
    IMU_LSM6DS_I2C_Read_Len_Reg8(0x22, 6, buf);

    gry[0] = buf[1] << 8 | buf[0];
    gry[1] = buf[3] << 8 | buf[2];
    gry[2] = buf[5] << 8 | buf[4];

    switch (IMU_LSM6DS_w_Full)
    {
    case IMU_LSM6DS_w_Full_245dps:
        *wx = ((float)gry[0] * 8.750f);
        *wy = ((float)gry[1] * 8.750f);
        *wz = ((float)gry[2] * 8.750f);
        break;
    case IMU_LSM6DS_w_Full_500dps:
        *wx = ((float)gry[0] * 17.50f);
        *wy = ((float)gry[1] * 17.50f);
        *wz = ((float)gry[2] * 17.50f);
        break;
    case IMU_LSM6DS_w_Full_1000dps:
        *wx = ((float)gry[0] * 35.00f);
        *wy = ((float)gry[1] * 35.00f);
        *wz = ((float)gry[2] * 35.00f);
        break;
    case IMU_LSM6DS_w_Full_2000dps:
        *wx = ((float)gry[0] * 70.00f);
        *wy = ((float)gry[1] * 70.00f);
        *wz = ((float)gry[2] * 70.00f);
        break;
    default:
        return -1;
    }
    return 0;
}
/**
 * @brief 获取温度
 * @return 温度(℃)
 * @author HZ12138
 * @date 2025-07-17 09:50:08
 */
float IMU_LSM6DS_Get_t(void)
{
    uint8_t buf[2];
    int16_t temp;

    IMU_LSM6DS_I2C_Read_Len_Reg8(0x20, 2, buf);

    temp = buf[1] << 8 | buf[0];

    return (((float)temp / 256.0f) + 25.0f);
}

extern char CDC_data[500];
/**
 * @brief 打印所有数据 (ax,ay,az,wx,wy,wz,t)
 * @author HZ12138
 * @date 2025-07-17 09:54:18
 */
void IMU_LSM6DS_Print_data(void)
{
    float ax, ay, az;
    float wx, wy, wz;
    float t;
    int temp;

    // if (IMU_LSM6DS_GetState_a() == 0)
    temp = IMU_LSM6DS_Get_a(&ax, &ay, &az);
    // if (IMU_LSM6DS_GetState_w() == 0)
    temp = IMU_LSM6DS_Get_w(&wx, &wy, &wz);
    // if (IMU_LSM6DS_GetState_t() == 0)
    //     t = IMU_LSM6DS_Get_t();

    memset(CDC_data, 0, 500);
    sprintf(CDC_data, "%f,%f,%f,%f,%f,%f,%f\n", ax, ay, az, wx, wy, wz, t);
    CDC_Transmit(0, (uint8_t *)CDC_data, strlen(CDC_data));

    // printf("%f,%f,%f,%f,%f,%f,%f\n", ax, ay, az, wx, wy, wz, t);
}

IMU_LSM6DS.h

#ifndef _IMU_LSM6DS_H_
#define _IMU_LSM6DS_H_

#define IMU_LSM6DS_REG_ID 0x0F // ID寄存器

#define IMU_LSM6DS_REG_CTRL1_XL 0x10        // 控制寄存器1
#define IMU_LSM6DS_REG_CTRL2_G 0x11         // 控制寄存器2
#define IMU_LSM6DS_REG_CTRL3_C 0x12         // 控制寄存器3
#define IMU_LSM6DS_REG_CTRL4_C 0x13         // 控制寄存器4
#define IMU_LSM6DS_REG_CTRL6_C 0x15         // 控制寄存器6
#define IMU_LSM6DS_REG_CTRL7_G 0x16         // 控制寄存器7
#define IMU_LSM6DS_REG_CTRL8_XL 0x17        // 控制寄存器8
#define IMU_LSM6DS_REG_STATUS 0x1E          // 数据状态寄存器
#define IMU_LSM6DS_REG_MASTER_CONFIG 0x1A   // 主机配置寄存器
#define IMU_LSM6DS_REG_FIFO_CTRL1 0x06      // FIFO控制寄存器1
#define IMU_LSM6DS_REG_FIFO_CTRL2 0x07      // FIFO控制寄存器2
#define IMU_LSM6DS_REG_FIFO_CTRL3 0x08      // FIFO控制寄存器3
#define IMU_LSM6DS_REG_FIFO_CTRL4 0x09      // FIFO控制寄存器4
#define IMU_LSM6DS_REG_FIFO_CTRL5 0x0A      // FIFO控制寄存器5
#define IMU_LSM6DS_REG_INT1_CTRL 0x0D       // IN1 控制寄存器
#define IMU_LSM6DS_REG_FIFO_STATUS1 0x3A    // FIFO状态寄存器1
#define IMU_LSM6DS_REG_FIFO_STATUS2 0x3B    // FIFO状态寄存器2
#define IMU_LSM6DS_REG_FIFO_STATUS3 0x3C    // FIFO状态寄存器3
#define IMU_LSM6DS_REG_FIFO_STATUS4 0x3D    // FIFO状态寄存器4
#define IMU_LSM6DS_REG_FIFO_DATA_OUT_L 0x3E // FIFO数据寄存器L
#define IMU_LSM6DS_REG_FIFO_DATA_OUT_H 0x3F // FIFO数据寄存器F
#define IMU_LSM6DS_REG_TAP_CFG 0x58         // TAP设置寄存器
#define IMU_LSM6DS_REG_DRDY_PULSE_CFG 0x0B  // 数据就绪寄存器

/* 加速度/角速度 速率选项 */
#define IMU_LSM6DS_w_a_RATE_PowerDown 0x00
#define IMU_LSM6DS_w_a_RATE_1Hz6 0xB0
#define IMU_LSM6DS_w_a_RATE_12Hz5 0x10
#define IMU_LSM6DS_w_a_RATE_26Hz 0x20
#define IMU_LSM6DS_w_a_RATE_52Hz6 0x30
#define IMU_LSM6DS_w_a_RATE_104Hz6 0x40
#define IMU_LSM6DS_w_a_RATE_208Hz6 0x50
#define IMU_LSM6DS_w_a_RATE_416Hz6 0x60
#define IMU_LSM6DS_w_a_RATE_833Hz6 0x70
#define IMU_LSM6DS_w_a_RATE_1KHz66 0x80
#define IMU_LSM6DS_w_a_RATE_3KHz33 0x90
#define IMU_LSM6DS_w_a_RATE_6KHz66 0xA0

/*加速度 量程选项*/
#define IMU_LSM6DS_a_Full_2g 0x00
#define IMU_LSM6DS_a_Full_4g 0x08
#define IMU_LSM6DS_a_Full_8g 0x0C
#define IMU_LSM6DS_a_Full_16g 0x04

/*角速度 量程选项*/
#define IMU_LSM6DS_w_Full_125dps 0x02
#define IMU_LSM6DS_w_Full_245dps 0x00
#define IMU_LSM6DS_w_Full_500dps 0x04
#define IMU_LSM6DS_w_Full_1000dps 0x08
#define IMU_LSM6DS_w_Full_2000dps 0x0C

/* 加速度带宽 选项*/
#define IMU_LSM6DS_a_BW_1KHz5 0x00
#define IMU_LSM6DS_a_BW_400Hz 0x01

/* 加速度计低通滤波 选项 */
#define IMU_LSM6DS_a_LOW_PASS_ODR_9 0xC8
#define IMU_LSM6DS_a_LOW_PASS_ODR_50 0x88
#define IMU_LSM6DS_a_LOW_PASS_ODR_100 0xA8
#define IMU_LSM6DS_a_LOW_PASS_ODR_400 0xE8

/*角速度计 高通滤波器 选项 */
#define IMU_LSM6DS_w_HP_DISABLE 0x00
#define IMU_LSM6DS_w_HP_ENABLE 0x40

/*角速度计 高通滤波器截止频率 选项 */
#define IMU_LSM6DS_w_HPM_16MHz 0x00
#define IMU_LSM6DS_w_HPM_65MHz 0x10
#define IMU_LSM6DS_w_HPM_260MHz 0x20
#define IMU_LSM6DS_w_HPM_1Hz04 0x30

/*角速度计 低通滤波带宽 选项 */
#define IMU_LSM6DS_w_CTRL6_C_FTYPE_1 0x00
#define IMU_LSM6DS_w_CTRL6_C_FTYPE_2 0x01
#define IMU_LSM6DS_w_CTRL6_C_FTYPE_3 0x02
#define IMU_LSM6DS_w_CTRL6_C_FTYPE_4 0x03

/*FIFO 加速度 速率 选项*/
#define IMU_LSM6DS_FIFO_a_12Hz5 0x01
#define IMU_LSM6DS_FIFO_a_26Hz 0x02
#define IMU_LSM6DS_FIFO_a_52Hz 0x03
#define IMU_LSM6DS_FIFO_a_104Hz 0x04
#define IMU_LSM6DS_FIFO_a_208Hz 0x05
#define IMU_LSM6DS_FIFO_a_417Hz 0x06
#define IMU_LSM6DS_FIFO_a_833Hz 0x07
#define IMU_LSM6DS_FIFO_a_1667Hz 0x08
#define IMU_LSM6DS_FIFO_a_3333Hz 0x09
#define IMU_LSM6DS_FIFO_a_6667Hz 0x0A
#define IMU_LSM6DS_FIFO_a_6Hz5 0x0B

/*FIFO 角速度 速率 选项*/
#define IMU_LSM6DS_FIFO_w_12Hz5 0x10
#define IMU_LSM6DS_FIFO_w_26Hz 0x20
#define IMU_LSM6DS_FIFO_w_52Hz 0x30
#define IMU_LSM6DS_FIFO_w_104Hz 0x40
#define IMU_LSM6DS_FIFO_w_208Hz 0x50
#define IMU_LSM6DS_FIFO_w_417Hz 0x60
#define IMU_LSM6DS_FIFO_w_833Hz 0x70
#define IMU_LSM6DS_FIFO_w_1667Hz 0x80
#define IMU_LSM6DS_FIFO_w_3333Hz 0x90
#define IMU_LSM6DS_FIFO_w_6667Hz 0xA0
#define IMU_LSM6DS_FIFO_w_6Hz5 0xB0

#endif

IMU.h

#ifndef _IMU_H_
#define _IMU_H_
#include "HZ_I2C.h"
#include "Print.h"
#include "main.h"
#include "IMU_LSM6DS.h"
#include "IMU_LIS2MD.h"
/*
LSM6DS:
    1.软件IIC 2个GPIO 开漏输出 最高速度
 */

#define IMU_IIC_Soft
// #define IMU_LSM6DS_IIC_Hard

#ifdef IMU_IIC_Soft
#define IMU_SDA_GPIOx GPIOA
#define IMU_SDA_Pin GPIO_PIN_4
#define IMU_SCL_GPIOx GPIOA
#define IMU_SCL_Pin GPIO_PIN_5
#define IMU_IIC_Delay 0x1
#endif // IMU_IIC_Soft

#define IMU_LSM6DS_Addr 0xD6
#define IMU_LIS2MD_Addr 0x3C

void IMU_I2C_Init(void);
uint8_t IMU_LSM6DS_I2C_Read_Reg8(uint8_t reg);
uint8_t IMU_LSM6DS_I2C_Write_Reg8(uint8_t reg, uint8_t data);
uint8_t IMU_LSM6DS_I2C_Read_Len_Reg8(uint8_t reg, uint8_t len, uint8_t *buf);

uint8_t IMU_LIS2MD_I2C_Read_Reg8(uint8_t reg);
uint8_t IMU_LIS2MD_I2C_Write_Reg8(uint8_t reg, uint8_t data);
uint8_t IMU_LIS2MD_I2C_Read_Len_Reg8(uint8_t reg, uint8_t len, uint8_t *buf);

int IMU_LSM6DS_Init(void);
void IMU_Delay(uint32_t time);
int8_t IMU_LSM6DS_GetState_a(void);
int8_t IMU_LSM6DS_GetState_w(void);
int8_t IMU_LSM6DS_GetState_t(void);
void IMU_LSM6DS_Print_data(void);
int8_t IMU_LSM6DS_Get_a(float *ax, float *ay, float *az);
int8_t IMU_LSM6DS_Get_w(float *wx, float *wy, float *wz);
float IMU_LSM6DS_Get_t(void);

int IMU_LIS2MD_Init(void);
uint8_t IMU_LIS2MD_Get_State(void);
void IMU_LIS2MD_Print_data(void);
int IMU_LIS2MD_Get_Magnetic(float *mx, float *my, float *mz);
float IMU_LIS2MD_Get_T(void);
uint16_t IMU_LSM6DS_Get_FIFO_num(void);
float IMU_LSM6DS_Get_FIFO_Data(void);
uint16_t IMU_LSM6DS_Get_FIFO_Data_TGA(void);

#endif

IMU_LIS2MD.c

#include "IMU.h"
// IMU_LIS2MD_

/**
 * @brief 设置BDU(块数据更新)
 * @param flag 0禁用 1启用
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-18 14:15:28
 */
int IMU_LIS2MD_Set_BDU(uint8_t flag)
{
    uint8_t temp;

    temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_C); // 读取控制寄存器C

    // 写入寄存器
    if (flag)
        temp |= 0x10; // bit 4 写1
    else
        temp &= 0xEF; // bit 4 清零
    IMU_LIS2MD_I2C_Write_Reg8(IMU_LIS2MD_REG_CFG_C, temp);

    // 读取验证是否成功
    temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_C);
    if (temp & 0x10)
    {
        if (!flag) // 读取的是1 期望的是0
            return -1;
    }
    else
    {
        if (flag) // 读取的是0 期望的是1
            return -1;
    }
    return 0;
}
/**
 * @brief LIS2MD复位
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-18 13:58:46
 */
int IMU_LIS2MD_Restart(void)
{
    uint8_t temp;
    temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A);

    temp |= 0x20;
    if (IMU_LIS2MD_I2C_Write_Reg8(IMU_LIS2MD_REG_CFG_A, temp))
        return -1;
    IMU_Delay(20);
    return 0;
}

/**
 * @brief 读取ID
 * @return ID
 * @author HZ12138
 * @date 2025-07-18 13:35:33
 */
uint8_t IMU_LIS2MD_Read_ID(void)
{
    return IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_ID);
}

/**
 * @brief 设置输出速率
 * @param opt 选项( IMU_LIS2MD_ODR_10Hz /...)
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-18 15:35:04
 */
int IMU_LIS2MD_Set_ODR(uint8_t opt)
{
    uint8_t temp;
    temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A);

    temp |= opt;
    IMU_LIS2MD_I2C_Write_Reg8(IMU_LIS2MD_REG_CFG_A, temp);

    temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A);

    if ((temp & 0x0C) != opt)
        return -1;
    return 0;
}
/**
 * @brief 设置偏移消除
 * @param flag 0禁用 1启用
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-18 16:39:28
 */
int IMU_LIS2MD_Set_Offset_CANC(uint8_t flag)
{
    uint8_t temp;

    temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_B); // 读取控制寄存器B

    // 写入寄存器
    if (flag)
        temp |= 0x02; // bit 1 写1
    else
        temp &= 0xFD; // bit 1 清零
    IMU_LIS2MD_I2C_Write_Reg8(IMU_LIS2MD_REG_CFG_B, temp);

    // 读取验证是否成功
    temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_B);
    if (temp & 0x02)
    {
        if (!flag) // 读取的是1 期望的是0
            return -1;
    }
    else
    {
        if (flag) // 读取的是0 期望的是1
            return -1;
    }
    return 0;
}
/**
 * @brief 设置温度补偿
 * @param flag 0禁用 1启用
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-18 16:45:30
 */
int IMU_LIS2MD_Set_TempComp(uint8_t flag)
{
    uint8_t temp;

    temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A); // 读取控制寄存器A

    // 写入寄存器
    if (flag)
        temp |= 0x80; // bit 1 写1
    else
        temp &= 0x7F; // bit 1 清零
    IMU_LIS2MD_I2C_Write_Reg8(IMU_LIS2MD_REG_CFG_A, temp);

    // 读取验证是否成功
    temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A);
    if (temp & 0x80)
    {
        if (!flag) // 读取的是1 期望的是0
            return -1;
    }
    else
    {
        if (flag) // 读取的是0 期望的是1
            return -1;
    }
    return 0;
}
/**
 * @brief 设置模式
 * @param opt 选项(IMU_LIS2MD_MODE_Continuous/...)
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-18 17:10:08
 */
int IMU_LIS2MD_Set_Mode(uint8_t opt)
{
    uint8_t temp;

    temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A); // 读取控制寄存器A

    temp &= 0xFC;
    temp |= opt;

    IMU_LIS2MD_I2C_Write_Reg8(IMU_LIS2MD_REG_CFG_A, temp);

    // 读取验证是否成功
    temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_CFG_A);
    if ((temp & 0x03) != opt)
        return -1;
    return 0;
}
/**
 * @brief 初始化LIS2MD
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-18 13:32:30
 */
int IMU_LIS2MD_Init(void)
{

    if (IMU_LIS2MD_Read_ID() != 0x40) // 验证ID
        return -1;
    if (IMU_LIS2MD_Restart() != 0) // 复位
        return -2;
    if (IMU_LIS2MD_Set_BDU(1) != 0) // 设置块数据更新
        return -3;
    if (IMU_LIS2MD_Set_ODR(IMU_LIS2MD_ODR_50Hz) != 0) // 设置数据更新速率
        return -4;
    if (IMU_LIS2MD_Set_Offset_CANC(1) != 0) // 设置偏移消除
        return -5;
    if (IMU_LIS2MD_Set_TempComp(1) != 0) // 设置温度补偿
        return -6;
    HAL_Delay(10);
    if (IMU_LIS2MD_Set_Mode(IMU_LIS2MD_MODE_Continuous) != 0) // 启动连续模式
        return -7;
    return 0;
}
/**
 * @brief 获取数据状态
 * @return 0 没有准备好 1 准备完成
 * @author HZ12138
 * @date 2025-07-18 21:01:46
 */
uint8_t IMU_LIS2MD_Get_State(void)
{
    uint8_t temp;

    temp = IMU_LIS2MD_I2C_Read_Reg8(IMU_LIS2MD_REG_STATUS); // 读取状态寄存器

    if (temp & 0x08)
        return 1;
    return 0;
}
/**
 * @brief 获取磁场数据 单位 mG(毫高斯)
 * @param mx x方向磁场
 * @param my y方向磁场
 * @param mz z方向磁场
 * @return 0成功 <0失败
 * @author HZ12138
 * @date 2025-07-18 21:01:44
 */
int IMU_LIS2MD_Get_Magnetic(float *mx, float *my, float *mz)
{
    uint8_t buf[6];
    int16_t temp_mx, temp_my, temp_mz;

    if (IMU_LIS2MD_I2C_Read_Len_Reg8(0x68, 6, buf))
        return -1;

    temp_mx = (buf[1] << 8) | buf[0];
    temp_my = (buf[3] << 8) | buf[2];
    temp_mz = (buf[5] << 8) | buf[4];

    *mx = (float)temp_mx * 1.5f;
    *my = (float)temp_my * 1.5f;
    *mz = (float)temp_mz * 1.5f;

    return 0;
}
/**
 * @brief 获取温度
 * @return 温度 (℃)
 * @author HZ12138
 * @date 2025-07-18 21:20:59
 */
float IMU_LIS2MD_Get_T(void)
{
    uint8_t buf[2];
    int16_t temp;
    IMU_LIS2MD_I2C_Read_Len_Reg8(0x6E, 2, buf);

    temp = (buf[1] << 8 | buf[0]);

    return (((float)temp / 8.0f) + 25.0f);
}
/**
 * @brief 打印数据
 * @author HZ12138
 * @date 2025-07-18 21:21:31
 */
void IMU_LIS2MD_Print_data(void)
{
    float mx, my, mz;
    float t;
    if (!IMU_LIS2MD_Get_State())
        return;
    IMU_LIS2MD_Get_Magnetic(&mx, &my, &mz);

    t = IMU_LIS2MD_Get_T();
    printf("%f,%f,%f,%f\n", mx, my, mz, t);
}

IMU_LIS2MD.h

#ifndef _IMU_LIS2MD_H_
#define _IMU_LIS2MD_H_
#define IMU_LIS2MD_REG_ID 0x4F // ID寄存器

#define IMU_LIS2MD_REG_CFG_A 0x60  // 控制寄存器A
#define IMU_LIS2MD_REG_CFG_B 0x61  // 控制寄存器B
#define IMU_LIS2MD_REG_CFG_C 0x62  // 控制寄存器C
#define IMU_LIS2MD_REG_STATUS 0x67 // 状态寄存器

/* 数据输出 选项 */
#define IMU_LIS2MD_ODR_10Hz 0x00
#define IMU_LIS2MD_ODR_20Hz 0x04
#define IMU_LIS2MD_ODR_50Hz 0x08
#define IMU_LIS2MD_ODR_100Hz 0x0C

/* 模式设置 选项 */
#define IMU_LIS2MD_MODE_Idle 0x11
#define IMU_LIS2MD_MODE_Single 0x01
#define IMU_LIS2MD_MODE_Continuous 0x00

#endif

IMU_I2C.c

#include "IMU.h"

#ifdef IMU_IIC_Soft
HZ_I2C_typedef IMU_I2C_h;
#endif // IMU_IIC_Soft

/**
 * @brief 初始化I2C
 * @author HZ12138
 * @date 2025-07-15 17:50:23
 */
void IMU_I2C_Init(void)
{
#ifdef IMU_IIC_Soft
    // 使用软件IIC 绑定地址
    // 绑定SDA和SCL到IIC句柄
    I2C_Init_Channel(&IMU_I2C_h,
                     IMU_SDA_GPIOx, IMU_SDA_Pin,
                     IMU_SCL_GPIOx, IMU_SCL_Pin,
                     IMU_IIC_Delay); // addr D6

#endif // IMU_IIC_Soft
}
/**
 * @brief 读8bits寄存器
 * @param reg 寄存器地址
 * @return 读取的数据
 * @author HZ12138
 * @date 2025-07-15 17:49:51
 */
uint8_t IMU_LSM6DS_I2C_Read_Reg8(uint8_t reg)
{
#ifdef IMU_IIC_Soft
    return I2C_Read_Reg8(IMU_I2C_h, IMU_LSM6DS_Addr, reg);
#endif // IMU_IIC_Soft
}

/**
 * @brief 写8bits寄存器
 * @param reg:寄存器地址 8bit
 * @param data:数据
 * @return 状态 0成功 其他失败
 * @author HZ12138
 * @date 2025-07-15 19:22:28
 */
uint8_t IMU_LSM6DS_I2C_Write_Reg8(uint8_t reg, uint8_t data)
{
#ifdef IMU_IIC_Soft
    return I2C_Write_Reg8(IMU_I2C_h, IMU_LSM6DS_Addr, reg, data);
#endif // IMU_IIC_Soft
}

/**
 * @brief I2C连续读寄存器
 * @param reg 寄存器地址
 * @param len 长度
 * @param buf 缓冲区地址
 * @author HZ12138
 * @date 2025-07-16 17:19:58
 */
uint8_t IMU_LSM6DS_I2C_Read_Len_Reg8(uint8_t reg, uint8_t len, uint8_t *buf)
{
#ifdef IMU_IIC_Soft
    return I2C_Read_Len_Reg8(IMU_I2C_h, IMU_LSM6DS_Addr, reg, len, buf);
#endif // IMU_IIC_Soft
}

/**
 * @brief 读8bits寄存器
 * @param reg 寄存器地址
 * @return 读取的数据
 * @author HZ12138
 * @date 2025-07-15 17:49:51
 */
uint8_t IMU_LIS2MD_I2C_Read_Reg8(uint8_t reg)
{
#ifdef IMU_IIC_Soft
    return I2C_Read_Reg8(IMU_I2C_h, IMU_LIS2MD_Addr, reg);
#endif // IMU_IIC_Soft
}

/**
 * @brief 写8bits寄存器
 * @param reg:寄存器地址 8bit
 * @param data:数据
 * @return 状态 0成功 其他失败
 * @author HZ12138
 * @date 2025-07-15 19:22:28
 */
uint8_t IMU_LIS2MD_I2C_Write_Reg8(uint8_t reg, uint8_t data)
{
#ifdef IMU_IIC_Soft
    return I2C_Write_Reg8(IMU_I2C_h, IMU_LIS2MD_Addr, reg, data);
#endif // IMU_IIC_Soft
}

/**
 * @brief I2C连续读寄存器
 * @param reg 寄存器地址
 * @param len 长度
 * @param buf 缓冲区地址
 * @author HZ12138
 * @date 2025-07-16 17:19:58
 */
uint8_t IMU_LIS2MD_I2C_Read_Len_Reg8(uint8_t reg, uint8_t len, uint8_t *buf)
{
#ifdef IMU_IIC_Soft
    return I2C_Read_Len_Reg8(IMU_I2C_h, IMU_LIS2MD_Addr, reg, len, buf);
#endif // IMU_IIC_Soft
}

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐