页面加载中,请稍候
来源:嵌入式Linux系统开发发布时间:2023-03-193186浏览
询问 AI博主最近在调试 lsm6dso,一款集合加速度和陀螺仪的模块,主要运用在手持设备中,先看效果视频:
LSM6DSO 是 ST 公司的六轴传感器,集成三轴加速度和三轴陀螺仪。
ST 对于自己出的传感器,都会提供驱动 demo,放在 github,如下:
https://github.com/STMicroelectronics
其中分为不同的平台,有的是仅仅基于 C 语言的平台无关的驱动,有的是基于 STM32,有的是基于 Linux,有的是基于 Android,一开始学习的时候,建议大家下载平台无关的驱动:

若后续大家想移植到 Linux、Android ,也可以在这里可以找到工程:
https://github.com/STMicroelectronics/STMems_Standard_C_drivers
https://github.com/STMicroelectronics/st-mems-android-linux-drivers-input
https://github.com/STMicroelectronics/STMems_Linux_IIO_drivers
https://github.com/STMicroelectronics/STMems_Android_Sensor_HAL_IIO
lsm6dso-pid 参考代码:
https://github.com/STMicroelectronics/STMems_Standard_C_drivers/tree/master/lsm6dso_STdC
arduino、micropython 参考代码:
https://github.com/arduino-libraries/Arduino_LSM6DSOX
https://github.com/micropython-Chinese-Community/mpy-lib/tree/master/sensor/LSM6DSO
数据手册下载,其中包含有中文应用手册:
https://www.st.com/zh/mems-and-sensors/lsm6dso.html

一共 14 个 PIN 脚,每个引脚的详细说明可以参考数据手册。总的来说就是 I2C 和 SPI 无法同时使用,因为它们有共用 PIN 脚。

一般用模式 1,模式 2、模式 3、模式 4 比较复杂,可以外接传感器,摄像头等。

LSM6DSO 从机地址是 110101x ,最后一位 x 和一个 PIN 的状态有关系。如果 SDO/SA0 是高,从机地址是 1101011。如果 SDO/SA0 是低,从机地址是 1101010。
这个方案可以使得一路 I2C bus 挂两个 lsm6dso,同时使用。
加上读写位,总结如下:

传输示意图如下:


该器件有 60+ 个寄存器,主要的几个如下:
1、设备 ID
只读,出厂已经固化在硬件里面了,可以通过读写这个寄存器,判断设备是否存在,通讯是否正常,设备的 ID 是 0x6C。

2、加速度控制寄存器
这个寄存器可以设置加速度的量程、输出速率等;


3、陀螺仪控制寄存器
这个寄存器可以设置陀螺仪的量程、输出速率等;


4、状态寄存器
通过读取这个寄存器可以判断,传感器是否有新的数据。

5、温度传感器
2个寄存器,输出的是有符号数据。

6、陀螺仪数据传感器
总共 6 个寄存器,分 x、y、z 三轴的高位和低位,这里要注意,输出的是有符号数据。



7、加速度数据传感器
总共 6 个寄存器,分 x、y、z 三轴的高位和低位,这里要注意,输出的是有符号数据。



