文章概览
i2c
一种通信方式
特点
未知,用两根线,SDA,SCK
HAL库常用代码
读写
1
2
3
4
5
6
7
8
9
const uint16_t i2c_timeout = 100;
uint8_t check;
uint8_t data;
// i2c | 设备地址 | 寄存器地址 | 寄存器长度 | 数据起始地址 | 数据长度 | 超时时间
HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDR, WHO_AM_I_REG, 1, &check, 1, i2c_timeout);
HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDR, PWR_MGMT_1_REG, 1, &Data, 1, i2c_timeout);
若修改来自非库函数的源代码,也就是把他们的 I2C 读写换成这个函数,以及删掉无用初始化
查找当前 I2C 设备地址
1
2
3
4
5
6
7for(uint8_t i=0;i<255;i++)
if(HAL_I2C_IsDeviceReady(&hi2c1, i, 1, 1000)==HAL_OK){
printf("%d\r\n", i);
break;
}
else
printf("wait");
mpu6050
陀螺仪+加速度计+温度计
i2c通信速度高达400KHz
自带FIFO(不清楚)
使用方法
接线时只需要接两根数据线和 vcc,gnd 共四根线即可。
定义一个结构体用于接收
1
MPU6050_t mpu6050data;
初始化
1
2
3
4
5
6
7
8while(MPU6050_Init(&hi2c1)==1);
// 等待几秒
printf ("****** MPU6050 Test 3s ******\r\n");
HAL_Delay (1000);
printf ("****** MPU6050 Test 2s ******\r\n");
HAL_Delay (1000);
printf ("****** MPU6050 Test 1s ******\r\n");
HAL_Delay (1000);读取
1
2
3MPU6050_Read_Accel(&hi2c1,&mpu6050data);
MPU6050_Read_Gyro(&hi2c1,&mpu6050data);
MPU6050_Read_Temp(&hi2c1,&mpu6050data);补充
芯片内置 dmp,直接可以帮你滤波,甚至识别运动。
模块封装都会引出很多引脚,平时只用4个
XDA,XCL是考虑到使用芯片内置 dmp 计算时,可以用9轴(加上磁场传感器),其中磁场传感器的外界接口就是这俩,用 i2c通信。(很少用)
AD0 设置 i2c 通信地址,接VCC时为 0x69,否则 0x68(一般悬空)
INT 中断输出引脚(不知道咋用)
阅读寄存器手册
i2c 通信HAL库直接指令
1
2
3
4
5
6
7
8
9
const uint16_t i2c_timeout = 100;
uint8_t check;
uint8_t data;
// i2c | 设备地址 | 寄存器地址 | 寄存器长度 | 数据起始地址 | 数据长度 | 超时时间
HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDR, WHO_AM_I_REG, 1, &check, 1, i2c_timeout);
HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDR, PWR_MGMT_1_REG, 1, &Data, 1, i2c_timeout);陀螺仪寄存器库操作
初始化
| WHO_AM_I | PWR_MGMT_1 | SMPLRT_DIV | ACCEL_CONFIG,GYRO_CONFIG |
| ——————— | —————— | ———————————— | —————————————— |
| 获取device ID | 重置一切设置 | 设置分频系数,即采样频率 | 设置加速度和角度的采样上下限 |读取数据
| ACCEL_XOUT_H | GYRO_XOUT_H | TEMP_OUT_H |
| —————— | —————- | ————— |
| 加速度 | 角度 | 温度 |
数据处理
卡尔曼滤波:把测量数据(当前角度)和预测数据(上次角度+当前加速度*时间间隔)加权求和(系数和唯一)
多想多做,发篇一作