惯性测量单元(IMU)-QMI8658A驱动开发简要介绍

背景:近日,因工作需要,在项目中开发了一个QMI8658A惯性测量单元的驱动。

概述

QMI8658(A系列)是一款国产六轴姿态传感器,也是一款低噪声、高带宽的六轴惯性测量单元(IMU),主要包含三轴陀螺仪和三轴加速计,还包括温度计。所以该传感器就是读取六轴数据就可以了,姿态解算自己在控制端实现,因为目前attitude engine无法使用了。

内部框图

在这里插入图片描述

PIN脚图及其PIN脚功能定义

在这里插入图片描述
在这里插入图片描述

QMI8658与主版的接口通信方式

在这里插入图片描述

典型应用线路连接示意图

主控器通过SPI总线与QMI8658相连

在这里插入图片描述

主控器通过IIC总线与QMI8658相连

在这里插入图片描述

寄存器总览

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

传感器驱动开发配置常用寄存器

QMI8658在典型传感器模式下,输出原始传感器值,使用寄存器配置和读取传感器的采集的数据,其思路为:上电->复位->陀螺仪校准->自检->配置传感器->读取传感器数据。使用配置的寄存器如下。
在这里插入图片描述

  • QMI8658的片上信息寄存器(Chip Information Register),主要包括WHO_AM_I、REVISION_ID寄存器。
  • QMI8658的配置寄存器(configuration register),主要包括CTRL1(通信接口、传感器使能设置)、CTRL2(加速度测量设置)、CTRL3(陀螺仪测量设置)、CTRL5(传感器数据会处理设置)、CTRL7(使能传感器和配置数据读取)、CTRL8(运动检测控制设置)、CTRL9(主机命令)。
  • QMI8658的FIFO队列寄存器(FIFO register),主要包括FIFO_WTM_TH、FIFO_CTRL(FIFO队列控制寄存器)、FIFO_SMPL_CNT(FIFO队列简单计数寄存器)、FIFO_STATUS(FIFO队列状态寄存器)、FIFO_DATA(FIFO队列数据输出寄存器)。
  • QMI8658的状态和时间戳寄存器(status and time stamp registers),主要包括STATUSINT(传感器数据可用并锁定寄存器)、SATUS0(输出数据状态寄存器)、SATUS1(其他状态寄存器)、TIMESTAMP(时间戳寄存器)。
  • QMI8658的传感器数据输出寄存器(sensor data output register),主要包括TEMP_[H,L](温度数据输出传感器)、A[X,Y,Z][H,L](加速度数据输出传感器)、G[X,Y,Z][H,L](角度数据输出传感器)。
  • QMI8658的按需校准寄存器(Calibration-On-Demand (COD) Status Register),包括COD_SATUS寄存器。 QMI8658的活动检测输出寄存器(Activity Detection Output Registers),主要包括TAP_SATUS寄存器(敲击配置寄存器)、STEP_COUNT(步数计数寄存器)。
  • QMI8658执行外部主机处理器的命令是通过读写CTRL9寄存器实现的,其中CTRL9支持多种指令,以及寄存器的指令读写Write –CTRL9 Protocol和CTRL9 Protocol -R。
  • QMI8658的中断支持,INT1和INT2,在不同模式(SyncSample同步采样、Non-SyncSample非同步采样、DDRY数据就绪)下存在一定的差异。

操作模式(operation mode)

有12种模式,模式的描述与配置方法如下。
在这里插入图片描述

复位

分为上电复位(VDD 和 VDDIO 线从断电状态驱动到有效工作范围初始化)和软件复位(REST寄存器写入0x0B)。
在这里插入图片描述
在这里插入图片描述

校准(COD)

QMI8658 按需校准(calibration on demand,COD)。支持陀螺仪的X/Y轴精度校准,提高精度,减少误差。
在这里插入图片描述

自检

QMI8658 自检(self-test)。支持加速度传感器自检和陀螺仪传感器自检。

加速度自检

在这里插入图片描述

陀螺仪自检

在这里插入图片描述

中断

在这里插入图片描述

同步采样模式

在这里插入图片描述

非同步采样模式

在这里插入图片描述

FIFO队列

在这里插入图片描述
在FIFO中加速度、角速度均占6个字节,根据使能的检测参数的个数,获取的数据可能是6字节或12字节;配置FIFO模式需要对相关的寄存器(如,FIFO_CTRL)进行配置,FIFO的中断、满载、数据、读取和重置等都需要通过对应寄存器处理实现。FIFO样本计数的计算方式:FIFO_Sample_Count (in byte) = 2 * (fifo_smpl_cnt_msb[1:0] * 256 + fifo_smpl_cnt_lsb[7:0])。若是要使用FIFO,更多详细请参考数据手册8 FIFO Description章节。

