概述
本文档旨在详细介绍如何配置和读取LSM6DSOW传感器的FIFO数据。LSM6DSOW是一款高性能的6轴IMU(惯性测量单元),集成了三轴加速度计和三轴陀螺仪。FIFO(先进先出)缓冲区是LSM6DSOW的重要功能之一,它能够有效地存储传感器数据,减少主机的读取频率,从而降低功耗和提高数据采集效率。
最近在弄ST和瑞萨RA的课程,需要样片的可以加群申请:615061293 。
视频教学
https://www.bilibili.com/video/BV1Dw4m1r712/
样品申请
https://www.wjx.top/vm/OhcKxJk.aspx#
源码下载
https://download.csdn.net/download/qq_24312945/89592307
硬件准备
首先需要准备一个开发板,这里我准备的是自己绘制的开发板,需要的可以进行申请。 主控为STM32H503CB,陀螺仪为LSM6DSOW,磁力计为LIS2MDL。
主要内容
- 初始化LSM6DSOW传感器并检查其设备ID
- 恢复传感器默认配置并设置必要的参数
- 配置FIFO模式和水印阈值
- 设置加速度计和陀螺仪的数据速率
- 连续读取FIFO中的传感器数据并解析输出
LSM6DSOW支持六种不同的FIFO模式,每种模式适用于不同的应用场景:
- Bypass Mode(旁路模式):
○ 在旁路模式下,FIFO不运行,传感器数据直接输出,不存储在FIFO中。该模式常用于实时数据读取。 - FIFO Mode(FIFO模式):
○ 在FIFO模式下,数据连续存储到FIFO中,直到FIFO满。当FIFO满时,旧数据将被新数据覆盖。适用于需要连续存储数据供后续处理的情况。 - Continuous Mode(连续模式):
○ 在连续模式下,FIFO始终保存最新的数据,当FIFO满时,旧数据被丢弃,新数据继续写入FIFO。适用于需要实时监控最新数据的应用。 - Continuous to FIFO Mode(连续到FIFO模式):
○ 开始时处于连续模式,当检测到某个事件时切换到FIFO模式。适用于在特定事件发生后保存数据。 - Bypass to Continuous Mode(旁路到连续模式):
○ 开始时处于旁路模式,当检测到某个事件时切换到连续模式。适用于事件发生后开始实时数据监控。 - Bypass to FIFO Mode(旁路到FIFO模式):
○ 开始时处于旁路模式,当检测到某个事件时切换到FIFO模式,开始存储数据。适用于事件发生后开始数据记录。
生成STM32CUBEMX
用STM32CUBEMX生成例程,这里使用MCU为STM32H503CB。
配置时钟树,配置时钟为250M。
串口配置
查看原理图,PA9和PA10设置为开发板的串口。
配置串口,速率为2000000。
IIC配置
LSM6DSOW最大IIC通讯速率为400k。
配置IIC速度为400k
CS和SA0设置
由于还有一个磁力计,需要把该CS也使能。
INT设置
配置为输入检测模式。
ICASHE
修改堆栈
串口重定向
打开魔术棒,勾选MicroLIB
在main.c中,添加头文件,若不添加会出现 identifier "FILE" is undefined报错。
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */
函数声明和串口重定向:
/* USER CODE BEGIN PFP */
int fputc(int ch, FILE *f){
HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
/* USER CODE END PFP */
参考驱动程序
https://github.com/STMicroelectronics/lsm6dso-pid
初始化管脚
由于需要向LSM6DSO_I2C_ADD_L写入以及为IIC模式。
所以使能CS为高电平,配置为IIC模式。 配置SA0为低电平。
printf("HELLO!n");
HAL_GPIO_WritePin(CS1_GPIO_Port, CS1_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(SA0_GPIO_Port, SA0_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(CS2_GPIO_Port, CS2_Pin, GPIO_PIN_SET);
HAL_Delay(100);
stmdev_ctx_t dev_ctx;
/* Initialize mems driver interface */
dev_ctx.write_reg = platform_write;
dev_ctx.read_reg = platform_read;
dev_ctx.mdelay = platform_delay;
dev_ctx.handle = &SENSOR_BUS;
/* Init test platform */
// platform_init();
/* Wait sensor boot time */
platform_delay(BOOT_TIME);
获取ID
可以向WHO_AM_I (0Fh)获取固定值,判断是否为0x6C
lsm6dso_device_id_get为获取函数。
对应的获取ID驱动程序,如下所示。
/* Check device ID */
lsm6dso_device_id_get(&dev_ctx, &whoamI);
printf("LSM6DSO_ID=0x%x,whoamI=0x%x",LSM6DSO_ID,whoamI);
if (whoamI != LSM6DSO_ID)
while (1);
复位操作
可以向CTRL3 (12h)的SW_RESET寄存器写入1进行复位。
lsm6dso_reset_set为重置函数。
对应的驱动程序,如下所示。
/* Restore default configuration */
lsm6dso_reset_set(&dev_ctx, PROPERTY_ENABLE);
do {
lsm6dso_reset_get(&dev_ctx, &rst);
} while (rst);
关闭I3C
/* Disable I3C interface */
lsm6dso_i3c_disable_set(&dev_ctx, LSM6DSO_I3C_DISABLE);
BDU设置
在很多传感器中,数据通常被存储在输出寄存器中,这些寄存器分为两部分:MSB和LSB。这两部分共同表示一个完整的数据值。例如,在一个加速度计中,MSB和LSB可能共同表示一个加速度的测量值。
连续更新模式(BDU = ‘0’):在默认模式下,输出寄存器的值会持续不断地被更新。这意味着在你读取MSB和LSB的时候,寄存器中的数据可能会因为新的测量数据而更新。这可能导致一个问题:当你读取MSB时,如果寄存器更新了,接下来读取的LSB可能就是新的测量值的一部分,而不是与MSB相对应的值。这样,你得到的就是一个“拼凑”的数据,它可能无法准确代表任何实际的测量时刻。
块数据更新(BDU)模式(BDU = ‘1’):当激活BDU功能时,输出寄存器中的内容不会在读取MSB和LSB之间更新。这就意味着一旦开始读取数据(无论是先读MSB还是LSB),寄存器中的那一组数据就被“锁定”,直到两部分都被读取完毕。这样可以确保你读取的MSB和LSB是同一测量时刻的数据,避免了读取到代表不同采样时刻的数据。
简而言之,BDU位的作用是确保在读取数据时,输出寄存器的内容保持稳定,从而避免读取到拼凑或错误的数据。这对于需要高精度和稳定性的应用尤为重要。
可以向CTRL3 (12h)的BDU寄存器写入1进行开启。
对应的驱动程序,如下所示。
/* Enable Block Data Update */
lsm6dso_block_data_update_set(&dev_ctx, PROPERTY_ENABLE);
设置量程和速率
速率可以通过CTRL1 (10h)设置加速度速率和CTRL2 (11h)进行设置角速度速率。
设置加速度量程可以通过CTRL1 (10h)进行设置。
设置角速度量程可以通过CTRL2 (11h)进行设置。
设置加速度和角速度的量程和速率可以使用如下函数。
/* Set Output Data Rate */
lsm6dso_xl_data_rate_set(&dev_ctx, LSM6DSO_XL_ODR_12Hz5);
lsm6dso_gy_data_rate_set(&dev_ctx, LSM6DSO_GY_ODR_12Hz5);
/* Set full scale */
lsm6dso_xl_full_scale_set(&dev_ctx, LSM6DSO_2g);
lsm6dso_gy_full_scale_set(&dev_ctx, LSM6DSO_2000dps);
设置FIFO水印
可编程FIFO阈值可以通过FIFO_CTRL1(07h)和FIFO_CTRL2(08h)寄存器中的WTM8[0]位设置。为了监视FIFO状态,可以读取专用寄存器(FIFO_STATUS1(3Ah),FIFO_STATUS2(3Bh)),以检测FIFO溢出事件、FIFO满状态、FIFO空状态、FIFO水位状态和FIFO中存储的未读样本数。
LSM6DSOW传感器通过一系列控制寄存器来配置和管理FIFO。通过配置WTM,用户可以灵活地管理传感器数据的批处理。当数据量达到设定的阈值时,主处理器可以一次性读取大量数据,提高数据读取效率,减少频繁的I/O操作。 1 LSB = 1传感器(6字节) + TAG(1字节)写入FIFO
/* Set FIFO watermark (number of unread sensor data TAG + 6 bytes
* stored in FIFO) to 10 samples
*/
lsm6dso_fifo_watermark_set(&dev_ctx, 10);
FIFO_CTRL3寄存器用于选择陀螺仪和加速度计数据在FIFO中的批处理数据速率(BDR)。每个传感器都有独立的控制位,可以设置不同的批处理数据速率,从而控制数据写入FIFO的频率。
/* Set FIFO batch XL/Gyro ODR to 12.5Hz */
lsm6dso_fifo_xl_batch_set(&dev_ctx, LSM6DSO_XL_BATCHED_AT_12Hz5);
lsm6dso_fifo_gy_batch_set(&dev_ctx, LSM6DSO_GY_BATCHED_AT_12Hz5);
FIFO_CTRL4寄存器用于配置LSM6DSOW传感器的FIFO模式、时间戳批处理和温度数据批处理速率。该寄存器包含多个字段,每个字段的功能如下所述。
FIFO_MODE[2:0]: FIFO模式选择
● 用于选择FIFO的工作模式。
● 000: Bypass mode(旁路模式),FIFO禁用
● 001: FIFO mode(FIFO模式),FIFO满时停止收集数据
● 010: 保留
● 011: Continuous-to-FIFO mode(连续到FIFO模式),连续模式直到触发器释放,然后进入FIFO模式
● 100: Bypass-to-continuous mode(旁路到连续模式),旁路模式直到触发器释放,然后进入连续模式
● 101: 保留
● 110: Continuous mode(连续模式),FIFO满时新数据覆盖旧数据
● 111: Bypass-to-FIFO mode(旁路到FIFO模式),旁路模式直到触发器释放,然后进入FIFO模式
/* Set FIFO mode to Stream mode (aka Continuous Mode) */
lsm6dso_fifo_mode_set(&dev_ctx, LSM6DSO_STREAM_MODE);
设置中断
COUNTER_BDR_REG1寄存器用于配置批处理数据速率计数器的相关参数。该寄存器允许用户选择数据准备模式、重置内部计数器以及选择批处理事件的触发器。以下是COUNTER_BDR_REG1寄存器的详细描述。
COUNTER_BDR_REG1寄存器位字段
● dataready_pulsed: 启用脉冲数据准备模式
○ 0: 数据准备锁存模式(默认),仅在接口读取后返回0;
○ 1: 数据准备脉冲模式(数据准备脉冲持续时间为75微秒)。
INT1_CTRL寄存器用于配置INT1引脚的控制信号。该寄存器的每个位可以启用一个信号,当MIPI I3CSM动态地址未分配时,信号可以通过INT1引脚传输。一些位还可以在使用MIPI I3CSM接口时触发IBI(带内中断)。引脚的输出是此处选择的信号与MD1_CFG(5Eh)中的信号的或组合。
INT1_CTRL寄存器字段描述
● DEN_DRDY_flag: 发送DEN_DRDY(DEN标记在传感器数据标志上)到INT1引脚。
● INT1_CNT_BDR: 启用COUNTER_BDR_IA中断在INT1引脚上。
● INT1_FIFO_FULL: 启用FIFO满中断在INT1引脚上。当使用MIPI I3CSM接口时,它还可以用于触发IBI。
● INT1_FIFO_OVR: 启用FIFO溢出中断在INT1引脚上。当使用MIPI I3CSM接口时,它还可以用于触发IBI。
● INT1_FIFO_TH: 启用FIFO阈值中断在INT1引脚上。当使用MIPI I3CSM接口时,它还可以用于触发IBI。
● INT1_BOOT: 启用引导状态在INT1引脚上。
● INT1_DRDY_G: 启用陀螺仪数据准备中断在INT1引脚上。当使用MIPI I3CSM接口时,它还可以用于触发IBI。
● INT1_DRDY_XL: 启用加速度计数据准备中断在INT1引脚上。当使用MIPI I3CSM接口时,它还可以用于触发IBI。
lsm6dso_pin_int1_route_get(&dev_ctx, &int1_route);
int1_route.fifo_th = PROPERTY_ENABLE;
lsm6dso_pin_int1_route_set(&dev_ctx, int1_route);
获取FIFO数据
FIFO_STATUS寄存器用于监控LSM6DSOW传感器FIFO的状态。它们包括FIFO_STATUS1(3Ah)和FIFO_STATUS2(3Bh),分别用于报告未读数据和FIFO状态信息。
当FIFO中的数据量达到或超过预设的水位线时,FIFO_WTM_IA位将被置为1。这意味着主处理器可以通过读取该位的状态来确定何时需要处理FIFO中的数据。例如,当数据量达到水位线时,触发一次中断,主处理器读取并处理FIFO中的数据,然后继续下一轮数据采集。
DIFF_FIFO 位于 FIFO_STATUS1 (3Ah) 和 FIFO_STATUS2 (3Bh) 寄存器中,用于指示FIFO中未读传感器数据的数量。它包括两个部分:
● DIFF_FIFO7:07:07:0: 位于 FIFO_STATUS1 寄存器中,表示未读数据的低8位。
● DIFF_FIFO9:89:89:8: 位于 FIFO_STATUS2 寄存器中,表示未读数据的高2位。
DIFF_FIFO字段用于跟踪FIFO中未读的数据量。通过读取DIFF_FIFO,可以确定FIFO中当前存储了多少数据,这对于决定何时读取FIFO中的数据非常重要。该字段的值在数据从FIFO中读取时会自动更新。
FIFO_DATA_OUT_TAG (78h)寄存器用于标识FIFO中的传感器数据来源。该寄存器包含标识符(TAG),用于指示数据是由哪个传感器生成的,并帮助用户正确地解析FIFO中的数据。
TAG_SENSOR: 标识FIFO中的传感器数据源。根据传感器类型和数据源,该字段值表示具体的传感器数据。详细见下表。
FIFO_DATA_OUT_TAG 寄存器提供了数据标签,用于识别FIFO中存储的数据来源。这对于解析和处理从FIFO中读取的数据非常重要。通过TAG字段,用户可以区分不同传感器的数据,并采取适当的处理措施。
FIFO_DATA_OUT_X, FIFO_DATA_OUT_Y 和 FIFO_DATA_OUT_Z 寄存器,这些寄存器用于读取LSM6DSOW传感器的FIFO中的X、Y和Z轴数据。每个轴的数据由两个寄存器组成:一个低字节寄存器(_L)和一个高字节寄存器(_H)。
为了从FIFO中读取加速度计或陀螺仪的X、Y、Z轴数据,需要依次读取对应的低字节和高字节寄存器,并将它们组合成一个完整的16位数据。
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
uint16_t num = 0;
uint8_t wmflag = 0;
lsm6dso_fifo_tag_t reg_tag;
axis3bit16_t dummy;
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0))
{
/* Read watermark flag */
lsm6dso_fifo_wtm_flag_get(&dev_ctx, &wmflag);
if (wmflag > 0) {
/* Read number of samples in FIFO */
lsm6dso_fifo_data_level_get(&dev_ctx, &num);
while (num--) {
/* Read FIFO tag */
lsm6dso_fifo_sensor_tag_get(&dev_ctx, ®_tag);
switch (reg_tag) {
case LSM6DSO_XL_NC_TAG:
memset(data_raw_acceleration.u8bit, 0x00, 3 * sizeof(int16_t));
lsm6dso_fifo_out_raw_get(&dev_ctx, data_raw_acceleration.u8bit);
acceleration_mg[0] =
lsm6dso_from_fs2_to_mg(data_raw_acceleration.i16bit[0]);
acceleration_mg[1] =
lsm6dso_from_fs2_to_mg(data_raw_acceleration.i16bit[1]);
acceleration_mg[2] =
lsm6dso_from_fs2_to_mg(data_raw_acceleration.i16bit[2]);
printf("Acceleration [mg]:%4.2ft%4.2ft%4.2frn",
acceleration_mg[0], acceleration_mg[1], acceleration_mg[2]);
break;
case LSM6DSO_GYRO_NC_TAG:
memset(data_raw_angular_rate.u8bit, 0x00, 3 * sizeof(int16_t));
lsm6dso_fifo_out_raw_get(&dev_ctx, data_raw_angular_rate.u8bit);
angular_rate_mdps[0] =
lsm6dso_from_fs2000_to_mdps(data_raw_angular_rate.i16bit[0]);
angular_rate_mdps[1] =
lsm6dso_from_fs2000_to_mdps(data_raw_angular_rate.i16bit[1]);
angular_rate_mdps[2] =
lsm6dso_from_fs2000_to_mdps(data_raw_angular_rate.i16bit[2]);
printf("Angular rate [mdps]:%4.2ft%4.2ft%4.2frn",
angular_rate_mdps[0], angular_rate_mdps[1], angular_rate_mdps[2]);
break;
default:
/* Flush unused samples */
memset(dummy.u8bit, 0x00, 3 * sizeof(int16_t));
lsm6dso_fifo_out_raw_get(&dev_ctx, dummy.u8bit);
break;
}
}
}
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
演示
-
mems
+关注
关注
129文章
3896浏览量
190315 -
fifo
+关注
关注
3文章
387浏览量
43532 -
三轴陀螺仪
+关注
关注
2文章
27浏览量
20289 -
stm32cubemx
+关注
关注
5文章
280浏览量
14746
发布评论请先 登录
相关推荐
评论