【Renesas RA6M4开发板之I2C读取mpu6050】
时间:2022-11-12 03:00:00
【Renesas RA6M4开发板之I2C读取mpu6050】
- 1.0 mpu6050
-
- 1.1 mpu6050介绍
- 1.2 mpu6050特点
- 1.3 mpu6050应用
- 2. RT-theard配置
-
- 2.1 硬件需求
- 2.2 软件配置
- 3. 代码分析
- 4. 下载验证
1.0 mpu6050
此图转载钦源盛数码专营店
本篇通过Renesas RA6M4开发板采用I2C读取mpu演示6050传感器的角加速度、角速度和温度示例程序。
1.1 mpu6050介绍
MPU6050是一种非常流行的空间运动传感器芯片,可以获得当前三个加速度重量和三个旋转角速度。由于其体积小、功能强、精度高,不仅广泛应用于工业中,而且是模型爱好者的工艺品,安装在各种飞机上在蓝天上疾驰。
1.2 mpu6050特点
使用芯片:MPU-6050
供电电源:3-5V(内部低压差稳压)
通信方式:标准lIC通信协议
芯片内置16BITAD转换器,16位数据输出
陀螺仪范围:±250 500 1000 2000 °/s
加速范围:±2±4±8±16G
温度范围:-20℃~60℃
采用沉金PCB,机焊工艺保证质量
引脚间距2.54MM
液体和反接电源需要在气体环境中工作
尺寸如下:
1.3 mpu6050应用
运动感知游戏
现实增强
行人导航器
零触摸手势用户界面
快速姿势
认证
电子稳像(EIS: Electronic lmage Stabilization )
光学稳像(Ols: Optical lmage Stabilization )
2. RT-theard配置
2.1 硬件需求
1、需要mpu气体环境下的气压和温度采集6050,I2C通讯接线SDA—p504;SCL—p506,地址后面的仓库配置不需要注意,和ssd1306不同
实现功能:
采用I2C读取mpu6050传感器的角加速度、角速度和温度示例
2、RA6M4开发板
3、USB下载线,ch340串口和6条母线,rx—p613;tx—p614
2.2 软件配置
Renesas RA6M4开发板环境配置参考:基于 RT-Thread Studio的CPK-RA6M4 开发板环境建设】
1、新建项目RA6M4-mpu6050工程
2、点击RT-theard Setting,在软件包下添加软件包,然后搜索mpu相关软件支持包,点击添加,然后出现相应的包。
3、配置ssd306,右键选择配置项
在软件包中打开示例程序。
5硬件中,启动I2C,设置端口SDA—p505;SCL—p506
6.保存所有刚性配置,更新当前配置文件
保存是灰色的,保存为蓝色。
3. 代码分析
1.刚加载软件包packages文件夹下,
mpu6xxx.c代码变更如下
(或添加头文件#include "bsp_api.h"
,否则会报错unitx_t
,根据提示全部改为rt_unitx_t
也OK,以下是增加手动校准的第二种方法。
mpu6xxx.c
/* * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2018-10-23 flybreak the first version * 2021-09-09 scratch-er added setting and getting sensor offsets */ #include #include #include #include #define DBG_TAG "mpu6xxx" #define DBG_LVL DBG_INFO #include #include "mpu6xxx.h" #include "mpu6xxx_reg.h" #ifdefPKG_USING_MPU6XXX_MAG
#include "ak8963_reg.h"
#endif
#define MPU6XXX_ACCEL_SEN (16384)
#define MPU6XXX_GYRO_SEN (1310)
#define MPU60X0_SPI_MAX_SPEED (1000 * 1000)
#define MPU60X0_TEMP_SEN (340)
#define MPU60X0_TEMP_OFFSET (36.5)
#define MPU6500_TEMP_SEN (333.87)
#define MPU6500_TEMP_OFFSET (21)
// MAG
#define AK8963_RANGE (4912)
#define AK8963_FULLSCALE (32760)
/** * This function writes the value of the register for mpu6xxx * * @param dev the pointer of device driver structure * @param reg the register for mpu6xxx * @param data value to write * * @return the writing status, RT_EOK reprensents writing the value of the register successfully. */
static rt_err_t mpu6xxx_write_reg(struct mpu6xxx_device *dev, rt_uint8_t reg, rt_uint8_t data)
{
rt_int8_t res = 0;
#ifdef RT_USING_I2C
struct rt_i2c_msg msgs;
rt_uint8_t buf[2] = {
reg, data};
#endif
if (dev->bus->type == RT_Device_Class_I2CBUS)
{
#ifdef RT_USING_I2C
msgs.addr = dev->i2c_addr; /* slave address */
msgs.flags = RT_I2C_WR; /* write flag */
msgs.buf = buf; /* Send data pointer */
msgs.len = 2;
if (rt_i2c_transfer((struct rt_i2c_bus_device *)dev->bus, &msgs, 1) == 1)
{
res = RT_EOK;
}
else
{
res = -RT_ERROR;
}
#endif
}
else
{
#ifdef RT_USING_SPI
res = rt_spi_send_then_send((struct rt_spi_device *)dev->bus, ®, 1, &data, 1);
#endif
}
return res;
}
/** * This function reads the value of registers for mpu6xxx * * @param dev the pointer of device driver structure * @param reg the register for mpu6xxx * @param len number of register * @param buf read data pointer * * @return the reading status, RT_EOK reprensents reading the value of registers successfully. */
static rt_err_t mpu6xxx_read_regs(struct mpu6xxx_device *dev, rt_uint8_t reg, rt_uint8_t len, rt_uint8_t *buf)
{
rt_int8_t res = 0;
#ifdef RT_USING_I2C
struct rt_i2c_msg msgs[2];
#endif
#ifdef RT_USING_SPI
rt_uint8_t tmp;
#endif
if (dev->bus->type == RT_Device_Class_I2CBUS)
{
#ifdef RT_USING_I2C
msgs[0].addr = dev->i2c_addr; /* Slave address */
msgs[0].flags = RT_I2C_WR; /* Write flag */
msgs[0].buf = ® /* Slave register address */
msgs[0].len = 1; /* Number of bytes sent */
msgs[1].addr = dev->i2c_addr; /* Slave address */
msgs[1].flags = RT_I2C_RD; /* Read flag */
msgs[1].buf = buf; /* Read data pointer */
msgs[1].len = len; /* Number of bytes read */
if (rt_i2c_transfer((struct rt_i2c_bus_device *)dev->bus, msgs, 2) == 2)
{
res = RT_EOK;
}
else
{
res = -RT_ERROR;
}
#endif
}
else
{
#ifdef RT_USING_SPI
//The first bit of the first byte contains the Read/Write bit and indicates the Read (1) or Write (0) operation.
tmp = reg | 0x80;
res = rt_spi_send_then_recv((struct rt_spi_device *)dev->bus, &tmp, 1, buf, len);
#endif
}
return res;
}
/** * This function writes a bit value of registers for mpu6xxx * * @param dev the pointer of device driver structure * @param reg the register for mpu6xxx * @param bit the position of the register * @param data value to write * * @return the writing status, RT_EOK reprensents writing a bit value of registers successfully. */
static rt_err_t mpu6xxx_write_bit(struct mpu6xxx_device *dev, rt_uint8_t reg, rt_uint8_t bit, rt_uint8_t data)
{
rt_uint8_t byte;
rt_err_t res;
res = mpu6xxx_read_regs(dev, reg, 1, &byte);
if (res != RT_EOK)
{
return res;
}
byte = (data != 0) ? (byte | (1 << bit)) : (byte & ~(1 << bit));
return mpu6xxx_write_reg(dev, reg, byte);
}
/** * This function reads a bit value of registers for mpu6xxx * * @param dev the pointer of device driver structure * @param reg the register for mpu6xxx * @param bit the position of the register * @param data read data pointer * * @return the reading status, RT_EOK reprensents reading a bit value of registers successfully. */
static rt_err_t mpu6xxx_read_bit(struct mpu6xxx_device *dev, rt_uint8_t reg, rt_uint8_t bit, rt_uint8_t *data)
{
rt_uint8_t byte;
rt_err_t res;
res = mpu6xxx_read_regs(dev, reg, 1, &byte);
if (res != RT_EOK)
{
return res;
}
*data = byte & (1 << bit);
return RT_EOK;
}
/** * This function writes multi-bit value of registers for mpu6xxx * * @param dev the pointer of device driver structure * @param reg the register for mpu6xxx * @param start_bit the start position of the register * @param len number of bits to write * @param data value to write * * @return the writing status, RT_EOK reprensents writing multi-bit value of registers successfully. */
static rt_err_t mpu6xxx_write_bits(struct mpu6xxx_device *dev, rt_uint8_t reg, rt_uint8_t start_bit, rt_uint8_t len, rt_uint8_t data)
{
rt_uint8_t byte, mask;
rt_err_t res;
res = mpu6xxx_read_regs(dev, reg, 1, &byte);
if (res != RT_EOK)
{
return res;
}
mask = ((1 << len) - 1) << (start_bit - len + 1);
data <<= (start_bit - len + 1); // shift data into correct position
data &= mask; // zero all non-important bits in data
byte &= ~(mask); // zero all important bits in existing byte
byte |= data; // combine data with existing byte
return mpu6xxx_write_reg(dev, reg, byte);
}
/** * This function reads multi-bit value of registers for mpu6xxx * * @param dev the pointer of device driver structure * @param reg the register for mpu6xxx * @param start_bit the start position of the register * @param len number of bits to write * @param data read data pointer * * @return the reading status, RT_EOK reprensents reading multi-bit value of registers successfully. */
static rt_err_t mpu6xxx_read_bits(struct mpu6xxx_device *dev, rt_uint8_t reg, rt_uint8_t start_bit, rt_uint8_t len, rt_uint8_t *data)
{
rt_uint8_t byte, mask;
rt_err_t res;
res = mpu6xxx_read_regs(dev, reg, 1, &byte);
if (res != RT_EOK)
{
return res;
}
mask = ((1 << len) - 1) << (start_bit - len + 1);
byte &= mask;
byte >>= (start_bit - len + 1);
*data = byte;
return RT_EOK;
}
// MAG
#ifdef PKG_USING_MPU6XXX_MAG
#define MAG_READ_DELAY_TIME 50
static void mpu92_mag_write_reg(struct mpu6xxx_device *dev, rt_uint8_t addr, rt_uint8_t data)
{
rt_uint8_t status = 0;
rt_uint32_t timeout = MAG_READ_DELAY_TIME;
mpu6xxx_write_reg(dev, MPU6XXX_RA_I2C_SLV4_ADDR, AK8963_I2C_ADDR);
mpu6xxx_write_reg(dev, MPU6XXX_RA_I2C_SLV4_REG, addr);
mpu6xxx_write_reg(dev, MPU6XXX_RA_I2C_SLV4_DO, data);
mpu6xxx_write_reg(dev, MPU6XXX_RA_I2C_SLV4_CTRL, MPU6500_I2C_SLVx_EN);
do
{
mpu6xxx_read_regs(dev, MPU6XXX_RA_I2C_MST_STATUS, 1, &status);
rt_thread_mdelay(1);
} while (((status & MPU6500_I2C_SLV4_DONE) == 0) && (timeout--));
}
#endif // PKG_USING_MPU6XXX_MAG
/** * This function gets the raw data of the accelerometer * * @param dev the pointer of device driver structure * @param accel the pointer of 3axes structure for receive data * * @return the reading status, RT_EOK reprensents reading the data successfully. */
static rt_err_t mpu6xxx_get_accel_raw(struct mpu6xxx_device *dev, struct mpu6xxx_3axes *accel)
{
rt_uint8_t buffer[6];
rt_err_t res;
res = mpu6xxx_read_regs(dev, MPU6XXX_RA_ACCEL_XOUT_H, 6, buffer);
if (res != RT_EOK)
{
return res;
}
accel->x = ((rt_uint16_t)buffer[0] << 8) + buffer[1];
accel->y = ((rt_uint16_t)buffer[2] << 8) + buffer[3];
accel->z = ((rt_uint16_t)buffer[4] << 8) + buffer[5];
return RT_EOK;
}
/** * This function gets the raw data of the gyroscope * * @param dev the pointer of device driver structure * @param gyro the pointer of 3axes structure for receive data * * @return the reading status, RT_EOK reprensents reading the data successfully. */
static rt_err_t mpu6xxx_get_gyro_raw(struct mpu6xxx_device *dev, struct mpu6xxx_3axes *gyro)
{
rt_uint8_t buffer[6];
rt_err_t res;
res = mpu6xxx_read_regs(dev, MPU6XXX_RA_GYRO_XOUT_H, 6, buffer);
if (res != RT_EOK)
{
return res;
}
gyro->x = ((rt_uint16_t)buffer[0] << 8) + buffer[1];
gyro->y = ((rt_uint16_t)buffer[2] << 8) + buffer[3];
gyro->z = ((rt_uint16_t)buffer[4] << 8) + buffer[5];
return RT_EOK;
}
#ifdef PKG_USING_MPU6XXX_MAG
/** * This function gets the raw data of the magnetometer * * @param dev the pointer of device driver structure * @param mag the pointer of 3axes structure for receive data * * @return the reading status, RT_EOK reprensents reading the data successfully. */
static rt_err_t mpu6xxx_get_mag_raw(struct mpu6xxx_device *dev, struct mpu6xxx_3axes *mag)
{
rt_uint8_t buffer[8];
rt_err_t res;
res = mpu6xxx_read_regs(dev, MPU6XXX_RA_EXT_SENS_DATA_00, 8, buffer);
if (res != RT_EOK)
{
return res;
}
mag->x = ((rt_uint16_t)buffer[2] << 8) + buffer[1];
mag->y = ((rt_uint16_t)buffer[4] << 8) + buffer[3];
mag->z = ((rt_uint16_t)buffer[6] << 8) + buffer[5];
return RT_EOK;
}
#endif
/** * This function gets the raw data of the temperature * * @param dev the pointer of device driver structure * @param temp read data pointer * * @return the reading status, RT_EOK reprensents reading the data successfully. */
static rt_err_t mpu6xxx_get_temp_raw(struct mpu6xxx_device *dev, rt_int16_t *temp)
{
rt_uint8_t buffer[2];
rt_err_t res;
res = mpu6xxx_read_regs(dev, MPU6XXX_RA_TEMP_OUT_H, 2, buffer);
if (res != RT_EOK)
{
return res;
}
*temp = ((rt_uint16_t)buffer[0] << 8) + buffer[1];
return RT_EOK;
}
/** * This function gets mpu6xxx parameters. * * @param dev the pointer of device driver structure * @param cmd Configuration item * @param param read data pointer * * @return the reading status, RT_EOK reprensents reading the data successfully. */
static rt_err_t mpu6xxx_get_param(struct mpu6xxx_device *dev, enum mpu6xxx_cmd cmd, rt_uint16_t *param)
{
rt_uint8_t data = 0;
rt_err_t res = RT_EOK;
RT_ASSERT(dev);
switch (cmd)
{
case MPU6XXX_GYRO_RANGE: /* Gyroscope full scale range */
res = mpu6xxx_read_bits(dev, MPU6XXX_RA_GYRO_CONFIG, MPU6XXX_GCONFIG_FS_SEL_BIT, MPU6XXX_GCONFIG_FS_SEL_LENGTH, &data);
*param = data;
break;
case MPU6XXX_ACCEL_RANGE: /* Accelerometer full scale range */
res = mpu6xxx_read_bits(dev, MPU6XXX_RA_ACCEL_CONFIG, MPU6XXX_ACONFIG_AFS_SEL_BIT, MPU6XXX_ACONFIG_AFS_SEL_LENGTH, &data);
*param = data;
break;
case MPU6XXX_DLPF_CONFIG: /* Digital Low Pass Filter */
res = mpu6xxx_read_bits(dev, MPU6XXX_RA_CONFIG, MPU6XXX_CFG_DLPF_CFG_BIT, MPU6XXX_CFG_DLPF_CFG_LENGTH, &data);
*param = data;
break;
case MPU6XXX_SAMPLE_RATE: /* Sample Rate */
/* Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV) */
res = mpu6xxx_read_bits(dev, MPU6XXX_RA_CONFIG, MPU6XXX_CFG_DLPF_CFG_BIT, MPU6XXX_CFG_DLPF_CFG_LENGTH, &data);
if (res != RT_EOK)
{
break;
}
if (data == 0 || data == 7) /* dlpf is disable */
{
res = mpu6xxx_read_regs(dev, MPU6XXX_RA_SMPLRT_DIV, 1, &data);
*param = 8000 / (data + 1);
}
else /* dlpf is enable */
{
res = mpu6xxx_read_regs(dev, MPU6XXX_RA_SMPLRT_DIV, 1, &data);
*param = 1000 / (data + 1);
}
break;
case MPU6XXX_SLEEP: /* sleep mode */
res = mpu6xxx_read_bit(dev, MPU6XXX_RA_PWR_MGMT_1, MPU6XXX_PWR1_SLEEP_BIT, &data);
*param = data;
break;
}
return res;
}
/** * This function set mpu6xxx parameters. * * @param de