本文档旨在详细介绍如何配置和读取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支持六种不同的FIFO模式,每种模式适用于不同的应用场景:
用STM32CUBEMX生成例程,这里使用MCU为STM32H503CB。
配置时钟树,配置时钟为250M。
查看原理图,PA9和PA10设置为开发板的串口。
配置串口,速率为2000000。
LSM6DSOW最大IIC通讯速率为400k。
配置IIC速度为400k
由于还有一个磁力计,需要把该CS也使能。
配置为输入检测模式。
打开魔术棒,勾选MicroLIB
在main.c中,添加头文件,若不添加会出现 identifier "FILE" is undefined报错。
/* USER CODE BEGIN Includes */#include"stdio.h"/* USER CODE END Includes */
函数声明和串口重定向:
/* USER CODE BEGIN PFP */intfputc(intch, FILE *f){HAL_UART_Transmit(&huart1 , (uint8_t*)&ch,1,0xFFFF);returnch; }/* 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_tdev_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);
可以向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);
/* Disable I3C interface */lsm6dso_i3c_disable_set(&dev_ctx, LSM6DSO_I3C_DISABLE);
在很多传感器中,数据通常被存储在输出寄存器中,这些寄存器分为两部分: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_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_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_tnum =0;uint8_twmflag =0;lsm6dso_fifo_tag_treg_tag;axis3bit16_tdummy;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) {caseLSM6DSO_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;caseLSM6DSO_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 */
全部0条评论
快来发表一下你的评论吧 !