简介这份资源面向嵌入式开发、物联网设备及智能穿戴方向的工程师与学习者提供博世BMI160六轴惯性测量单元三轴加速度计三轴陀螺仪的官方驱动源码与数据手册可用于运动追踪、姿态检测与方向感知等场景的硬件集成。压缩包共17个文件约2.22MB以c与h源码文件为核心辅以pdf数据手册、md说明文档及若干工程辅助文件覆盖驱动实现、寄存器定义与编译集成指引。其中驱动源码包含初始化、工作模式配置、数据读取、校准与错误处理等函数头文件则定义结构体、枚举、函数原型及寄存器宏便于理解测量范围、输出速率与滤波器配置数据手册详尽说明技术规格、电气特性、接口协议、引脚配置、操作模式与误差模型为精确校准与性能优化提供依据。目前已有1058人学习下载适合希望快速将BMI160接入自有硬件或软件项目、并深入掌握其底层交互细节的开发者参考。1. BMI160 官方驱动与 Datasheet从六轴数据到姿态解算的第一公里如果你正在做可穿戴设备、平衡车或者任何需要姿态感知的小型硬件大概率绕不开 BMI160 这颗六轴 IMU。它便宜、量大、社区资料多但真正上手时你会发现一个尴尬的现实网上能搜到的例程大多是半成品寄存器配置靠猜读出来的加速度计数据飘得离谱陀螺仪零偏大到没法看。这时候一份原厂的 Datasheet 加上官方驱动基本就是救命稻草。我手里这份资源包含 BMI160 的完整数据手册和官方驱动源码覆盖寄存器映射、I2C/SPI 通信时序、FIFO 配置、中断引脚设置以及低功耗模式切换。它适合两类人一是刚拿到模块、连 WHO_AM_I 都读不出来的新手二是已经能读出数据、但被零偏和噪声折磨到想换方案的熟手。下面我按实际调试顺序把这份资源拆开讲清楚。2. 先搞懂 BMI160 的寄存器地图为什么你的 I2C 读出来全是 0xFF2.1 从 Datasheet 的地址空间看起BMI160 的寄存器地址是 8 位的但读写操作要拼成 16 位高 8 位是地址低 8 位是数据。很多新手直接用 7 位地址去读结果返回 0xFF 或者 0x00然后怀疑模块坏了。Datasheet 第 3 章明确写了I2C 从机地址是 0x68SDO 接地或 0x69SDO 接 VDDIO。注意这是 7 位地址HAL 库的HAL_I2C_Mem_Read需要左移一位变成 0xD0 或 0xD2。我见过至少三个人卡在这里一整天血泪经验就是先拿逻辑分析仪抓波形确认地址字节到底是 0xD0 还是 0x68。官方驱动里通常有一个bmi160_get_regs函数它封装了地址拼接和读写方向位。你不需要自己拼但得知道它内部怎么处理的。比如读BMI160_CHIP_ID地址 0x00正常返回 0xD1。如果返回 0xFF先查地址再查供电最后查上拉电阻。BMI160 的 I2C 引脚是开漏输出SDA/SCL 必须接 4.7k 上拉到 1.8V 或 3.3V很多模块自带电平转换和上拉但如果你是自己画板子漏了上拉就是读不到。2.2 关键寄存器一览与配置顺序Datasheet 里寄存器有上百个但真正影响基础功能的就那么十几个。我整理了一份常用寄存器表配合官方驱动的宏定义看更清楚寄存器名地址作用典型值CHIP_ID0x00芯片 ID0xD1ACC_CONF0x40加速度计 ODR 和带宽0x28ACC_RANGE0x41加速度计量程0x03±2gGYR_CONF0x42陀螺仪 ODR 和带宽0x28GYR_RANGE0x43陀螺仪量程0x00±2000°/sCMD0x7E命令寄存器0x11软复位ACC_DATA0x12加速度计数据起始6 字节GYR_DATA0x0C陀螺仪数据起始6 字节配置顺序不能乱先软复位延时至少 1ms再读 CHIP_ID 确认通信正常然后配置量程和 ODR最后使能传感器。官方驱动里bmi160_init就是按这个流程走的。如果你先使能再配置传感器可能已经进入工作状态再改量程会触发内部状态机异常读出来的数据会跳变。2.3 用官方驱动初始化代码与参数说明下面这段代码基于官方驱动移植到 STM32 HAL 库I2C 句柄换成你自己的#include bmi160.h struct bmi160_dev bmi160; int8_t rslt; /* 1. 绑定读写函数和延时函数 */ bmi160.read bmi160_i2c_read; bmi160.write bmi160_i2c_write; bmi160.delay_ms HAL_Delay; bmi160.id BMI160_I2C_ADDR; /* 0x68 或 0x69 */ /* 2. 初始化软复位 读 CHIP_ID */ rslt bmi160_init(bmi160); if (rslt ! BMI160_OK) { printf(BMI160 init failed: %d\n, rslt); while (1); } /* 3. 配置加速度计ODR 100Hz带宽 normal量程 ±2g */ bmi160.accel_cfg.odr BMI160_ACCEL_ODR_100HZ; bmi160.accel_cfg.bw BMI160_ACCEL_BW_NORMAL_AVG4; bmi160.accel_cfg.range BMI160_ACCEL_RANGE_2G; rslt bmi160_set_sens_conf(bmi160); /* 4. 配置陀螺仪ODR 100Hz量程 ±2000°/s */ bmi160.gyro_cfg.odr BMI160_GYRO_ODR_100HZ; bmi160.gyro_cfg.bw BMI160_GYRO_BW_NORMAL_MODE; bmi160.gyro_cfg.range BMI160_GYRO_RANGE_2000_DPS; rslt bmi160_set_sens_conf(bmi160);逻辑说明bmi160_init内部会写 CMD 寄存器 0x11 触发软复位然后轮询状态寄存器直到复位完成最后读 CHIP_ID 校验。参数说明ODR 选 100Hz 是平衡功耗和实时性的常用值如果你做跌倒检测可以降到 50Hz做无人机飞控可以升到 800Hz 甚至 1600Hz。带宽参数影响内部低通滤波器的截止频率NORMAL_AVG4表示 4 次平均噪声会小一些但延迟增加。量程根据你的运动剧烈程度选±2g 适合手环±16g 适合碰撞记录。3. 读出六轴数据FIFO、中断与零偏补偿的实操细节3.1 轮询模式 vs FIFO 模式怎么选官方驱动支持两种数据读取方式轮询和 FIFO。轮询就是定时读ACC_DATA和GYR_DATA寄存器简单但占用 CPU而且如果主循环有其他任务采样间隔会抖动。FIFO 模式让 BMI160 内部缓存数据达到设定水位后触发中断MCU 再一次性读走。Datasheet 第 2.6 节详细描述了 FIFO 的 1024 字节空间和多种工作模式。我一般这样选如果 MCU 资源紧张、主频低于 48MHz用轮询ODR 设 100Hz定时器每 10ms 读一次。如果做姿态解算需要严格等间隔采样用 FIFO水位设 10 帧中断引脚接 MCU 的外部中断。注意 FIFO 模式下要配置FIFO_CONFIG_1和FIFO_CONFIG_2寄存器官方驱动有bmi160_set_fifo_config函数参数用位或组合。3.2 读取原始数据并转成物理量读出来的 16 位数据是补码格式需要根据量程换算。下面是读取加速度计和陀螺仪的代码片段struct bmi160_sensor_data accel; struct bmi160_sensor_data gyro; /* 轮询读取 */ rslt bmi160_get_sensor_data(BMI160_ACCEL_SEL | BMI160_GYRO_SEL, accel, gyro, bmi160); /* 换算成物理量 */ float accel_x accel.x * 2.0f / 32768.0f; /* ±2g 对应 32768 LSB/g */ float gyro_x gyro.x * 2000.0f / 32768.0f; /* ±2000dps 对应 16.4 LSB/dps */ /* 零偏补偿静止时采集 100 个样本求平均 */ static float gyro_bias_x 0; if (calibrating) { gyro_bias_x gyro_x; if (calib_count 100) { gyro_bias_x / 100; calibrating 0; } } gyro_x - gyro_bias_x;逻辑说明bmi160_get_sensor_data内部会连续读 12 个字节然后拼成两个结构体。参数说明加速度计换算系数是量程 / 32768陀螺仪同理。零偏补偿是必须做的BMI160 的陀螺仪零偏典型值 ±1°/s不补偿的话积分几秒钟角度就飞了。我一般在上电后让设备静止 2 秒采集 200 个样本求平均作为零偏存到 Flash 里下次上电直接加载。3.3 中断配置与 FIFO 水位设置如果你用 FIFO 模式需要配置中断引脚。BMI160 有两个中断引脚 INT1 和 INT2可以映射到 FIFO 满、数据就绪、任何运动检测等事件。官方驱动里bmi160_set_int_config函数可以设置。常见做法是INT1 接 FIFO 水位中断水位设 10 帧MCU 外部中断下降沿触发在中断服务函数里读 FIFO。注意 FIFO 读完后要写FIFO_CONFIG_0的fifo_flush位或者直接读空否则下次中断不会触发。提示FIFO 模式下如果 MCU 处理太慢FIFO 会溢出溢出后数据顺序会乱。建议在中断里只做数据搬运把解算放到主循环。4. 避坑与排查BMI160 调试中最容易翻车的五个点4.1 现象读 CHIP_ID 返回 0xFF 或 0x00原因I2C 地址错误、上拉电阻缺失、供电电压不对。BMI160 的 VDD 和 VDDIO 可以不同但 VDDIO 决定 I2C 电平如果 VDDIO 接 1.8V 而 MCU 是 3.3V需要电平转换。解决先用万用表量 SDA/SCL 静态电压正常应该是 VDDIO。如果为 0查上拉如果为 3.3V 但 VDDIO 是 1.8V查电平转换。4.2 现象加速度计数据静止时跳动超过 50mg原因ODR 和带宽配置不匹配或者电源纹波太大。BMI160 的内部 LDO 对电源敏感如果 VDD 和 VDDIO 共用一路 LDO 且纹波超过 50mV噪声会耦合进传感器。解决在 VDD 引脚就近放 100nF 和 1uF 电容ODR 降到 100Hz带宽选NORMAL_AVG4。如果还不行检查 PCB 布局传感器远离 DC-DC 和天线。4.3 现象陀螺仪零偏随温度漂移严重原因BMI160 的陀螺仪零偏温漂典型值 ±0.05°/s/°C不做温度补偿的话从 25°C 到 60°C 零偏可能变化 1.75°/s。解决如果产品工作温度范围宽需要做温度补偿。常见做法是查 Datasheet 里的温漂曲线用多项式拟合或者简单点每隔 10°C 重新校准一次零偏。官方驱动没有内置温度补偿需要自己实现。4.4 现象FIFO 读出来的数据顺序错乱原因FIFO 溢出后没有及时 flush或者读 FIFO 时没有按帧长度对齐。BMI160 的 FIFO 每帧包含 1 字节 header 和 6 字节数据加速度计陀螺仪。如果读的时候字节数不对后续解析全乱。解决每次读 FIFO 前先读FIFO_LENGTH寄存器算出完整帧数只读整数帧。官方驱动的bmi160_get_fifo_data会处理这些但你要确保传入的缓冲区够大。4.5 现象SPI 模式下读出来全是 0xFF原因SPI 模式选择错误。BMI160 的 SPI 是 4 线模式但 CS 拉低后的第一个字节是地址最高位表示读写方向。很多新手用 3 线 SPI 或者 CPOL/CPHA 设错。解决Datasheet 第 3.3 节明确写了 SPI 时序CPOL1CPHA1即模式 3。CS 拉低后先发地址字节读操作地址最高位置 1再发 dummy 字节然后读数据。官方驱动的 SPI 读写函数已经处理了你只需要确认 MCU 的 SPI 配置是模式 3时钟不超过 10MHz。5. 进阶技巧用 BMI160 做姿态解算的验证方法与参数整定5.1 从原始数据到欧拉角互补滤波的快速验证拿到六轴数据后最直接的验证方式是做互补滤波看角度能不能跟得上。下面是一个最小实现的伪代码你可以直接移植/* 互补滤波陀螺仪积分 加速度计修正 */ float dt 0.01f; /* 100Hz 采样 */ float alpha 0.98f; /* 陀螺仪积分得到角度 */ angle_pitch gyro_x * dt; angle_roll gyro_y * dt; /* 加速度计计算倾角 */ float accel_pitch atan2f(accel_y, accel_z) * 57.2958f; float accel_roll atan2f(-accel_x, sqrtf(accel_y*accel_y accel_z*accel_z)) * 57.2958f; /* 互补融合 */ angle_pitch alpha * angle_pitch (1 - alpha) * accel_pitch; angle_roll alpha * angle_roll (1 - alpha) * accel_roll;逻辑说明陀螺仪积分短期准但长期漂加速度计长期稳但动态噪声大互补滤波用 alpha 加权。参数说明alpha 越大越信任陀螺仪动态响应好但漂移抑制弱alpha 越小越信任加速度计静态稳但运动时滞后。我一般从 0.98 开始调如果发现角度回正太慢就降到 0.95如果抖动厉害就升到 0.99。注意这个算法只在静止或慢速运动时有效快速旋转时加速度计会引入离心力误差。5.2 用 Datasheet 里的噪声密度参数评估你的滤波效果Datasheet 第 1 章给出了 BMI160 的噪声密度加速度计 180μg/√Hz陀螺仪 0.008°/s/√Hz。这个参数怎么用假设你配置 ODR 100Hz带宽 50Hz那么加速度计的有效噪声 RMS 大约是 180μg/√Hz × √50Hz ≈ 1.27mg。如果你实测静止时噪声超过 5mg说明要么电源有问题要么配置不对。陀螺仪同理0.008 × √50 ≈ 0.057°/s实测超过 0.5°/s 就不正常。我一般会写一个简单的测试设备静止放在桌上采集 1000 个样本算标准差。加速度计三轴标准差应该在 2mg 以内陀螺仪在 0.1°/s 以内。如果超标先查电源纹波再查 PCB 应力。BMI160 对焊接应力敏感回流焊后如果板子有弯曲零偏会偏很多。这时候可以试着用手轻轻按压芯片看数据有没有变化如果有说明应力没释放需要重新做应力释放或者换封装。5.3 一个我常犯的错误忘了配置中断引脚的方向最后说一个我踩过的坑。BMI160 的 INT1 和 INT2 默认是推挽输出但如果你在驱动里配置成开漏又没有外部上拉中断就永远触发不了。官方驱动的bmi160_set_int_config里有一个int_pin_cfg参数可以设BMI160_INT_PIN_CFG的output_en和open_drain位。我一般设成推挽输出output_en使能open_drain关闭。还有中断的触发极性也要和 MCU 的外部中断配置一致BMI160 可以设高电平、低电平、上升沿、下降沿。我习惯用下降沿MCU 那边配GPIO_MODE_IT_FALLING。从那以后我每次调新板子都强制走一遍先读 CHIP_ID再读中断引脚电平最后用示波器看中断波形。这三步过了后面基本不会有大问题。希望帮到你。本文还有配套的精品资源点击获取