1. 概述
项目中,往往需要根据不同的环境使用不同的芯片处理某些数据,当使用不同的芯片对六轴陀螺仪芯片MPU6050进行数据处理中,硬件的连接、I/O口的设置往往需要根据相应的情况进行处理。
2. STM32G030对MPU6050的读取
开发环境: STM32CubeIDE
芯片型号:STM32G031F8P6
时钟配置,不使用外部时钟
定时器配置,1ms中断,陀螺仪dt = 20ms
开启串口2
文件列表
my_iic.c 文件
#include "my_delay.h"
#include "main.h"
#include "my_iic.h"
void i2c_NAck(void);
void i2c_Ack(void);
#define I2C_SCL_1() HAL_GPIO_WritePin(GPIOB, IIC_SCL_Pin, 1) //SCL=1
#define I2C_SCL_0() HAL_GPIO_WritePin(GPIOB, IIC_SCL_Pin, 0) //SCL=0
#define I2C_SDA_1() HAL_GPIO_WritePin(GPIOB, IIC_SDA_Pin, 1) //SDA=1
#define I2C_SDA_0() HAL_GPIO_WritePin(GPIOB, IIC_SDA_Pin, 0) //SDA=0
#define I2C_SDA_READ() HAL_GPIO_ReadPin(GPIOB, IIC_SDA_Pin) //读数据线状态
#define I2C_WR 0
#define I2C_RD 1
//延时 64MHz 频率慢一些,72MHz设置为10
static void i2c_Delay(void)
{
for (int i = 0; i < 9; i++);
}
/*
* IIC start 发起总线起始信号
*
* */
void i2c_Start(void)
{
I2C_SDA_1();
I2C_SCL_1();
i2c_Delay();
I2C_SDA_0();
i2c_Delay();
I2C_SCL_0();
i2c_Delay();
}
//停止信号
void i2c_Stop(void)
{
I2C_SDA_0();
I2C_SCL_1();
i2c_Delay();
I2C_SDA_1();
}
//字节发送
void i2c_SendByte(uint8_t _ucByte)
{
uint8_t i;
for (i = 0; i < 8; i++)
{
if (_ucByte & 0x80)
{
I2C_SDA_1();
}
else
{
I2C_SDA_0();
}
i2c_Delay();
I2C_SCL_1();
i2c_Delay();
I2C_SCL_0();
if (i == 7)
{
I2C_SDA_1();
}
_ucByte <<= 1;
i2c_Delay();
}
}
//字节读取
uint8_t i2c_ReadByte(uint8_t ack)
{
uint8_t i;
uint8_t value;
value = 0;
for (i = 0; i < 8; i++)
{
value <<= 1;
I2C_SCL_1();
i2c_Delay();
if (I2C_SDA_READ())
{
value++;
}
I2C_SCL_0();
i2c_Delay();
}
if(ack==0)
i2c_NAck();
else
i2c_Ack();
return value;
}
//等待
uint8_t i2c_WaitAck(void)
{
uint8_t re;
I2C_SDA_1(); /* CPUÊÍ·ÅSDA×ÜÏß */
i2c_Delay();
I2C_SCL_1(); /* CPUÇý¶¯SCL = 1, ´ËʱÆ÷¼þ»á·µ»ØACKÓ¦´ð */
i2c_Delay();
if (I2C_SDA_READ()) /* CPU¶ÁÈ¡SDA¿ÚÏß״̬ */
{
re = 1;
}
else
{
re = 0;
}
I2C_SCL_0();
i2c_Delay();
return re;
}
//ACK
void i2c_Ack(void)
{
I2C_SDA_0(); /* CPUÇý¶¯SDA = 0 */
i2c_Delay();
I2C_SCL_1(); /* CPU²úÉú1¸öʱÖÓ */
i2c_Delay();
I2C_SCL_0();
i2c_Delay();
I2C_SDA_1(); /* CPUÊÍ·ÅSDA×ÜÏß */
}
//NACK
void i2c_NAck(void)
{
I2C_SDA_1(); /* CPUÇý¶¯SDA = 1 */
i2c_Delay();
I2C_SCL_1(); /* CPU²úÉú1¸öʱÖÓ */
i2c_Delay();
I2C_SCL_0();
i2c_Delay();
}
//检查
uint8_t i2c_CheckDevice(uint8_t _Address)
{
uint8_t ucAck;
i2c_Stop();
i2c_Start();
i2c_SendByte(_Address|I2C_WR);
ucAck = i2c_WaitAck();
i2c_Stop();
return ucAck;
}
my_iic.h 文件
void i2c_Start(void);
void i2c_Stop(void);
void i2c_SendByte(uint8_t _ucByte);
uint8_t i2c_ReadByte(uint8_t ack);
uint8_t i2c_WaitAck(void);
void i2c_Ack(void);
void i2c_NAck(void);
uint8_t i2c_CheckDevice(uint8_t _Address);
void i2c_GPIO_Config(void);
my_mpu6050.c 文件
#include "my_delay.h"
#include "main.h"
#include "my_iic.h"
#include "my_mpu6050.h"
#include "stdio.h"
写寄存器
void MPU6050_WriteReg(uint8_t reg_add,uint8_t reg_dat)
{
i2c_Start();
i2c_SendByte(MPU6050_SLAVE_ADDRESS);
i2c_WaitAck();
i2c_SendByte(reg_add);
i2c_WaitAck();
i2c_SendByte(reg_dat);
i2c_WaitAck();
i2c_Stop();
}
//读数据
void MPU6050_ReadData(uint8_t reg_add,unsigned char*Read,uint8_t num)
{
unsigned char i;
i2c_Start();
i2c_SendByte(MPU6050_SLAVE_ADDRESS);
i2c_WaitAck();
i2c_SendByte(reg_add);
i2c_WaitAck();
i2c_Start();
i2c_SendByte(MPU6050_SLAVE_ADDRESS+1);
i2c_WaitAck();
for(i=0;i<(num-1);i++){
*Read=i2c_ReadByte(1);
Read++;
}
*Read=i2c_ReadByte(0);
i2c_Stop();
}
初始化
void MPU6050_Init(void)
{
int i=0,j=0;
for(i=0;i<1000;i++)
{
for(j=0;j<1000;j++)
{
;
}
}
MPU6050_WriteReg(MPU6050_RA_PWR_MGMT_1, 0x00); //½â³ýÐÝÃß״̬
MPU6050_WriteReg(MPU6050_RA_SMPLRT_DIV , 0x07); //ÍÓÂÝÒDzÉÑùÂÊ£¬1KHz
MPU6050_WriteReg(MPU6050_RA_CONFIG , 0x06); //µÍͨÂ˲¨Æ÷µÄÉèÖ㬽ØֹƵÂÊÊÇ1K£¬´ø¿íÊÇ5K
MPU6050_WriteReg(MPU6050_RA_ACCEL_CONFIG , 0x00); //ÅäÖüÓËٶȴ«¸ÐÆ÷¹¤×÷ÔÚ2Gģʽ£¬²»×Ô¼ì
MPU6050_WriteReg(MPU6050_RA_GYRO_CONFIG, 0x18); //ÍÓÂÝÒÇ×Լ켰²âÁ¿·¶Î§£¬µäÐÍÖµ£º0x18(²»×Լ죬2000deg/s)
}
//读6050的ID
uint8_t MPU6050ReadID(void)
{
unsigned char Re = 0;
MPU6050_ReadData(MPU6050_RA_WHO_AM_I,&Re,1); //¶ÁÆ÷¼þµØÖ·
if(Re != 0x68)
{
printf("MPU6050 dectected error! --%d \r\n", Re);
return 0;
}
else
{
printf("MPU6050 ID = %d\r\n",Re);
return 1;
}
}
//读加速度
void MPU6050ReadAcc(short *accData)
{
uint8_t buf[6];
MPU6050_ReadData(MPU6050_ACC_OUT, buf, 6);
accData[0] = (buf[0] << 8) | buf[1];
accData[1] = (buf[2] << 8) | buf[3];
accData[2] = (buf[4] << 8) | buf[5];
}
//读角速度
void MPU6050ReadGyro(short *gyroData)
{
uint8_t buf[6];
MPU6050_ReadData(MPU6050_GYRO_OUT,buf,6);
gyroData[0] = (buf[0] << 8) | buf[1];
gyroData[1] = (buf[2] << 8) | buf[3];
gyroData[2] = (buf[4] << 8) | buf[5];
}
void MPU6050ReadTemp(short *tempData)
{
uint8_t buf[2];
MPU6050_ReadData(MPU6050_RA_TEMP_OUT_H,buf,2); //¶ÁȡζÈÖµ
*tempData = (buf[0] << 8) | buf[1];
}
void MPU6050_ReturnTemp(float *Temperature)
{
short temp3;
uint8_t buf[2];
MPU6050_ReadData(MPU6050_RA_TEMP_OUT_H,buf,2); //¶ÁȡζÈÖµ
temp3= (buf[0] << 8) | buf[1];
*Temperature=((double) temp3/340.0)+36.53;
my_mpu6050.h 文件
#define MPU6050_SLAVE_ADDRESS (0x68<<1) //MPU6050Æ÷¼þ¶ÁµØÖ·
#define MPU6050_WHO_AM_I 0x75
#define MPU6050_SMPLRT_DIV 0 //8000Hz
#define MPU6050_DLPF_CFG 0
#define MPU6050_GYRO_OUT 0x43 //MPU6050ÍÓÂÝÒÇÊý¾Ý¼Ä´æÆ÷µØÖ·
#define MPU6050_ACC_OUT 0x3B //MPU6050¼ÓËÙ¶ÈÊý¾Ý¼Ä´æÆ÷µØÖ·
#define MPU6050_ADDRESS_AD0_LOW 0x68 // address pin low (GND), default for InvenSense evaluation board
#define MPU6050_ADDRESS_AD0_HIGH 0x69 // address pin high (VCC)
#define MPU6050_DEFAULT_ADDRESS MPU6050_ADDRESS_AD0_LOW
#define MPU6050_RA_XG_OFFS_TC 0x00 //[7] PWR_MODE, [6:1] XG_OFFS_TC, [0] OTP_BNK_VLD
#define MPU6050_RA_YG_OFFS_TC 0x01 //[7] PWR_MODE, [6:1] YG_OFFS_TC, [0] OTP_BNK_VLD
#define MPU6050_RA_ZG_OFFS_TC 0x02 //[7] PWR_MODE, [6:1] ZG_OFFS_TC, [0] OTP_BNK_VLD
#define MPU6050_RA_X_FINE_GAIN 0x03 //[7:0] X_FINE_GAIN
#define MPU6050_RA_Y_FINE_GAIN 0x04 //[7:0] Y_FINE_GAIN
#define MPU6050_RA_Z_FINE_GAIN 0x05 //[7:0] Z_FINE_GAIN
#define MPU6050_RA_XA_OFFS_H 0x06 //[15:0] XA_OFFS
#define MPU6050_RA_XA_OFFS_L_TC 0x07
#define MPU6050_RA_YA_OFFS_H 0x08 //[15:0] YA_OFFS
#define MPU6050_RA_YA_OFFS_L_TC 0x09
#define MPU6050_RA_ZA_OFFS_H 0x0A //[15:0] ZA_OFFS
#define MPU6050_RA_ZA_OFFS_L_TC 0x0B
#define MPU6050_RA_XG_OFFS_USRH 0x13 //[15:0] XG_OFFS_USR
#define MPU6050_RA_XG_OFFS_USRL 0x14
#define MPU6050_RA_YG_OFFS_USRH 0x15 //[15:0] YG_OFFS_USR
#define MPU6050_RA_YG_OFFS_USRL 0x16
#define MPU6050_RA_ZG_OFFS_USRH 0x17 //[15:0] ZG_OFFS_USR
#define MPU6050_RA_ZG_OFFS_USRL 0x18
#define MPU6050_RA_SMPLRT_DIV 0x19
#define MPU6050_RA_CONFIG 0x1A
#define MPU6050_RA_GYRO_CONFIG 0x1B
#define MPU6050_RA_ACCEL_CONFIG 0x1C
#define MPU6050_RA_FF_THR 0x1D
#define MPU6050_RA_FF_DUR 0x1E
#define MPU6050_RA_MOT_THR 0x1F
#define MPU6050_RA_MOT_DUR 0x20
#define MPU6050_RA_ZRMOT_THR 0x21
#define MPU6050_RA_ZRMOT_DUR 0x22
#define MPU6050_RA_FIFO_EN 0x23
#define MPU6050_RA_I2C_MST_CTRL 0x24
#define MPU6050_RA_I2C_SLV0_ADDR 0x25
#define MPU6050_RA_I2C_SLV0_REG 0x26
#define MPU6050_RA_I2C_SLV0_CTRL 0x27
#define MPU6050_RA_I2C_SLV1_ADDR 0x28
#define MPU6050_RA_I2C_SLV1_REG 0x29
#define MPU6050_RA_I2C_SLV1_CTRL 0x2A
#define MPU6050_RA_I2C_SLV2_ADDR 0x2B
#define MPU6050_RA_I2C_SLV2_REG 0x2C
#define MPU6050_RA_I2C_SLV2_CTRL 0x2D
#define MPU6050_RA_I2C_SLV3_ADDR 0x2E
#define MPU6050_RA_I2C_SLV3_REG 0x2F
#define MPU6050_RA_I2C_SLV3_CTRL 0x30
#define MPU6050_RA_I2C_SLV4_ADDR 0x31
#define MPU6050_RA_I2C_SLV4_REG 0x32
#define MPU6050_RA_I2C_SLV4_DO 0x33
#define MPU6050_RA_I2C_SLV4_CTRL 0x34
#define MPU6050_RA_I2C_SLV4_DI 0x35
#define MPU6050_RA_I2C_MST_STATUS 0x36
#define MPU6050_RA_INT_PIN_CFG 0x37
#define MPU6050_RA_INT_ENABLE 0x38
#define MPU6050_RA_DMP_INT_STATUS 0x39
#define MPU6050_RA_INT_STATUS 0x3A
#define MPU6050_RA_ACCEL_XOUT_H 0x3B
#define MPU6050_RA_ACCEL_XOUT_L 0x3C
#define MPU6050_RA_ACCEL_YOUT_H 0x3D
#define MPU6050_RA_ACCEL_YOUT_L 0x3E
#define MPU6050_RA_ACCEL_ZOUT_H 0x3F
#define MPU6050_RA_ACCEL_ZOUT_L 0x40
#define MPU6050_RA_TEMP_OUT_H 0x41
#define MPU6050_RA_TEMP_OUT_L 0x42
#define MPU6050_RA_GYRO_XOUT_H 0x43
#define MPU6050_RA_GYRO_XOUT_L 0x44
#define MPU6050_RA_GYRO_YOUT_H 0x45
#define MPU6050_RA_GYRO_YOUT_L 0x46
#define MPU6050_RA_GYRO_ZOUT_H 0x47
#define MPU6050_RA_GYRO_ZOUT_L 0x48
#define MPU6050_RA_EXT_SENS_DATA_00 0x49
#define MPU6050_RA_EXT_SENS_DATA_01 0x4A
#define MPU6050_RA_EXT_SENS_DATA_02 0x4B
#define MPU6050_RA_EXT_SENS_DATA_03 0x4C
#define MPU6050_RA_EXT_SENS_DATA_04 0x4D
#define MPU6050_RA_EXT_SENS_DATA_05 0x4E
#define MPU6050_RA_EXT_SENS_DATA_06 0x4F
#define MPU6050_RA_EXT_SENS_DATA_07 0x50
#define MPU6050_RA_EXT_SENS_DATA_08 0x51
#define MPU6050_RA_EXT_SENS_DATA_09 0x52
#define MPU6050_RA_EXT_SENS_DATA_10 0x53
#define MPU6050_RA_EXT_SENS_DATA_11 0x54
#define MPU6050_RA_EXT_SENS_DATA_12 0x55
#define MPU6050_RA_EXT_SENS_DATA_13 0x56
#define MPU6050_RA_EXT_SENS_DATA_14 0x57
#define MPU6050_RA_EXT_SENS_DATA_15 0x58
#define MPU6050_RA_EXT_SENS_DATA_16 0x59
#define MPU6050_RA_EXT_SENS_DATA_17 0x5A
#define MPU6050_RA_EXT_SENS_DATA_18 0x5B
#define MPU6050_RA_EXT_SENS_DATA_19 0x5C
#define MPU6050_RA_EXT_SENS_DATA_20 0x5D
#define MPU6050_RA_EXT_SENS_DATA_21 0x5E
#define MPU6050_RA_EXT_SENS_DATA_22 0x5F
#define MPU6050_RA_EXT_SENS_DATA_23 0x60
#define MPU6050_RA_MOT_DETECT_STATUS 0x61
#define MPU6050_RA_I2C_SLV0_DO 0x63
#define MPU6050_RA_I2C_SLV1_DO 0x64
#define MPU6050_RA_I2C_SLV2_DO 0x65
#define MPU6050_RA_I2C_SLV3_DO 0x66
#define MPU6050_RA_I2C_MST_DELAY_CTRL 0x67
#define MPU6050_RA_SIGNAL_PATH_RESET 0x68
#define MPU6050_RA_MOT_DETECT_CTRL 0x69
#define MPU6050_RA_USER_CTRL 0x6A
#define MPU6050_RA_PWR_MGMT_1 0x6B
#define MPU6050_RA_PWR_MGMT_2 0x6C
#define MPU6050_RA_BANK_SEL 0x6D
#define MPU6050_RA_MEM_START_ADDR 0x6E
#define MPU6050_RA_MEM_R_W 0x6F
#define MPU6050_RA_DMP_CFG_1 0x70
#define MPU6050_RA_DMP_CFG_2 0x71
#define MPU6050_RA_FIFO_COUNTH 0x72
#define MPU6050_RA_FIFO_COUNTL 0x73
#define MPU6050_RA_FIFO_R_W 0x74
#define MPU6050_RA_WHO_AM_I 0x75
#define MPU6050_TC_PWR_MODE_BIT 7
#define MPU6050_TC_OFFSET_BIT 6
#define MPU6050_TC_OFFSET_LENGTH 6
#define MPU6050_TC_OTP_BNK_VLD_BIT 0
#define MPU6050_VDDIO_LEVEL_VLOGIC 0
#define MPU6050_VDDIO_LEVEL_VDD 1
#define MPU6050_CFG_EXT_SYNC_SET_BIT 5
#define MPU6050_CFG_EXT_SYNC_SET_LENGTH 3
#define MPU6050_CFG_DLPF_CFG_BIT 2
#define MPU6050_CFG_DLPF_CFG_LENGTH 3
#define MPU6050_EXT_SYNC_DISABLED 0x0
#define MPU6050_EXT_SYNC_TEMP_OUT_L 0x1
#define MPU6050_EXT_SYNC_GYRO_XOUT_L 0x2
#define MPU6050_EXT_SYNC_GYRO_YOUT_L 0x3
#define MPU6050_EXT_SYNC_GYRO_ZOUT_L 0x4
#define MPU6050_EXT_SYNC_ACCEL_XOUT_L 0x5
#define MPU6050_EXT_SYNC_ACCEL_YOUT_L 0x6
#define MPU6050_EXT_SYNC_ACCEL_ZOUT_L 0x7
#define MPU6050_DLPF_BW_256 0x00
#define MPU6050_DLPF_BW_188 0x01
#define MPU6050_DLPF_BW_98 0x02
#define MPU6050_DLPF_BW_42 0x03
#define MPU6050_DLPF_BW_20 0x04
#define MPU6050_DLPF_BW_10 0x05
#define MPU6050_DLPF_BW_5 0x06
#define MPU6050_GCONFIG_FS_SEL_BIT 4
#define MPU6050_GCONFIG_FS_SEL_LENGTH 2
#define MPU6050_GYRO_FS_250 0x00
#define MPU6050_GYRO_FS_500 0x01
#define MPU6050_GYRO_FS_1000 0x02
#define MPU6050_GYRO_FS_2000 0x03
#define MPU6050_ACONFIG_XA_ST_BIT 7
#define MPU6050_ACONFIG_YA_ST_BIT 6
#define MPU6050_ACONFIG_ZA_ST_BIT 5
#define MPU6050_ACONFIG_AFS_SEL_BIT 4
#define MPU6050_ACONFIG_AFS_SEL_LENGTH 2
#define MPU6050_ACONFIG_ACCEL_HPF_BIT 2
#define MPU6050_ACONFIG_ACCEL_HPF_LENGTH 3
#define MPU6050_ACCEL_FS_2 0x00
#define MPU6050_ACCEL_FS_4 0x01
#define MPU6050_ACCEL_FS_8 0x02
#define MPU6050_ACCEL_FS_16 0x03
#define MPU6050_DHPF_RESET 0x00
#define MPU6050_DHPF_5 0x01
#define MPU6050_DHPF_2P5 0x02
#define MPU6050_DHPF_1P25 0x03
#define MPU6050_DHPF_0P63 0x04
#define MPU6050_DHPF_HOLD 0x07
#define MPU6050_TEMP_FIFO_EN_BIT 7
#define MPU6050_XG_FIFO_EN_BIT 6
#define MPU6050_YG_FIFO_EN_BIT 5
#define MPU6050_ZG_FIFO_EN_BIT 4
#define MPU6050_ACCEL_FIFO_EN_BIT 3
#define MPU6050_SLV2_FIFO_EN_BIT 2
#define MPU6050_SLV1_FIFO_EN_BIT 1
#define MPU6050_SLV0_FIFO_EN_BIT 0
#define MPU6050_MULT_MST_EN_BIT 7
#define MPU6050_WAIT_FOR_ES_BIT 6
#define MPU6050_SLV_3_FIFO_EN_BIT 5
#define MPU6050_I2C_MST_P_NSR_BIT 4
#define MPU6050_I2C_MST_CLK_BIT 3
#define MPU6050_I2C_MST_CLK_LENGTH 4
#define MPU6050_CLOCK_DIV_348 0x0
#define MPU6050_CLOCK_DIV_333 0x1
#define MPU6050_CLOCK_DIV_320 0x2
#define MPU6050_CLOCK_DIV_308 0x3
#define MPU6050_CLOCK_DIV_296 0x4
#define MPU6050_CLOCK_DIV_286 0x5
#define MPU6050_CLOCK_DIV_276 0x6
#define MPU6050_CLOCK_DIV_267 0x7
#define MPU6050_CLOCK_DIV_258 0x8
#define MPU6050_CLOCK_DIV_500 0x9
#define MPU6050_CLOCK_DIV_471 0xA
#define MPU6050_CLOCK_DIV_444 0xB
#define MPU6050_CLOCK_DIV_421 0xC
#define MPU6050_CLOCK_DIV_400 0xD
#define MPU6050_CLOCK_DIV_381 0xE
#define MPU6050_CLOCK_DIV_364 0xF
#define MPU6050_I2C_SLV_RW_BIT 7
#define MPU6050_I2C_SLV_ADDR_BIT 6
#define MPU6050_I2C_SLV_ADDR_LENGTH 7
#define MPU6050_I2C_SLV_EN_BIT 7
#define MPU6050_I2C_SLV_BYTE_SW_BIT 6
#define MPU6050_I2C_SLV_REG_DIS_BIT 5
#define MPU6050_I2C_SLV_GRP_BIT 4
#define MPU6050_I2C_SLV_LEN_BIT 3
#define MPU6050_I2C_SLV_LEN_LENGTH 4
#define MPU6050_I2C_SLV4_RW_BIT 7
#define MPU6050_I2C_SLV4_ADDR_BIT 6
#define MPU6050_I2C_SLV4_ADDR_LENGTH 7
#define MPU6050_I2C_SLV4_EN_BIT 7
#define MPU6050_I2C_SLV4_INT_EN_BIT 6
#define MPU6050_I2C_SLV4_REG_DIS_BIT 5
#define MPU6050_I2C_SLV4_MST_DLY_BIT 4
#define MPU6050_I2C_SLV4_MST_DLY_LENGTH 5
#define MPU6050_MST_PASS_THROUGH_BIT 7
#define MPU6050_MST_I2C_SLV4_DONE_BIT 6
#define MPU6050_MST_I2C_LOST_ARB_BIT 5
#define MPU6050_MST_I2C_SLV4_NACK_BIT 4
#define MPU6050_MST_I2C_SLV3_NACK_BIT 3
#define MPU6050_MST_I2C_SLV2_NACK_BIT 2
#define MPU6050_MST_I2C_SLV1_NACK_BIT 1
#define MPU6050_MST_I2C_SLV0_NACK_BIT 0
#define MPU6050_INTCFG_INT_LEVEL_BIT 7
#define MPU6050_INTCFG_INT_OPEN_BIT 6
#define MPU6050_INTCFG_LATCH_INT_EN_BIT 5
#define MPU6050_INTCFG_INT_RD_CLEAR_BIT 4
#define MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT 3
#define MPU6050_INTCFG_FSYNC_INT_EN_BIT 2
#define MPU6050_INTCFG_I2C_BYPASS_EN_BIT 1
#define MPU6050_INTCFG_CLKOUT_EN_BIT 0
#define MPU6050_INTMODE_ACTIVEHIGH 0x00
#define MPU6050_INTMODE_ACTIVELOW 0x01
#define MPU6050_INTDRV_PUSHPULL 0x00
#define MPU6050_INTDRV_OPENDRAIN 0x01
#define MPU6050_INTLATCH_50USPULSE 0x00
#define MPU6050_INTLATCH_WAITCLEAR 0x01
#define MPU6050_INTCLEAR_STATUSREAD 0x00
#define MPU6050_INTCLEAR_ANYREAD 0x01
#define MPU6050_INTERRUPT_FF_BIT 7
#define MPU6050_INTERRUPT_MOT_BIT 6
#define MPU6050_INTERRUPT_ZMOT_BIT 5
#define MPU6050_INTERRUPT_FIFO_OFLOW_BIT 4
#define MPU6050_INTERRUPT_I2C_MST_INT_BIT 3
#define MPU6050_INTERRUPT_PLL_RDY_INT_BIT 2
#define MPU6050_INTERRUPT_DMP_INT_BIT 1
#define MPU6050_INTERRUPT_DATA_RDY_BIT 0
// TODO: figure out what these actually do
// UMPL source code is not very obivous
#define MPU6050_DMPINT_5_BIT 5
#define MPU6050_DMPINT_4_BIT 4
#define MPU6050_DMPINT_3_BIT 3
#define MPU6050_DMPINT_2_BIT 2
#define MPU6050_DMPINT_1_BIT 1
#define MPU6050_DMPINT_0_BIT 0
#define MPU6050_MOTION_MOT_XNEG_BIT 7
#define MPU6050_MOTION_MOT_XPOS_BIT 6
#define MPU6050_MOTION_MOT_YNEG_BIT 5
#define MPU6050_MOTION_MOT_YPOS_BIT 4
#define MPU6050_MOTION_MOT_ZNEG_BIT 3
#define MPU6050_MOTION_MOT_ZPOS_BIT 2
#define MPU6050_MOTION_MOT_ZRMOT_BIT 0
#define MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT 7
#define MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT 4
#define MPU6050_DELAYCTRL_I2C_SLV3_DLY_EN_BIT 3
#define MPU6050_DELAYCTRL_I2C_SLV2_DLY_EN_BIT 2
#define MPU6050_DELAYCTRL_I2C_SLV1_DLY_EN_BIT 1
#define MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT 0
#define MPU6050_PATHRESET_GYRO_RESET_BIT 2
#define MPU6050_PATHRESET_ACCEL_RESET_BIT 1
#define MPU6050_PATHRESET_TEMP_RESET_BIT 0
#define MPU6050_DETECT_ACCEL_ON_DELAY_BIT 5
#define MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH 2
#define MPU6050_DETECT_FF_COUNT_BIT 3
#define MPU6050_DETECT_FF_COUNT_LENGTH 2
#define MPU6050_DETECT_MOT_COUNT_BIT 1
#define MPU6050_DETECT_MOT_COUNT_LENGTH 2
#define MPU6050_DETECT_DECREMENT_RESET 0x0
#define MPU6050_DETECT_DECREMENT_1 0x1
#define MPU6050_DETECT_DECREMENT_2 0x2
#define MPU6050_DETECT_DECREMENT_4 0x3
#define MPU6050_USERCTRL_DMP_EN_BIT 7
#define MPU6050_USERCTRL_FIFO_EN_BIT 6
#define MPU6050_USERCTRL_I2C_MST_EN_BIT 5
#define MPU6050_USERCTRL_I2C_IF_DIS_BIT 4
#define MPU6050_USERCTRL_DMP_RESET_BIT 3
#define MPU6050_USERCTRL_FIFO_RESET_BIT 2
#define MPU6050_USERCTRL_I2C_MST_RESET_BIT 1
#define MPU6050_USERCTRL_SIG_COND_RESET_BIT 0
#define MPU6050_PWR1_DEVICE_RESET_BIT 7
#define MPU6050_PWR1_SLEEP_BIT 6
#define MPU6050_PWR1_CYCLE_BIT 5
#define MPU6050_PWR1_TEMP_DIS_BIT 3
#define MPU6050_PWR1_CLKSEL_BIT 2
#define MPU6050_PWR1_CLKSEL_LENGTH 3
#define MPU6050_CLOCK_INTERNAL 0x00
#define MPU6050_CLOCK_PLL_XGYRO 0x01
#define MPU6050_CLOCK_PLL_YGYRO 0x02
#define MPU6050_CLOCK_PLL_ZGYRO 0x03
#define MPU6050_CLOCK_PLL_EXT32K 0x04
#define MPU6050_CLOCK_PLL_EXT19M 0x05
#define MPU6050_CLOCK_KEEP_RESET 0x07
#define MPU6050_PWR2_LP_WAKE_CTRL_BIT 7
#define MPU6050_PWR2_LP_WAKE_CTRL_LENGTH 2
#define MPU6050_PWR2_STBY_XA_BIT 5
#define MPU6050_PWR2_STBY_YA_BIT 4
#define MPU6050_PWR2_STBY_ZA_BIT 3
#define MPU6050_PWR2_STBY_XG_BIT 2
#define MPU6050_PWR2_STBY_YG_BIT 1
#define MPU6050_PWR2_STBY_ZG_BIT 0
#define MPU6050_WAKE_FREQ_1P25 0x0
#define MPU6050_WAKE_FREQ_2P5 0x1
#define MPU6050_WAKE_FREQ_5 0x2
#define MPU6050_WAKE_FREQ_10 0x3
#define MPU6050_BANKSEL_PRFTCH_EN_BIT 6
#define MPU6050_BANKSEL_CFG_USER_BANK_BIT 5
#define MPU6050_BANKSEL_MEM_SEL_BIT 4
#define MPU6050_BANKSEL_MEM_SEL_LENGTH 5
#define MPU6050_WHO_AM_I_BIT 6
#define MPU6050_WHO_AM_I_LENGTH 6
#define MPU6050_DMP_MEMORY_BANKS 8
#define MPU6050_DMP_MEMORY_BANK_SIZE 256
#define MPU6050_DMP_MEMORY_CHUNK_SIZE 16
void MPU6050ReadTemp(short *tempData);
void MPU6050ReadGyro(short *gyroData);
void MPU6050ReadAcc(short *accData);
void MPU6050_ReturnTemp(float *Temperature);
void MPU6050_Init(void);
uint8_t MPU6050ReadID(void);
void PMU6050_ReadData(uint8_t reg_add,unsigned char*Read,uint8_t num);
void PMU6050_WriteReg(uint8_t reg_add,uint8_t reg_dat);
void MPU6050_PWR_MGMT_1_INIT(void);
my_kalman.c 文件
#include "my_kalman.h"
#include "my_delay.h"
#include "main.h"
#include "my_iic.h"
#include "my_mpu6050.h"
#include "stdio.h"
#include "string.h"
#include "math.h"
extern uint16_t kalman_printf_cnt;
/* MPU6050Êý¾Ý */
short Accel[3];
short Gyro[3];
float Temp;
float accel_x; //X
float accel_y; //Y
float accel_z; //Z
float gyro_x; //X
float gyro_y; //
float gyro_z; //
float pitch_raw; //
float pitch_kalman; //
float roll_raw; //
float roll_kalman; //
static float Q_angle = 0.003; //
static float Q_gyro = 0.0025; //
static float R_angle = 0.3; //
static float dt = 0.02;
void Kalman_Cal_Pitch(float acc,float gyro)
{
static float QQ_bias;
static float KK_0, KK_1;
static float PPP[2][2] = { { 1, 0 },{ 0, 1 } };
pitch_kalman += (gyro - QQ_bias) * dt;
PPP[0][0] = PPP[0][0] + Q_angle - (PPP[0][1] + PPP[1][0])*dt;
PPP[0][1] = PPP[0][1] - PPP[1][1]*dt;
PPP[1][0] = PPP[1][0] - PPP[1][1]*dt;
PPP[1][1] = PPP[1][1] + Q_gyro;
KK_0 = PPP[0][0] / (PPP[0][0] + R_angle);
KK_1 = PPP[1][0] / (PPP[0][0] + R_angle);
pitch_kalman = pitch_kalman + KK_0 * (acc - pitch_kalman);
QQ_bias = QQ_bias + KK_1 * (acc - pitch_kalman);
PPP[0][0] = PPP[0][0] - KK_0 * PPP[0][0];
PPP[0][1] = PPP[0][1] - KK_0 * PPP[0][1];
PPP[1][0] = PPP[1][0] - KK_1 * PPP[0][0];
PPP[1][1] = PPP[1][1] - KK_1 * PPP[0][1];
}
void Kalman_Cal_Roll(float acc,float gyro)
{
static float Q_bias; //
static float K_0, K_1; //
static float PP[2][2] = { { 1, 0 },{ 0, 1 } };//
roll_kalman += (gyro - Q_bias) * dt; //
PP[0][0] = PP[0][0] + Q_angle - (PP[0][1] + PP[1][0])*dt;
PP[0][1] = PP[0][1] - PP[1][1]*dt;
PP[1][0] = PP[1][0] - PP[1][1]*dt;
PP[1][1] = PP[1][1] + Q_gyro;
K_0 = PP[0][0] / (PP[0][0] + R_angle);
K_1 = PP[1][0] / (PP[0][0] + R_angle);
roll_kalman = roll_kalman + K_0 * (acc - roll_kalman);
Q_bias = Q_bias + K_1 * (acc - roll_kalman);
PP[0][0] = PP[0][0] - K_0 * PP[0][0];
PP[0][1] = PP[0][1] - K_0 * PP[0][1];
PP[1][0] = PP[1][0] - K_1 * PP[0][0];
PP[1][1] = PP[1][1] - K_1 * PP[0][1];
}
void MPU6050_DATA_DEL(void)
{
float accx,accy,accz;
MPU6050ReadAcc(Accel);
MPU6050ReadGyro(Gyro);
accel_x = Accel[0];
accel_y = Accel[1];
accel_z = Accel[2];
gyro_x = Gyro[0];
gyro_y = Gyro[1];
gyro_z = Gyro[2];
if(accel_x<32764)
{
accx=accel_x/(16384.0); //0-1g
}
else
{
accx=1-(accel_x-49152)/16384.0;
}
if(accel_y<32764)
{
accy=accel_y/16384.0;
}
else
{
accy=1-(accel_y-49152)/16384.0;
}
if(accel_z<32764)
{
accz=accel_z/16384.0;
}
else
{
accz=(accel_z-49152)/16384.0;
}
pitch_raw=(atan(accy/accz))*180/3.14;
// roll_raw=(atan(accx/accz))*180/3.14;
roll_raw= atan2(accx,accz)*180/3.14;
if(accel_y<32764)
{
pitch_raw = +pitch_raw;
}
if(accel_y>32764)
{
pitch_raw = -pitch_raw;
}
if(gyro_x<32768)
{
gyro_x=-(gyro_x/16.4);
}
if(gyro_x>32768)
{
gyro_x=+(65535-gyro_x)/16.4;
}
if(gyro_y<32768)
{
gyro_y=-(gyro_y/16.4);
}
if(gyro_y>32768)
{
gyro_y=+(65535-gyro_y)/16.4;
}
if(gyro_z<32768)
{
gyro_z=-(gyro_z/16.4);
}
if(gyro_z>32768)
{
gyro_z=+(65535-gyro_z)/16.4;
}
// Kalman_Cal_Pitch(pitch_raw, gyro_x); //
Kalman_Cal_Roll(roll_raw, gyro_y); //
if(kalman_printf_cnt > 49)
{
kalman_printf_cnt = 0;
printf("p_kalman: %.1f, r_kalman: %.1f \r\n", pitch_raw, roll_kalman);
}
}
my_kalman.h 文件
void MPU6050_DATA_DEL(void);
main.c 文件
#include <stdio.h>
#include "my_delay.h"
#include "my_mpu6050.h"
#include "my_iic.h"
#include "my_kalman.h"
uint8_t dt_kalman = 0;
uint16_t kalman_printf_cnt = 0; //20ms
int main(void)
{
//定时器中断20ms 对应dt - 0.02
HAL_TIM_Base_Start_IT(&htim3);
//mpu6050初始化
MPU6050_Init();
//循环读取ID
while(MPU6050ReadID() == 0)
{
HAL_Delay(500);
}
while (1)
{
if(dt_kalman)
{
MPU6050_DATA_DEL();
dt_kalman = 0;
}
}
}
stm32g0xx_it.c 文件
extern uint16_t kalman_printf_cnt; //20ms
extern uint8_t dt_kalman;
uint8_t dt_kalman_cnt=0;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == htim3.Instance)
{
dt_kalman_cnt++;
if(dt_kalman_cnt > 19) //20ms
{
dt_kalman_cnt = 0;
dt_kalman = 1;
kalman_printf_cnt++;
}
}
}
3. STM32F1xx对MPU6050的读取
芯片:STM32F105RBT6
相对与STM32G030,F105RBT6需要注意几点:
- SCL,SDA和INT的引脚调整;
- IIC延时delay设置72MHz计数10次,64MHz计数9次左右;
- IIC_SCL和IIC_SDA的输出方式为开漏输出,不要使用推挽输出,推挽输出为强上下拉,这样从机就没法改变数据线的电平了。
G030里面的配置是推挽却没有问题,可以正常读取,开漏作为数据线更好。
推挽输出
开漏输出