一、LSM6DS3TR 简介
LSM6DS3TR 是 ST 公司生产的一个六轴传感器,包含内置的三轴加速度计和三轴陀螺仪。其中加速度计能够计算 X、Y、Z 三个方向的加速度数据,如图 1 所示:

图 1-加速度方向
陀螺仪计算 X、Y、Z 轴三个轴向的角速度,如图 2 所示:

图 2-角速度方向
二、LSM6DS3TR 驱动
本例程驱动把 LSM6DS3TR 传感器配置为无中断触发,不使用 FIFO 先进先出寄存器的缓存功能。传感器中陀螺仪输出的三轴角速度和加速度计输出的三轴加速度准备就绪后直接覆盖旧数据,所以每次从传感器输出寄存器读取数据时,获得的都是最新时刻的加速度和角速度值。如果本例程不符合你的功能预期,请参考 LSM6DS3TR 数据手册进行寄存器配置更改。
本例程的软件开发 IDE 为 Keil5,使用 C/C++ 混合编程,通过 IIC 通信协议实现主机和从机的通信。
以下是驱动 LSM6DS3TR 传感器需要进行的操作,按操作先后顺序排列:
1、对芯片进行复位操作

传感器复位需要对 LSM6DS3TR 的 CTRL3_C 寄存器进行操作,数据手册表明,CTRL3_C 寄存器的地址为 0x12,其中第 8 位 BOOT 位控制传感器芯片是否重启,第 1 位 SW_RESET 位控制传感器芯片复位,实践表明,两个寄存器位都会在置 1 后自动复位。
/***********************************************************************
[函数名称]Reset_LSM6D
[函数功能]设备复位函数
***********************************************************************/
void Reset_LSM6D(void) {
uint8_t buf[1] = {0}; //创建 1 字节通信缓存
IIC_Read(CTRL3_C, buf, 1); //读取寄存器配置
buf[0] |= 0x80; //将 BOOT 位置 1,其他位保持不变
IIC_Send(CTRL3_C, buf, 1); //重启芯片
HAL_Delay(15); //等待重启完成
//将芯片中的寄存器配置恢复到出厂配置
IIC_Read(CTRL3_C, buf, 1); //读取寄存器配置
buf[0] |= 0x01; //将 SW_RESET 位置 1,其他位保持不变
IIC_Send(CTRL3_C, buf, 1); //复位芯片
while (buf[0] & 0x01) //等待芯片复位完成
IIC_Read(CTRL3_C, buf, 1);
}
2、读取 WHO AM I 寄存器返回值,验证通讯是否可靠

WHO AM I 是只读寄存器,地址为 0x0F,其内部 1 个字节的数据位在出厂时就已经配置好,不可更改。LSM6DS3TR 芯片在收到读取 WHO AM I 寄存器的指令后,会发送固定的 0x6A 一个字节数据到主机,该寄存器可用于检验主机和从机的通讯有无异常。由于代码简单,且与配置寄存器无关,所以本部分代码没有以函数形式体现,在完整初始化代码中有包含。
3、设置加速度计输出速率和满量程选择

CTRL1_XL 寄存器中的 ODR_XL[3:0] 四位用来配置加速度计的数据输出速率,输出速率配置为 208Hz 表示加速度计每秒钟输出 208 个完整的三轴加速度数据,当传感器的输出速率提高后,主机读取数据的速度也要跟上哦,否则会造成资源浪费。
/***********************************************************************
[函数名称]SetAccelerateRate_LSM6D
[函数功能]设置加速度数据输出速率
***********************************************************************/
#define RATE_208Hz 0x50
void SetAccelerateRate_LSM6D(void) {
uint8_t buf[1] = {0};
IIC_Read(CTRL1_XL, buf, 1); //读取 CTRL1_XL 寄存器值
buf[0] |= RATE_208Hz; //设置加速度计的数据输出速率为 208Hz
IIC_Send(CTRL1_XL, buf, 1);
}
CTRL1_XL 寄存器中的 FS_XL[1:0] 两位用来配置加速度计的最大量程选择,根据你的应用场景,参考下表做出选择:

本例程中选择最大量程±4g,传感器最大量程不同,由原始数据转换为可用数据的转换系数也不同,在数据手册中根据自己的配置选择对应的转换系数:
/**************************************************************************
[函数名称]SetAccelerateFullScale_LSM6D
[函数功能]设置加速度计的满量程
**************************************************************************/
#define ACC_FSXL_4G 0x08
void SetAccelerateFullScale_LSM6D(void) {
uint8_t buf[1] = {0};
IIC_Read(CTRL1_XL, buf, 1); //读取 CTRL1_XL 寄存器配置
buf[0] |= ACC_FSXL_4G; //设置加速度计的满量程
IIC_Send(CTRL1_XL, buf, 1);
}
4、设置陀螺仪输出速率和满量程选择

