基于STM32F103驱动QMI8658A输出加速度陀螺仪数据简介QMI8658A和QMI8658C区别QMI8658A引脚定义QMI8658A寄存器表代码驱动接线代码现象总结简介QMI8658A 是上海矽睿QST推出的一款高性能 6 轴惯性测量单元IMU芯片集成了一个 3-轴加速度计和一个 3-轴陀螺仪用于精确感知和追踪设备的运动与姿态。它支持 I³C、I²C 和 SPI 通信接口具有 低噪声、高分辨率16 位、宽动态范围和低功耗 的特点并内置了 FIFO 缓存及温度传感器适合智能穿戴、无人机、机器人、AR/VR、游戏控制器及其他需要运动检测的消费电子与工业应用。QMI8658A和QMI8658C区别QMI8658系列有两个版本的芯片QMI8658A是低噪音版本QMI8658C是标准版本。芯片QMI8658AQMI8658C传感器类型6轴(3轴加速度3轴陀螺仪)6轴(3轴加速度3轴陀螺仪)陀螺仪量程±16/32/64/128/256/512/1024/2048°/s±16/32/64/128/256/512/1024/2048°/s加速度量程±2/4/8/16 g±2/4/8/16 g最大输出速率1000Hz1000Hz内置DSP有 运动协处理器用于基本动作检测和功能如步数、Tap/动作事件等有高级DSP协处理器(AttitudeEngine)并可进行复杂运动编码和传感器融合姿态融合算法无内建高级 9D 融合算法支持 XKF3 9D 融合算法(需外接磁力计)FIFO容量1536字节1536字节通讯协议I3C, I2C ,3-wire or 4-wire SPII3C, I2C3-wire or 4-wire SPI陀螺仪噪声典型13 mdps/√Hz15 mdps/√Hz加速度计噪声典型150 µg/√Hz200 µg/√Hz选型推荐如果你需要更低传感器本底噪声更优的原始陀螺/加速度噪声并侧重于低功耗动作检测与原始传感器数据处理QMI8658A 更合适。如果你需要板级/系统级的姿态输出内置高性能传感器融合、AttitudeEngine 与指定的方向精度并想减少主机处理负担QMI8658C 是更好的选择。QMI8658A引脚定义上面表格是芯片支持的通讯协议,这里使用的是模块进行测试,模块的CS引脚已经拉高到3.3V,所以只能用IIC进行测试,没法使用SPI通讯。引脚引脚定义VCC供电电压3.3/5VGND供电地SCL串行时钟线SDA串行数据线XDA接从器件SDA,无从器件不接(或接VDDIO,GND)XCL接从器件SCL,无从器件不接(或接VDDIO,GND)ADO模块默认下拉接地( AD00,IIC地址:0x6B;AD01,IIC地址:0x6A )INT接的是芯片的INT1,INT2上拉到3.3V以下是IIC的接线图,这里模块的布线已经把外围电路处理好了,所以可以直接使用IIC进行通讯。QMI8658A寄存器表这里提供了两个通用寄存器存放芯片ID以及版本ID。1.地址00H的ID寄存器读取数据为0x05才是正常。2.地址01H的Revision ID寄存器读取数据为0x7c才是正常。(这里版本号要看对应手册目前官网更新最新的是D版本的手册是0x7c有一些旧的手册版本号是0x68,这个要根据自己购买的产品确认好)代码驱动接线STM32F103C8T6QMI8658OLEDPB10–SCLPB11–SDAPB8SCL–PB9SDA–3.3VVCCVCCGNDGNDGND代码mian.cuint8_tID,R_ID;//定义用于存放ID号的变量int16_tAX,AY,AZ,GX,GY,GZ;//定义用于存放各个数据的变量intmain(void){/*模块初始化*/OLED_Init();//OLED初始化qmi8658_init();//QMI8658初始化/*显示ID号*/OLED_ShowString(1,1,ID:);//显示静态字符串IDQMI8658_GetID();//获取QMI8658的ID号OLED_ShowHexNum(1,4,ID,2);//OLED显示ID号/*显示REVISION_ID号*/OLED_ShowString(1,8,R_ID:);//显示静态字符串R_IDQMI8658_GetRID();//获取QMI8658的ID号OLED_ShowHexNum(1,13,R_ID,2);//OLED显示ID号Delay_ms(2000);/*显示加速度和陀螺仪数据*/OLED_ShowString(1,1,Acc );OLED_ShowString(1,8,Gyro );while(1){QMI8658_GetData(AX,AY,AZ,GX,GY,GZ);//获取QMI8658的数据OLED_ShowSignedNum(2,1,AX,5);//OLED显示数据OLED_ShowSignedNum(3,1,AY,5);OLED_ShowSignedNum(4,1,AZ,5);OLED_ShowSignedNum(2,8,GX,5);OLED_ShowSignedNum(3,8,GY,5);OLED_ShowSignedNum(4,8,GZ,5);}}QMI8658.c#includestm32f10x.h#includemath.h#includeMyI2C.h#includeqmi8658.h#includeDelay.h/* 全局变量缓存区 */qmi8658_state g_imu;/** * 函 数QMI8658写寄存器 * 参 数RegAddress 寄存器地址范围参考QMI8658手册的寄存器描述 * 参 数Data 要写入寄存器的数据范围0x00~0xFF * 返 回 值无 */voidqmi8658_write_one_byte(uint8_tRegAddress,uint8_tData){MyI2C_Start();//I2C起始MyI2C_SendByte((QMI8658_ADDRESS1)|0x00);//发送从机地址读写位为0表示即将写入MyI2C_ReceiveAck();//接收应答MyI2C_SendByte(RegAddress);//发送寄存器地址MyI2C_ReceiveAck();//接收应答MyI2C_SendByte(Data);//发送要写入寄存器的数据MyI2C_ReceiveAck();//接收应答MyI2C_Stop();//I2C终止}/** * 函 数QMI8658读寄存器 * 参 数RegAddress 寄存器地址范围参考QMI8658手册的寄存器描述 * 返 回 值读取寄存器的数据范围0x00~0xFF */uint8_tqmi8658_read_one_byte(uint8_tRegAddress){uint8_tData;MyI2C_Start();//I2C起始MyI2C_SendByte((QMI8658_ADDRESS1)|0x00);//发送从机地址读写位为0表示即将写入MyI2C_ReceiveAck();//接收应答MyI2C_SendByte(RegAddress);//发送寄存器地址MyI2C_ReceiveAck();//接收应答MyI2C_Start();//I2C重复起始MyI2C_SendByte((QMI8658_ADDRESS1)|0x01);//发送从机地址读写位为1表示即将读取MyI2C_ReceiveAck();//接收应答DataMyI2C_ReceiveByte();//接收指定寄存器的数据MyI2C_SendAck(1);//发送应答给从机非应答终止从机的数据输出MyI2C_Stop();//I2C终止returnData;}/* 写多个连续寄存器从 reg 开始写 len 个字节 * reg: 寄存器地址 * data: 要写入的字节 * data 指向长度至少为 len 的缓冲区 * 返回 0 成功 */uint8_tqmi8568_write_nbytes(uint8_treg,uint8_t*data,uint16_tlen){uint16_ti;MyI2C_Start();//I2C起始MyI2C_SendByte((QMI8658_ADDRESS1)|0x00);//发送从机地址读写位为0表示即将写入MyI2C_ReceiveAck();//接收应答MyI2C_SendByte(reg);//发送寄存器地址MyI2C_ReceiveAck();//接收应答for(i0;ilen;i){MyI2C_SendByte(data[i]);MyI2C_ReceiveAck();}MyI2C_Stop();return0;}/* 连续读多个寄存器从 reg 开始读取 len 字节 * out_buf: 指向接收缓冲区至少 len 长 */uint8_tqmi8568_read_nbytes(uint8_treg,uint8_t*out_buf,uint16_tlen){uint16_ti;/* 写寄存器地址 */MyI2C_Start();MyI2C_SendByte((QMI8658_ADDRESS1)|0x00);MyI2C_ReceiveAck();MyI2C_SendByte(reg);MyI2C_ReceiveAck();/* 重复起始切换到读模式 */MyI2C_Start();MyI2C_SendByte((QMI8658_ADDRESS1)|0x01);MyI2C_ReceiveAck();/* 依次读取 len 字节对最后一个字节发送 NACK */for(i0;ilen;i){if(i(len-1)){out_buf[i]MyI2C_ReceiveByte();/* 最后一个字节 NACK */MyI2C_SendAck(1);}else{out_buf[i]MyI2C_ReceiveByte();/* 发送 ACK继续接收 */MyI2C_SendAck(0);}}MyI2C_Stop();return0;}/** * 函 数QMI8658获取ID号 * 参 数无 * 返 回 值QMI8658的ID号 */uint8_tQMI8658_GetID(void){returnqmi8658_read_one_byte(Register_WhoAmI);//返回WHO_AM_I寄存器的值}/** * 函 数QMI8658获取Revision ID号 * 参 数无 * 返 回 值QMI8658的Revision ID号 */uint8_tQMI8658_GetRID(void){returnqmi8658_read_one_byte(Register_Revision);//返回Revision寄存器的值}/** * brief 陀螺仪校准 * param 无 * retval 检查结果 * arg 0: 校准成功 * arg 1: 校准失败 */uint8_tqmi8658_calibration(void){uint8_tsta0;qmi8658_write_one_byte(Register_Ctrl7,0x00);/* 关闭陀螺仪、加速度计 */qmi8658_write_one_byte(Register_Ctrl9,0xA2);Delay_ms(2000);staqmi8658_read_one_byte(Register_COD_Status);if(sta0x00){return0;}elsereturn1;}/** * brief 传感器软件复位 * param 无 * retval 无 */voidqmi8658_reset(void){qmi8658_write_one_byte(Register_Reset,0xB0);/* 复位QMI8658 */Delay_ms(150);}/** * brief 读取初始状态寄存器 * param 无 * retval 读取结果 */uint8_tqmi8658_read_statusint(void){returnqmi8658_read_one_byte(Register_StatusInt);}/** * brief 读取状态寄存器0 * param 无 * retval 读取结果 */uint8_tqmi8658_read_status0(void){returnqmi8658_read_one_byte(Register_Status0);}/** * brief 读取状态寄存器1 * param 无 * retval 读取结果 */uint8_tqmi8658_read_status1(void){returnqmi8658_read_one_byte(Register_Status1);}/*****************************************************************************************************************//** * brief 配置加速度计参数 * param range 量程 * param odr odr输出速率 * param lpfEnable 低通滤波器 Qmi8658Lpf_Enable 打开Qmi8658Lpf_Disable 关闭 * param stEnable 陀螺仪自检 Qmi8658St_Enable 自检Qmi8658St_Disable 不自检 * retval 无 */voidqmi8658_config_acc(enumqmi8658_accrangerange,enumqmi8658_accodrodr,enumqmi8658_LpfConfiglpfEnable,enumqmi8658_StConfigstEnable){unsignedcharctl_dada;switch(range){caseQmi8658accrange_2g:g_imu.ssvt_a(114);break;caseQmi8658accrange_4g:g_imu.ssvt_a(113);break;caseQmi8658accrange_8g:g_imu.ssvt_a(112);break;caseQmi8658accrange_16g:g_imu.ssvt_a(111);break;default:rangeQmi8658accrange_8g;g_imu.ssvt_a(112);break;}if(stEnableQmi8658St_Enable){ctl_dada(unsignedchar)range|(unsignedchar)odr|0x80;}else{ctl_dada(unsignedchar)range|(unsignedchar)odr;}qmi8658_write_one_byte(Register_Ctrl2,ctl_dada);/* set LPF HPF */qmi8568_read_nbytes(Register_Ctrl5,ctl_dada,1);ctl_dada0xf0;if(lpfEnableQmi8658Lpf_Enable){ctl_dada|A_LSP_MODE_3;ctl_dada|0x01;}else{ctl_dada~0x01;}qmi8658_write_one_byte(Register_Ctrl5,ctl_dada);}/** * brief 配置陀螺仪参数 * param range 量程 * param odr odr输出速率 * param lpfEnable 低通滤波器 Qmi8658Lpf_Enable 打开Qmi8658Lpf_Disable 关闭 * param stEnable 陀螺仪自检 Qmi8658St_Enable 自检Qmi8658St_Disable 不自检 * retval 无 */voidqmi8658_config_gyro(enumqmi8658_gyrrangerange,enumqmi8658_gyrodrodr,enumqmi8658_LpfConfiglpfEnable,enumqmi8658_StConfigstEnable){/* Set the CTRL3 register to configure dynamic range and ODR */unsignedcharctl_dada;/* Store the scale factor for use when processing raw data */switch(range){caseQmi8658gyrrange_16dps:g_imu.ssvt_g2048;break;caseQmi8658gyrrange_32dps:g_imu.ssvt_g1024;break;caseQmi8658gyrrange_64dps:g_imu.ssvt_g512;break;caseQmi8658gyrrange_128dps:g_imu.ssvt_g256;break;caseQmi8658gyrrange_256dps:g_imu.ssvt_g128;break;caseQmi8658gyrrange_512dps:g_imu.ssvt_g64;break;caseQmi8658gyrrange_1024dps:g_imu.ssvt_g32;break;caseQmi8658gyrrange_2048dps:g_imu.ssvt_g16;break;default:rangeQmi8658gyrrange_512dps;g_imu.ssvt_g64;break;}if(stEnableQmi8658St_Enable){ctl_dada(unsignedchar)range|(unsignedchar)odr|0x80;}else{ctl_dada(unsignedchar)range|(unsignedchar)odr;}qmi8658_write_one_byte(Register_Ctrl3,ctl_dada);/* Conversion from degrees/s to rad/s if necessary *//* set LPF HPF */qmi8568_read_nbytes(Register_Ctrl5,ctl_dada,1);ctl_dada0x0f;if(lpfEnableQmi8658Lpf_Enable){ctl_dada|G_LSP_MODE_3;ctl_dada|0x10;}else{ctl_dada~0x10;}qmi8658_write_one_byte(Register_Ctrl5,ctl_dada);}/** * brief 使能陀螺仪、加速度计 * param enableFlags * QMI8658_DISABLE_ALL : 都不使能 * QMI8658_ACC_ENABLE : 使能加速度计 * QMI8658_GYR_ENABLE : 使能陀螺仪 * QMI8658_ACCGYR_ENABLE: 使能陀螺仪、加速度计 * retval 无 */voidqmi8658_enablesensors(unsignedcharenableFlags){#ifdefined(QMI8658_SYNC_SAMPLE_MODE)g_imu.cfg.syncsample1;qmi8658_enable_ahb_clock(0);qmi8658_write_one_byte(Register_Ctrl7,enableFlags|0x80);#elseqmi8658_write_one_byte(Register_Ctrl7,enableFlags);#endifg_imu.cfg.ensensorsenableFlags0x03;Delay_ms(2);}/** * brief 配置QMI8658陀螺仪和加速度计的量程、输出频率参数等 * param low_power 0 正常模式 1低功耗模式 * retval 无 */voidqmi8658_config_reg(unsignedcharlow_power){qmi8658_enablesensors(QMI8658_DISABLE_ALL);if(low_power){g_imu.cfg.ensensorsQMI8658_ACC_ENABLE;g_imu.cfg.accrangeQmi8658accrange_8g;g_imu.cfg.accodrQmi8658accodr_LowPower_21Hz;g_imu.cfg.gyrrangeQmi8658gyrrange_1024dps;g_imu.cfg.gyrodrQmi8658gyrodr_250Hz;}else{g_imu.cfg.ensensorsQMI8658_ACCGYR_ENABLE;/* 使能陀螺仪、加速度计 */g_imu.cfg.accrangeQmi8658accrange_16g;/* ±16g */g_imu.cfg.accodrQmi8658accodr_500Hz;/* 500Hz采样 */g_imu.cfg.gyrrangeQmi8658gyrrange_128dps;/* ±128dps */g_imu.cfg.gyrodrQmi8658gyrodr_500Hz;/* 500Hz采样 */}if(g_imu.cfg.ensensorsQMI8658_ACC_ENABLE){qmi8658_config_acc(g_imu.cfg.accrange,g_imu.cfg.accodr,Qmi8658Lpf_Enable,Qmi8658St_Enable);/* 设置参数并开启加速度计自检和低通滤波器 */}if(g_imu.cfg.ensensorsQMI8658_GYR_ENABLE){qmi8658_config_gyro(g_imu.cfg.gyrrange,g_imu.cfg.gyrodr,Qmi8658Lpf_Enable,Qmi8658St_Enable);/* 设置参数并开启陀螺仪自检和低通滤波器 */}}/** * brief 初始化QMI8658 * param 无 * retval 初始化结果 * arg 0: 成功 * arg 1: 失败 */uint8_tqmi8658_init(void){MyI2C_Init();//先初始化底层的I2Cqmi8658_reset();/* 复位传感器 */qmi8658_write_one_byte(Register_Ctrl1,0x60);/* I2C驱动 */qmi8658_write_one_byte(Register_Ctrl7,0x00);/* 关闭陀螺仪、加速度计 */qmi8658_config_reg(0);/* 配置陀螺仪和加速度计的量程和数据输出速率等参数 */qmi8658_enablesensors(g_imu.cfg.ensensors);/* 使能陀螺仪、加速度计 */return0;}/** * 函 数QMI8658获取数据 * 参 数AccX AccY AccZ 加速度计X、Y、Z轴的数据使用输出参数的形式返回范围-32768~32767 * 参 数GyroX GyroY GyroZ 陀螺仪X、Y、Z轴的数据使用输出参数的形式返回范围-32768~32767 * 返 回 值无 */voidQMI8658_GetData(int16_t*AccX,int16_t*AccY,int16_t*AccZ,int16_t*GyroX,int16_t*GyroY,int16_t*GyroZ){uint8_tDataH,DataL;//定义数据高8位和低8位的变量DataHqmi8658_read_one_byte(Register_Ax_H);//读取加速度计X轴的高8位数据DataLqmi8658_read_one_byte(Register_Ax_L);//读取加速度计X轴的低8位数据*AccX(DataH8)|DataL;//数据拼接通过输出参数返回DataHqmi8658_read_one_byte(Register_Ay_H);//读取加速度计Y轴的高8位数据DataLqmi8658_read_one_byte(Register_Ay_L);//读取加速度计Y轴的低8位数据*AccY(DataH8)|DataL;//数据拼接通过输出参数返回DataHqmi8658_read_one_byte(Register_Az_H);//读取加速度计Z轴的高8位数据DataLqmi8658_read_one_byte(Register_Az_L);//读取加速度计Z轴的低8位数据*AccZ(DataH8)|DataL;//数据拼接通过输出参数返回DataHqmi8658_read_one_byte(Register_Gx_H);//读取陀螺仪X轴的高8位数据DataLqmi8658_read_one_byte(Register_Gx_L);//读取陀螺仪X轴的低8位数据*GyroX(DataH8)|DataL;//数据拼接通过输出参数返回DataHqmi8658_read_one_byte(Register_Gy_H);//读取陀螺仪Y轴的高8位数据DataLqmi8658_read_one_byte(Register_Gy_L);//读取陀螺仪Y轴的低8位数据*GyroY(DataH8)|DataL;//数据拼接通过输出参数返回DataHqmi8658_read_one_byte(Register_Gz_H);//读取陀螺仪Z轴的高8位数据DataLqmi8658_read_one_byte(Register_Gz_L);//读取陀螺仪Z轴的低8位数据*GyroZ(DataH8)|DataL;//数据拼接通过输出参数返回}现象总结这里显示的是实时从寄存器获取的数据如果要更精确的数据需要对代码进行加算法去获取更准确的数据再开发。需要代码的可以在评论区留言邮箱哦