博主用的是轮询去读数据,大家也可以配置成中断方式。另外,博主是直接去各个数据寄存器去读数据,大家也可以配置成去器件 FIFO 中读数据。该器件有 3Kbyte 的 FIFO,若使用压缩算法,可以达到 9Kbyte。
初始化部分:
i2c_init();
LSM6DSO_Check();
u8LSM6DSO_Check(void)
{
u8temp;
temp=LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_WHO_AM_I);
if(temp==0X6C)
return0;
else
return1;
}
LSM6DSO_WriteOneByte(LSM6DSO_ADDRESS,LSM6DSO_CTRL1_XL,ODR_XL_104Hz|FS_XL_2g);
LSM6DSO_WriteOneByte(LSM6DSO_ADDRESS,LSM6DSO_CTRL2_G,ODR_G_104Hz|FS_G_250);
读数据
while(1)
{
status=LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_STATUS_REG);
if(statusTEM_DATA_AVAILABLE)
{
temp_raw=LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUT_TEMP_L)|(LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUT_TEMP_H)<<8);
temp_deg=temp_raw/TEMP_LSB_PER_DEG+TEMP_OFFSET_DEG;
sprintf((char*)temperature,"temperature:%02f",temp_deg);
LCD_ShowString(30,90,200,16,16,temperature);
}
if(statusGYR_DATA_AVAILABLE)
{
gyr_x_raw=LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUTX_L_G)|(LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUTX_H_G)<<8);
gyr_y_raw=LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUTY_L_G)|(LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUTY_H_G)<<8);
gyr_z_raw=LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUTZ_L_G)|(LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUTZ_H_G)<<8);
gyr_x=gyr_x_raw*GYR_LSB_250_PER;
gyr_y=gyr_y_raw*GYR_LSB_250_PER;
gyr_z=gyr_z_raw*GYR_LSB_250_PER;
printf("Gyro:X:%02fmdps,Y:%02fmdps,Z:%02fmdps\r\n",gyr_x,gyr_y,gyr_z);
}
if(statusACC_DATA_AVAILABLE)
{
acc_x_raw=LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUTX_L_A)|(LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUTX_H_A)<<8);
acc_y_raw=LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUTY_L_A)|(LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUTY_H_A)<<8);
acc_z_raw=LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUTZ_L_A)|(LSM6DSO_ReadOneByte(LSM6DSO_ADDRESS,LSM6DSO_OUTZ_H_A)<<8);
acc_x=acc_x_raw*ACC_LSB_2G_PER;
acc_y=acc_y_raw*ACC_LSB_2G_PER;
acc_z=acc_z_raw*ACC_LSB_2G_PER;
printf("Acc:X:%02fmg,Y:%02fmg,Z:%02fmg\r\n",acc_x,acc_y,acc_z);
}
寄存器定义
#defineLSM6DSO_ADDRESS0xD4
#defineLSM6DSO_ID0x6C
#defineLSM6DSO_SDO_CRTL0x02
#defineLSM6DSO_FIFO_CTRL10x07
#defineLSM6DSO_FIFO_CTRL20x08
#defineLSM6DSO_FIFO_CTRL30x09
#defineLSM6DSO_FIFO_CTRL40x0A
#defineLSM6DSO_COUNTER_BDR_REG10x0B
#defineLSM6DSO_COUNTER_BDR_REG20x0C
#defineLSM6DSO_INT1_CTRL0x0D
#defineLSM6DSO_INT2_CTRL0x0E
#defineLSM6DSO_WHO_AM_I0x0F
#defineLSM6DSO_CTRL1_XL0x10
//bit[7:4]
typedefenum{
ODR_XL_OFF=(0<<4),
ODR_XL_1Hz6_LOW_POWER_ONLY=(11<<4),
ODR_XL_12Hz5=(1<<4),
ODR_XL_26Hz=(2<<4),
ODR_XL_52Hz=(3<<4),
ODR_XL_104Hz=(4<<4),
ODR_XL_208Hz=(5<<4),
ODR_XL_416Hz=(6<<4),
ODR_XL_833Hz=(7<<4),
ODR_XL_1k66Hz=(8<<4),
ODR_XL_3k33Hz=(9<<4),
ODR_XL_6k66Hz=(10<<4),
}lsm6dso_odr_xl_t;
//bit[3:2]
typedefenum{
FS_XL_2g=(0<<2),
FS_XL_4g=(2<<2),
FS_XL_8g=(3<<2),
FS_XL_16g_SPIT_OIS_IU_FS=(1<<2),/*checkXL_FS_MODE=‘0’inCTRL8_XL(17h)*/
}lsm6dso_fs_xl_t;
#defineACC_LSB_2G_PER0.061
#defineACC_LSB_4G_PER0.122
#defineACC_LSB_8G_PER0.244
#defineACC_LSB_16G_PER0.488
#defineLSM6DSO_CTRL2_G0x11
//bit[7:4]
typedefenum{
ODR_G_OFF=(0<<4),
ODR_G_12Hz5=(1<<4),
ODR_G_26Hz=(2<<4),
ODR_G_52Hz=(3<<4),
ODR_G_104Hz=(4<<4),
ODR_G_208Hz=(5<<4),
ODR_G_416Hz=(6<<4),
ODR_G_833Hz=(7<<4),
ODR_G_1k66Hz=(8<<4),
ODR_G_3k33Hz=(9<<4),
ODR_G_6k66Hz=(10<<4),
ODR_G_NOT_AVAILABLE=(11<<4),
}lsm6dso_odr_g_t;
//bit[3:2]
typedefenum{
FS_G_250=(0<<2),
FS_G_500=(1<<2),
FS_G_1000=(2<<2),
FS_G_2000=(3<<2),
}lsm6dso_fs_g_t;
#defineGYR_LSB_250_PER8.75
#defineGYR_LSB_500_PER17.50
#defineGYR_LSB_1000_PER35.0
#defineGYR_LSB_2000_PER70.0
#defineLSM6DSO_CTRL3_C0x12
#defineLSM6DSO_CTRL4_C0x13
#defineLSM6DSO_CTRL5_C0x14
#defineLSM6DSO_CTRL6_C0x15
#defineLSM6DSO_CTRL7_G0x16
#defineLSM6DSO_CTRL8_XL0x17
#defineLSM6DSO_CTRL9_XL0x18
#defineLSM6DSO_CTRL10_C0x19
#defineLSM6DSO_ALL_INT_SRC0x1A
#defineLSM6DSO_WAKE_UP_SRC0x1B
#defineLSM6DSO_TAP_SRC0x1C
#defineLSM6DSO_D6D_SRC0x1D
#defineLSM6DSO_STATUS_REG0x1E
#defineTEM_DATA_AVAILABLE(1<<2)
#defineGYR_DATA_AVAILABLE(1<<1)
#defineACC_DATA_AVAILABLE(1<<0)
#defineLSM6DSO_OUT_TEMP_L0x20
#defineLSM6DSO_OUT_TEMP_H0x21
#defineTEMP_LSB_PER_DEG256.0
#defineTEMP_OFFSET_DEG25
#defineLSM6DSO_OUTX_L_G0x22
#defineLSM6DSO_OUTX_H_G0x23
#defineLSM6DSO_OUTY_L_G0x24
#defineLSM6DSO_OUTY_H_G0x25
#defineLSM6DSO_OUTZ_L_G0x26
#defineLSM6DSO_OUTZ_H_G0x27
#defineLSM6DSO_OUTX_L_A0x28
#defineLSM6DSO_OUTX_H_A0x29
#defineLSM6DSO_OUTY_L_A0x2A
#defineLSM6DSO_OUTY_H_A0x2B
#defineLSM6DSO_OUTZ_L_A0x2C
#defineLSM6DSO_OUTZ_H_A0x2D
新闻来源:嵌入式Linux系统开发,文中所述为作者独立观点,不代表icspec立场。更多精彩资讯请下载icspec App。如对本稿件有异议,请联系微信客服specltkj。
暂无评论哦,快来评论一下吧!
2026-07-08
2026-06-23