IMU(LSM6DSMTR+LIS2MDLTR)
LSM6DSMTR是一款集成3轴加速度计和3轴陀螺仪的传感器,采用LGA-14封装,体积小巧。其电路设计简单,仅需I2C上拉电阻和电源滤波电容,支持0xD6地址。文章详细介绍了基于STM32的软件I2C驱动实现,包括初始化、寄存器读写等函数封装,并提供了传感器复位、BDU设置和加速度计采样率配置的方法。代码示例展示了如何通过I2C接口对LSM6DSMTR进行控制,支持多种采样频率设置(1.6Hz-
LSM6DSMTR(陀螺仪)
概述
LSM6DSMTR 是一款3轴加速度计3轴角速度计的陀螺仪
LGA-14 封装 超小体积

电路设计
采用I2C通信,基本上外部电路只用I2C的上拉和电源滤波即可
1号脚接3V3时 I2C地址为:0xD6 (直接或即可无需右移)
2/3号脚可以接其他I2C器件 如磁力计
两个可编程中断 根据情况使用

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

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

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 软件复位

- bit7 写1 复位
- 延迟15ms以上
- bit0 写1 软件复位
- 延迟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

- 读取寄存器
- 写入数据
- 再次读取验证
#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]

#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]

#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]

#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]

#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

#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;
}
设置加速度计低通滤波
设置以下寄存器以设置加速度计低通滤波

#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] 设置截止频率

#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]来设置低通滤波带宽

#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;
}
进入总线直通模式
直通功能示意图

bit2 写入1启用

#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 设置加速度计和角速度计数据就位后触发中断

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

#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] 分别获取温度,角速度,加速度的数据状态

#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个寄存器中


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

/**
* @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个寄存器中



根据量程乘上系数即可

/**
* @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里

经过偏移(没找到为啥,根据例程反推的)
/**
* @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 超小封装

电路设计
将LIS2MDLTR的I2C口接到LSM6DSMTR 的 SDX/SCX 上
LSM6DSMTR 启用总线直通
I2C地址为:
0x3C(直接 或 即可无需右移)

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

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

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

#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 启动

#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]设置输出速率

#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启动

#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 启动

#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]设置

#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时代表数据准备完成

#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个寄存器中



/**
* @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寄存器中

/**
* @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
}
更多推荐



所有评论(0)