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

IMU(LSM6DSMTR+LIS2MDLTR)

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_Softreturn 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_Softreturn 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_Softreturn 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 写1temp |= 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 写1elsetemp &= 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 期望的是0return -1;}else{if (flag) // 读取的是0 期望的是1return -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清零后写入opttemp &= 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 清零后写入opttemp &= 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清零后写入opttemp &= 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 期望的是0return -2;}else{if (en) // 读取的是0 期望的是1return -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 置1temp |= 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(); // 初始化IICif (IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_ID) != 0x6A) // 检测IDreturn -1;IMU_LSM6DS_ReStart(); // 软复位if (IMU_LSM6DS_SetBDU(1)) // 设置BDUreturn -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()) // 设置Int1return -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_Softreturn 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_Softreturn 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_Softreturn 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 写1elsetemp &= 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 期望的是0return -1;}else{if (flag) // 读取的是0 期望的是1return -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 写1elsetemp &= 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 期望的是0return -1;}else{if (flag) // 读取的是0 期望的是1return -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 写1elsetemp &= 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 期望的是0return -1;}else{if (flag) // 读取的是0 期望的是1return -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); // 读取控制寄存器Atemp &= 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) // 验证IDreturn -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 写1temp |= 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 写1elsetemp &= 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 期望的是0return -1;}else{if (flag) // 读取的是0 期望的是1return -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清零后写入opttemp &= 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 清零后写入opttemp &= 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清零后写入opttemp &= 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 期望的是0return -2;}else{if (en) // 读取的是0 期望的是1return -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 置1temp |= 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(); // 初始化IICif (IMU_LSM6DS_I2C_Read_Reg8(IMU_LSM6DS_REG_ID) != 0x6A) // 检测IDreturn -1;IMU_LSM6DS_ReStart(); // 软复位if (IMU_LSM6DS_SetBDU(1)) // 设置BDUreturn -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()) // 设置Int1return -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 0x3Cvoid 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 写1elsetemp &= 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 期望的是0return -1;}else{if (flag) // 读取的是0 期望的是1return -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 写1elsetemp &= 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 期望的是0return -1;}else{if (flag) // 读取的是0 期望的是1return -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 写1elsetemp &= 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 期望的是0return -1;}else{if (flag) // 读取的是0 期望的是1return -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); // 读取控制寄存器Atemp &= 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) // 验证IDreturn -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_Softreturn 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_Softreturn 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_Softreturn 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_Softreturn 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_Softreturn 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_Softreturn I2C_Read_Len_Reg8(IMU_I2C_h, IMU_LIS2MD_Addr, reg, len, buf);
#endif // IMU_IIC_Soft
}
http://www.lryc.cn/news/595955.html

相关文章:

  • 隧道代理与普通代理:一场网络隐身术的“智能革命”
  • 开发者的AI认知指南:用大模型重新理解人工智能(上)
  • 基于AutoJawSegment项目的CBCT图像分割实践指南
  • Qt开发环境搭建全攻略(Windows+Linux+macOS)
  • Navicat 远程连接SQLlite数据库
  • 【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - 主页-微博基本信息实现
  • DearMom以“新生儿安全系统”重塑婴儿车价值,揽获CBME双项大奖
  • 数据库隔离级别
  • 在vscode 使用 remote-ssh
  • Vue3 面试题及详细答案120道(16-30 )
  • Baumer工业相机堡盟工业相机如何通过YoloV8深度学习模型实现持械检测(C#代码,UI界面版)
  • 【Altium Designer2025】电子设计自动化(EDA)软件——Altium Designer25版保姆级下载安装详细图文教程(附安装包)
  • ob导出租户所有表记录
  • SpringBoot--Mapper XML 和 Mapper 接口在不同包
  • C++中的list(2)简单复现list中的关键逻辑
  • 文本分类与情感分析Python实战
  • liunx运维进阶脚本
  • 2025.7.25论文阅读
  • VUE2 项目学习笔记 ? 语法 v-if/v-show
  • 为何在 Vue 的 v-model 指令中不能使用可选链(Optional Chaining)?
  • 【Spring Boot】Spring Boot循环依赖破解:@Lazy与Setter注入的取舍指南(流程图修复版)
  • JavaWeb学习打卡10(HttpServletRequest详解应用、获取参数,请求转发实例)
  • 分布在内侧内嗅皮层(MEC)的边界细胞对NLP中的深层语义分析的积极影响和启示
  • 短剧小程序系统开发:重塑影视内容传播格局
  • Python爬虫实战:批量下载亚马逊商品图片
  • java多线程编程自用笔记
  • 日常随笔-React摘要
  • 浅谈——游戏中的各种配置格式
  • C++ 模板库map数据结构的概念和使用案例
  • React集成百度【BMap Draw】教程(001):实现距离测量和面积测量