CTRL2_G 寄存器的 ODR_G[3:0] 四位用来控制陀螺仪的输出速率,如果同时使用陀螺仪和加速度计的话,建议两者的输出速率保持一致。加速度计的输出速率我设置的是 208Hz,陀螺仪保持一致,也为 208Hz,ODR_G[3:0] 配置为 0101,即 0x05。
/*****************************************************************************
[函数名称]SetAngleSpeedRate_LSM6D
[函数功能]设置陀螺仪数据输出速率
*****************************************************************************/
void SetAngleSpeedRate_LSM6D(void) {
uint8_t buf[1] = {0};
IIC_Read(CTRL2_G, buf, 1); //读取 CTRL2_G 寄存器的配置
buf[0] |= RATE_208Hz; //设置加速度计的数据采样率为 208Hz
IIC_Send(CTRL2_G, buf, 1);
}
CTRL2_G 寄存器的 FS_G[1:0] 两位用来控制陀螺仪的最大量程选择,量程越小,能表示的数值越精确,精度越高,我这里配置的是 500dps,表示陀螺仪最大能检测每秒钟 500°的旋转,像是体操运动员空中转体一圈半,已经能够满足日常生活中的大部分需求。以下是陀螺仪量程和应用场景的对应表,可以参考:

/*****************************************************************************
[函数名称]SetAngleSpeedFullScale_LSM6D
[函数功能]设置陀螺仪满量程
*****************************************************************************/
#define GYR_FSG_500 0x04
void SetAngleSpeedFullScale_LSM6D(void) {
uint8_t buf[1] = {0};
IIC_Read(CTRL2_G, buf, 1);
buf[0] |= GYR_FSG_500; //设置加速度计的最大量程 500dps
IIC_Send(CTRL2_G, buf, 1);
}
5、设置加速度计 BW 带宽

CTRL1_XL 寄存器中的 LPF1_BW_SEL 位和加速度计的滤波带宽选择有关,需要结合 CTRL8_XL 寄存器中的功能位进行配置,官方给了一个参考表 Table73(见下文),在这个表中很清晰的给出了配置加速度计带宽和滤波的选择。
BW0_XL 位则和高通滤波有关,如果加速度计输出速率>1.67KHz,就需要配置该位,但是我们设置的输出速率是 208Hz,所以这个寄存器位可以不管,保持默认状态就可以。

CTRL8_XL 寄存器用来控制加速度计的带宽和滤波选择,可以参考下表 Table73 来进行配置,比较关键的是 INPUT_COMPOSITE 位,这个位控制输出数据是 Low Noise(低噪声)还是 Low Latency(低延时),本例程中将 CTRL8_XL 寄存器中的 INPUT_COMPOSITE 位置 1,使用低噪声模式,更注重加速度计输出数据的精度。

