STM32H5开发陀螺仪LSM6DSV16X(1)----轮询获取陀螺仪数据
概述
本文将介绍如何通过轮询的方式从LSM6DSV16X六轴惯性传感器获取陀螺仪数据。轮询模式是一种常用的传感器读取方法。主控MCU周期性查询陀螺仪输出寄存器,无需依赖中断机制即可实现数据采集。该方法适用于响应时延要求不高、系统结构简单的场景。方便快速验证陀螺仪功能或进行基本测试。
我目前正在学习ST 课程。如果需要样品,可以进群申请:615061293。
视频教学
[https://www.bilibili.com/video/BV1FQojYaE2M/]
样品申请
[https://www.wjx.top/vm/OhcKxJk.aspx#]
源码下载
【https://download.csdn.net/download/qq_24312945/91359685】
硬件准备
首先需要准备一块开发板。我这里准备的是自己画的开发板。如果您需要的话,可以申请。
主控为STM32H503CB,陀螺仪为LSM6DSV16X,磁力计为LIS2MDL。
参考程序
https://github.com/CoreMaker-lab/STM32H503_LSM6DSV16X_LIS2MDL
https://gitee.com/CoreMaker/STM32H503_LSM6DSV16X_LIS2MDL
通信模式
对于LSM6DSV16X,可以使用SPI或IIC进行通信。最小系统图如下所示。
当CS引脚为1时,为IIC模式。
本文使用的板卡原理图如下所示。
管脚定义
IIC通信模式
当使用IIC 通讯模式时,SA0 用于控制IIC 的地址位。 IIC的地址可以通过SDO/SA0引脚修改。
SDO/SA0 引脚可用于修改设备地址的最低有效位。如果SDO/SA0 引脚连接到电源电压,则LSb(最低有效位)为“1”(地址1101011b);否则,如果SDO/SA0 引脚接地,则LSb 的值为“0”(地址1101010b)。
IIC接口如下图所示。使用的主要引脚是CS、SCL、SDA 和SA0。
速率
该模块支持的速度为普通模式(100k)和快速模式(400k)。
生成STM32CUBEMX
使用STM32CUBEMX 生成例程。这里使用的MCU是STM32H503CB。
配置时钟树,将时钟配置为250M。
串口配置
查看原理图,PB6和PB7设置为开发板的串口。
配置串口速率为2000000。
IIC配置
将IIC配置为快速模式,速度为400k。
CS和SA0设置
ICASHE
修改堆栈
串口重定向
打开魔棒查看MicroLIB
在main.c中,添加头文件。如果没有,将会出现标识符“FILE”未定义的错误。
/* USER CODE BEGIN 包含*/#include 'stdio.h'/* USER CODE END 包含*/函数声明和串口重定向:
/* 用户代码开始PFP */int fputc(int ch, FILE *f){ HAL_UART_Transmit(huart1, (uint8_t *)ch, 1,0xFFFF); return ch;}/* 用户代码结束PFP */
参考程序
https://github.com/STMicroelectronics/lsm6dsv16x-pid/tree/main
初始换管脚
由于需要写入LSM6DSV16X_I2C_ADD_L并处于IIC模式。
因此使CS为高电平并配置为IIC模式。配置SA0为高电平。
printf('你好!n'); HAL_GPIO_WritePin(CS1_GPIO_端口、CS1_Pin、GPIO_PIN_SET); HAL_GPIO_WritePin(SA0_GPIO_端口、SA0_Pin、GPIO_PIN_RESET); HAL_GPIO_WritePin(CS2_GPIO_端口、CS2_Pin、GPIO_PIN_SET); HAL_延迟(100); lsm6dsv16x_reset_t 首先; stmdev_ctx_t dev_ctx; /* 初始化mems驱动接口*/dev_ctx.write_reg=platform_write; dev_ctx.read_reg=platform_read; dev_ctx.mdelay=platform_delay; dev_ctx.handle=SENSOR_BUS; /* 初始化测试平台*///platform_init(dev_ctx.handle); /* 等待传感器启动时间*/platform_delay(BOOT_TIME);
获取ID
可以从WHO_AM_I(0Fh)中获取固定值来判断是否为0x70。
lsm6dsv16x_device_id_get是获取函数。
对应的获取ID驱动如下。
/* 检查设备ID */lsm6dsv16x_device_id_get(dev_ctx, whoamI); printf('LSM6DSV16X_ID=0x%x,whoamI=0x%x',LSM6DSV16X_ID,whoamI); if (whoamI!=LSM6DSV16X_ID) while (1);
复位操作
可以通过向CTRL3 (12h) 的SW_RESET 寄存器写入1 来复位。
lsm6dsv16x_reset_set 是复位函数。
对应的驱动如下。
/* 恢复默认配置*/lsm6dsv16x_reset_set(dev_ctx, LSM6DSV16X_RESTORE_CTRL_REGS);执行{ lsm6dsv16x_reset_get(dev_ctx, rst); while (首先!=LSM6DSV16X_READY);
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 将其打开。
对应的驱动如下。
/* 启用块数据更新*/lsm6dsv16x_block_data_update_set(dev_ctx, PROPERTY_ENABLE);
设置量程和速率
速率可以通过CTRL1(10h)设置加速度和CTRL2(11h)设置角速度速率。
可以通过CTRL8(17h)设置加速范围。角速度范围可以通过CTRL6 (15h) 设置。
要设置加速度和角速度的范围和速率,可以使用以下函数。
/* 设置输出数据速率。 * 所选数据速率必须等于或大于MLC 数据速率。 */lsm6dsv16x_xl_data_rate_set(dev_ctx, LSM6DSV16X_ODR_AT_7Hz5); lsm6dsv16x_gy_data_rate_set(dev_ctx, LSM6DSV16X_ODR_AT_15Hz); /* 设置满刻度*/lsm6dsv16x_xl_full_scale_set(dev_ctx, LSM6DSV16X_2g); lsm6dsv16x_gy_full_scale_set(dev_ctx,LSM6DSV16X_2000dps);
配置过滤链
/* 配置过滤链*/filt_settting_mask.drdy=PROPERTY_ENABLE; filt_settting_mask.irq_xl=PROPERTY_ENABLE; filt_settting_mask.irq_g=PROPERTY_ENABLE; lsm6dsv16x_filt_setdling_mask_set(dev_ctx, filt_setdling_mask); lsm6dsv16x_filt_gy_lp1_set(dev_ctx, PROPERTY_ENABLE); lsm6dsv16x_filt_gy_lp1_bandwidth_set(dev_ctx,LSM6DSV16X_GY_ULTRA_LIGHT); lsm6dsv16x_filt_xl_lp2_set(dev_ctx, PROPERTY_ENABLE); lsm6dsv16x_filt_xl_lp2_bandwidth_set(dev_ctx,LSM6DSV16X_XL_STRONG);
轮询读取数据
进入无限循环,不断检查是否有新数据(加速度、角速率、温度)。对于每种类型的数据(加速度、角速率、温度),如果有新数据,则读取原始数据,转换为相应的单位(毫克、毫度每秒、摄氏度),并通过串行输出打印。
要确定数据是否准备好,可以访问STATUS_REG(1Eh)。
/* 仅当新的xl 值可用时才读取输出*/lsm6dsv16x_flag_data_ready_get(dev_ctx, drdy);对于加速度数据,可以通过28-2D获得。
加速度数据首先以原始格式(通常是整数)读取,然后需要转换为更有意义的单位,例如重力毫升(mg)。这里的转换函数lsm6dsv16x_from_fs2_to_mg() 根据加速度计的范围(此处假设为2g)将原始数据转换为毫重力单位。
Acceleration_mg[0]=lsm6dsv16x_from_fs2_to_mg(data_raw_acceleration[0]);另外三行代码分别转换X、Y、Z轴的加速度数据。
LSM6DSV16X 加速度计通常具有固定的位分辨率,例如16 位(即输出值为16 位整数)。这意味着加速度计可以输出的不同值的总数为2^16=65536。这些值均匀分布在-2g 到+2g 范围内。
因此,该范围(4g 或4000 mg)被分为65536 级。
每步大小为4000 mg/655360.061 mg/LSB
因此,函数((float_t)lsb) * 0.061f 中的乘法将原始整数值转换为以毫(mg) 为单位的加速度值。这种转换是将加速度计的原始读数转换为实际物理测量值所必需的。
if (drdy.drdy_xl) { /* 读取加速度场数据*/memset(data_raw_acceleration,0x00, 3 * sizeof(int16_t)); lsm6dsv16x_acceleration_raw_get(dev_ctx, data_raw_acceleration); Acceleration_mg[0]=lsm6dsv16x_from_fs2_to_mg(data_raw_acceleration[0]); Acceleration_mg[1]=lsm6dsv16x_from_fs2_to_mg(data_raw_acceleration[1]); Acceleration_mg[2]=lsm6dsv16x_from_fs2_to_mg(data_raw_acceleration[2]); printf('加速度[mg]:%4.2ft%4.2ft%4.2frn',acceleration_mg[0],acceleration_mg[1],acceleration_mg[2]); }对于角速度数据,可以通过22-2D得到。
在LSM6DSV16X 传感器中,函数lsm6dsv16x_from_fs2000_to_mdps(int16_t lsb) 用于将原始传感器数据(以最低有效位(LSB) 为单位)转换为以毫度每秒(mdps) 为单位的角速度值。这里70.0f是用于从原始数据单位转换为实际物理单位的转换因子。
具体来说,该转换因子基于传感器的灵敏度或比例因子。对于LSM6DSV16X 传感器,当满量程设置为2000 dps(度/秒)时,每个LSB 代表70 mdps 的角速度值。
/* 仅当新的xl 值可用时才读取输出*/if (
drdy.drdy_gy) { /* Read angular rate field data */ memset(data_raw_angular_rate, 0x00, 3 * sizeof(int16_t)); lsm6dsv16x_angular_rate_raw_get(&dev_ctx, data_raw_angular_rate); angular_rate_mdps[0] = lsm6dsv16x_from_fs2000_to_mdps(data_raw_angular_rate[0]); angular_rate_mdps[1] = lsm6dsv16x_from_fs2000_to_mdps(data_raw_angular_rate[1]); angular_rate_mdps[2] = lsm6dsv16x_from_fs2000_to_mdps(data_raw_angular_rate[2]); printf("Angular rate [mdps]:%4.2ft%4.2ft%4.2frn",angular_rate_mdps[0], angular_rate_mdps[1], angular_rate_mdps[2]); }对于温度数据,可以通过20-21进行获取。 if (drdy.drdy_temp) { /* Read temperature data */ memset(&data_raw_temperature, 0x00, sizeof(int16_t)); lsm6dsv16x_temperature_raw_get(&dev_ctx, &data_raw_temperature); temperature_degC = lsm6dsv16x_from_lsb_to_celsius( data_raw_temperature); printf("Temperature [degC]:%6.2frn", temperature_degC); }审核编辑 黄宇