QMI8658支持监测功能

  • QMI8658运动检测(motion detection)包括无运动检测、任意运动检测、显著运动检测。
  • QMI8658敲击检测(tap detection)包括单点敲击和双点敲击。 QMI8658 计步检测(pedometer detection)。
  • QMI8658运动唤醒(wake on motion)。原理是 极低功耗模式下,主机睡眠后由运动唤醒;类似任意运动检测,但没有数据输出;通过中断唤醒主机。
  • QMI8658 锁定机制(locking mechanism)。在syncSample同步采样模式下启用,读取传感器数据时可以锁定当前样本数据,防止被新数据覆盖,这就类似于影子寄存器机制,确保数据的一致性。

注意事项(开发过程中踩坑)

不同的惯性测量单元(IMU),数据的单位不一样。角速度单位有度每秒(dps)、弧度每秒(radps)等;加速度的单位有重(g)、米每平方秒(mss)。
在这里插入图片描述
在这里插入图片描述

开源驱动

推荐一个git的开源驱动库,SensorLib。驱动尽量找开源的官方驱动,没必要自己去造每一个轮子;若是需要根据软件架构的原因,定制开发,也尽量参考着来开发,过于死磕数据手册没有太多价值和提升。

以下是一个基于STM32F103C8T6使用I2C通信与QMI8658 IMU进行交互的示例代码。此代码包含了I2C初始化、QMI8658的初始化以及读取数据的基本功能。 ```c #include "stm32f10x.h" // I2C 初始化函数 void I2C1_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; I2C_InitTypeDef I2C_InitStructure; // 使能 I2C1 和 GPIOA 时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 配置 I2C1 SCL (PA6) 和 SDA (PA7) 引脚 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // I2C1 配置 I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; I2C_InitStructure.I2C_OwnAddress1 = 0x00; I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_InitStructure.I2C_ClockSpeed = 100000; I2C_Init(I2C1, &I2C_InitStructure); // 使能 I2C1 I2C_Cmd(I2C1, ENABLE); } // I2C 写寄存器函数 void I2C_WriteReg(uint8_t devAddr, uint8_t regAddr, uint8_t data) { while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); I2C_GenerateSTART(I2C1, ENABLE); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, devAddr << 1, I2C_Direction_Transmitter); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); I2C_SendData(I2C1, regAddr); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); I2C_SendData(I2C1, data); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); I2C_GenerateSTOP(I2C1, ENABLE); } // I2C 读寄存器函数 uint8_t I2C_ReadReg(uint8_t devAddr, uint8_t regAddr) { uint8_t data; while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); I2C_GenerateSTART(I2C1, ENABLE); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, devAddr << 1, I2C_Direction_Transmitter); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); I2C_SendData(I2C1, regAddr); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); I2C_GenerateSTART(I2C1, ENABLE); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, devAddr << 1, I2C_Direction_Receiver); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); I2C_AcknowledgeConfig(I2C1, DISABLE); I2C_GenerateSTOP(I2C1, ENABLE); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)); data = I2C_ReceiveData(I2C1); return data; } // QMI8658 初始化函数 void QMI8658_Init(void) { // 这里需要根据 QMI8658 的数据手册进行寄存器配置 // 示例:写入某个寄存器来初始化 I2C_WriteReg(0x6B, 0x01, 0x01); // 假设 0x6B 是 QMI8658 的 I2C 地址,0x01 是寄存器地址,0x01 是要写入的数据 } // 读取 QMI8658 数据 uint8_t QMI8658_ReadData(uint8_t regAddr) { return I2C_ReadReg(0x6B, regAddr); } int main(void) { uint8_t data; I2C1_Init(); QMI8658_Init(); while (1) { // 读取 QMI8658 的某个寄存器数据 data = QMI8658_ReadData(0x02); // 可以在这里处理读取到的数据 } } ``` ### 代码说明: 1. **I2C1_Init 函数**:初始化 I2C1 接口,配置 SCL 和 SDA 引脚,设置 I2C 的时钟速度等参数。 2. **I2C_WriteReg 函数**:向指定设备的指定寄存器写入数据。 3. **I2C_ReadReg 函数**:从指定设备的指定寄存器读取数据。 4. **QMI8658_Init 函数**:对 QMI8658 进行初始化,需要根据 QMI8658 的数据手册进行具体的寄存器配置。 5. **QMI8658_ReadData 函数**:从 QMI8658 的指定寄存器读取数据。 6. **main 函数**:初始化 I2C 和 QMI8658,然后在循环中不断读取 QMI8658 的某个寄存器数据。 ### 注意事项: - 上述代码中的 I2C 地址(0x6B)和寄存器地址(如 0x01、0x02)需要根据 QMI8658 的实际情况进行调整。 - 代码中的初始化配置只是示例,实际使用时需要参考 QMI8658 的数据手册进行准确的寄存器配置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值