加速度计滤波路径和带宽的选择原理就不详细介绍了,感兴趣的可以在数据手册里面查找,我们配置的输出速率是 208Hz,工作频率不算高频,实际应用中噪声也在可接受的范围内,所以这里只是简单配置了一下加速度计的带宽和滤波器试验了一下,陀螺仪的滤波相关寄存器配置保持默认,不影响正常输出。
/**************************************************************************
[函数名称]SetAcceleratemeterBW_LSM6d
[函数功能]设置加速度计带宽选择
**************************************************************************/
#define LSM6DS3TRC_ACC_BW0XL_400HZ 0x01 //加速度计模拟带宽
#define LSM6DS3TRC_ACC_LOW_PASS_ODR_50 0x88 //低通滤波器
void SetAcceleratemeterBW_LSM6d(void) {
uint8_t buf[1] = {0};
IIC_Read(CTRL1_XL, buf, 1);
buf[0] |= LSM6DS3TRC_ACC_BW0XL_400HZ;
IIC_Send(CTRL1_XL, buf, 1);
IIC_Read(CTRL8_XL, buf, 1);
buf[0] |= LSM6DS3TRC_ACC_LOW_PASS_ODR_50;
IIC_Send(CTRL8_XL, buf, 1);
}
6、驱动代码
将上文中的各个函数补充到这个 LSM6DS3TR 的初始化函数中,就可以实现六轴传感器的正确驱动。
#define ADDR_Read 0xD5 //IIC 读地址
#define ADDR_Write 0xD4 //IIC 写地址
#define CTRL1_XL 0x10 //LSM6DS3TR 寄存器地址
#define CTRL2_G 0x11
#define CTRL3_C 0x12
#define CTRL8_XL 0x17
#define STATUS_REG 0x1E //加速度计的模拟链带宽
#define LSM6DS3TRC_ACC_BW0XL_1500HZ 0x00
#define LSM6DS3TRC_ACC_BW0XL_400HZ 0x01 //加速度计带宽选择
#define LSM6DS3TRC_ACC_LOW_PASS_ODR_50 0x88 //低通滤波器
#define LSM6DS3TRC_ACC_LOW_PASS_ODR_100 0xA8
#define LSM6DS3TRC_ACC_LOW_PASS_ODR_9 0xC8
#define LSM6DS3TRC_ACC_LOW_PASS_ODR_400 0xE8
/**************************************************************************
[函数名称]SelfTest_LSM6D
[函数功能]检测 IIC 总线上挂载的设备是否存在
**************************************************************************/
uint8_t SelfTest_LSM6D(uint8_t addr) {
uint8_t recAck = 0xFF; //接收变量
IIC_Start(); //IIC 启动信号
IIC_SendByte(addr); //发送地址
recAck = IIC_MasterRec_Ack(); //主机接收 ACK 信号
IIC_Stop(); //IIC 停止信号
return (recAck == 0);
}
/**************************************************************************
[函数名称]Init_LSM6D
[函数功能]初始化函数
**************************************************************************/
BOOL {
(SelfTest_LSM6D(ADDR_Read) == )
;
Reset_LSM6D();
WhoAmI = ;
IIC_Read(, &WhoAmI, );
(WhoAmI != )
;
SetAccelerateRate_LSM6D();
SetAccelerateFullScale_LSM6D();
SetAngleSpeedRate_LSM6D();
SetAngleSpeedFullScale_LSM6D();
SetAcceleratemeterBW_LSM6d();
;
}
三、LSM6DS3TR 传感器数据读取
在完成驱动部分代码设计之后,我们就可以实现六轴传感器的正常运行了,并通过 LSM6DS3TR 传感器中状态寄存器的 GDA(陀螺仪)和 XLDA(加速度计)标志位,判断陀螺仪和加速度计数据是否准备就绪,从而进行正确的读取。

union{
//加速度一级缓存,原始数据
struct {
int16_t X;
int16_t Y;
int16_t Z;
}m_Data;
uint8_t m_Byte[6];
}Acceleration;
union{
//角速度一级缓存,原始数据
struct {
int16_t X;
int16_t Y;
int16_t Z;
}m_Data;
uint8_t m_Byte[6];
}AngleSpeed;
union {
//读状态寄存器的位域
struct{
//从上到下,位由低到高
uint8_t XLDA : 1; //加速度计有效标志位
uint8_t GDA : 1; //陀螺仪有效标志位
uint8_t TDA : 1; //温度数据有效标志位,不使用
uint8_t : 5; //无关位
}m_Bit;
//位域结构体
uint8_t m_Byte;
}status; //状态寄存器读取缓存
/*****************************************************************************
[函数名称]Read_LSM6D
[函数功能]定时运行函数,使用定时器 15ms 调用一次,但是有误差
[备 注] 定义坐标轴方向 —— x:正前;y:右; z:上
实际坐标轴方向 —— y:正前;x:右;-z:上
由于安装时芯片翻了个个,所以坐标轴方向有变动,注意区分
*****************************************************************************/
void Read_LSM6D(void) {
IIC_Read(STATUS_REG, &status.m_Byte, 1); //读状态寄存器的值到缓存
(status.m_Bit.GDA == )
{
IIC_Read(, AngleSpeed.m_Byte, );
data.gyro.x = AngleSpeed.m_Data.Y * / ;
data.gyro.y = AngleSpeed.m_Data.X * / ;
data.gyro.z = -AngleSpeed.m_Data.Z * / ;
}
(status.m_Bit.XLDA == )
{
IIC_Read(, Acceleration.m_Byte, );
data.accel.x = Acceleration.m_Data.Y * / ;
data.accel.y = Acceleration.m_Data.X * / ;
data.accel.z = -Acceleration.m_Data.Z * / ;
}
}
四、总结
本文详细阐述了 LSM6DS3TR 六轴传感器的驱动配置与数据读取流程。通过 IIC 接口完成复位、参数初始化及数据校验,实现了加速度与角速度数据的实时获取。开发者可根据实际硬件连接调整 IIC 引脚定义,并根据应用需求修改量程与输出速率配置。


