1. MPU6050原始数据读取与校准
任务与环境
目标:通过 I2C 读取 MPU6050 的加速度计、陀螺仪原始值,并完成零偏校准与温度补偿。硬件:MPU6050(地址 0x68)、MCU 或 Linux 主机 I2C 总线。依赖:C 语言 + linux/i2c-dev.h(Linux 用户态 I2C),无需额外库。
关键寄存器:0x6B PWR_MGMT_1(唤醒)、0x1C ACCEL_CONFIG、0x1B GYRO_CONFIG、0x3B 起 14 字节数据(加速度 6 + 温度 2 + 陀螺仪 6)、0x41/0x43 温度与陀螺仪零偏寄存器。
数据流与校准关系
完整实现
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#include <math.h>
#define ADDR 0x68
static int fd;
static int wr(uint8_t reg, uint8_t val){
uint8_t b[2] = {reg, val};
return write(fd, b, 2) == 2 ? 0 : -1;
}
static int rd(uint8_t reg, uint8_t *buf, int n){
if (write(fd, ®, 1) != 1) return -1;
return read(fd, buf, n) == n ? 0 : -1;
}
static int16_t be16(uint8_t *p){ return (int16_t)((p[0] << 8) | p[1]); }
/* 读取原始数据:ax,ay,az,gx,gy,gz,temp_raw */
static int read_raw(int16_t *ax,int16_t *ay,int16_t *az,
int16_t *gx,int16_t *gy,int16_t *gz,int16_t *tr){
uint8_t b[14];
if (rd(0x3B, b, 14)) return -1;
*ax = be16(b+0); *ay = be16(b+2); *az = be16(b+4);
*tr = be16(b+6);
*gx = be16(b+8); *gy = be16(b+10); *gz = be16(b+12);
return 0;
}
/* 零偏校准:静止采样 N 次求均值 */
static void calibrate(int n, double *bx,double *by,double *bz){
double sx=0, sy=0, sz=0;
int16_t ax,ay,az,gx,gy,gz,tr;
for (int i=0;i<n;i++){
read_raw(&ax,&ay,&az,&gx,&gy,&gz,&tr);
sx+=gx; sy+=gy; sz+=gz;
usleep(2000);
}
*bx=sx/n; *by=sy/n; *bz=sz/n;
}
int main(int argc, char **argv){
const char *dev = argc>1 ? argv[1] : "/dev/i2c-1";
fd = open(dev, O_RDWR);
if (fd < 0 || ioctl(fd, I2C_SLAVE, ADDR) < 0){ perror("i2c"); return 1; }
wr(0x6B, 0x00); /* 唤醒 */
wr(0x1C, 0x00); /* ±2g */
wr(0x1B, 0x00); /* ±250 dps */
usleep(50000);
double bx,by,bz;
calibrate(200, &bx,&by,&bz); /* 保持静止 */
printf("gyro bias: %.2f %.2f %.2f\n", bx,by,bz);
int16_t ax,ay,az,gx,gy,gz,tr;
for (int i=0;i<5;i++){
if (read_raw(&ax,&ay,&az,&gx,&gy,&gz,&tr)) break;
double T = tr/340.0 + 36.53; /* 温度补偿 */
double gxs = (gx-bx)/131.0; /* 去零偏 + 转 dps */
double gys = (gy-by)/131.0;
double gzs = (gz-bz)/131.0;
printf("T=%.2fC ax=%.3fg ay=%.3fg az=%.3fg gx=%.3f gy=%.3f gz=%.3f dps\n",
T, ax/16384.0, ay/16384.0, az/16384.0, gxs, gys, gzs);
usleep(200000);
}
close(fd);
return 0;
}
编译与运行
gcc mpu6050.c -o mpu6050 -lm
./mpu6050 /dev/i2c-1
若使用树莓派需先启用 I2C:sudo raspi-config → Interface → I2C,并用 i2cdetect -y 1 确认 0x68 出现。
验证与判定
- 程序启动后先打印
gyro bias三个值,校准期间传感器必须静止。 - 随后 5 行输出中,静止时
az≈1.000g、ax/ay≈0,三轴角速度接近 0 dps,即判定校准与温度补偿生效。 - 温度
T应接近室温(约 20~30℃),若明显偏离说明温度寄存器解析或量程配置有误。 - 若
i2c报错,检查设备节点、接线(SDA/SCL/GND/VCC)与地址。