赞
踩
MPU6050是一款流行的运动追踪传感器,它结合了3轴加速度计和3轴陀螺仪,能够提供全面的运动追踪能力。这种传感器特别适用于需要运动或方向检测的项目,如无人机、机器人和运动控制系统。
一、主要特性
(1)六轴运动追踪:MPU6050能够同时测量三个方向的加速度和三个方向的角速度,提供全面的运动追踪数据。
(2)I2C接口:它通过I2C(Inter-Integrated Circuit)总线与微控制器通信,这是一种常见的串行通信协议,允许多个设备通过两根线(数据线和时钟线)进行连接和通信。
(3)数字输出:所有测量数据都以数字形式提供,这意味着不需要额外的模拟到数字转换器(ADC)来处理信号。
(4)内置数字运动处理器(DMP):MPU6050内置的DMP可以处理复杂的运动检测算法,减轻主控制器的负担。-可编程的中断:支持可编程的中断功能,允许传感器在检测到特定运动事件时立即通知主控制器。
(5)电源管理:具有高效的电源管理系统,支持低功耗运行模式。
二、技术规格
(1)加速度计范围:±2g、±4g、±8g、±16g
(2)陀螺仪范围:±250、±500、±1000、±2000°/秒
(3)通信:I2C协议
(4)电源电压:2.3V至3.4V
(5)工作温度范围:-40°C至+85°C
三、应用领域
MPU6050广泛应用于需要运动或方向检测的领域,包括:
(1)无人机:用于稳定控制和导航。
(2)机器人:提供平衡和运动控制。
(3)可穿戴设备:用于活动追踪和姿态检测。
MPU6050的内部结构图如下:
如图所示,mpu6050内置陀螺仪,通过六路adc采集加速度和加速度并通过i2c接口输出数据。详细的介绍将在以后的文章中展现。
mpu6050.c
- #include "MPU6050.h"
- #include "Soft_I2C.h"
-
- void Delay1ms(); //@11.0592MHz
- void MPU_Delay_Ms(uint16_t Milliseconds) //
- {
- while(Milliseconds--)
- Delay1ms();
- }
-
- //IIC连续写
- //reg:要写入的寄存器地址
- //len:要写入的长度
- //buf:要写入的数据的首地址
- //返回值:0,正常
- // 其他,错误代码
- uint8_t MPU_Write_Len(uint8_t reg, uint8_t len, uint8_t *buf)
- {
- return i2c_mem_write(MPU_ADDR, reg, buf, len);
- }
-
- //IIC连续读
- //reg:要读取的寄存器地址
- //len:要读取的长度
- //buf:读取到的数据存储区
- //返回值:0,正常
- // 其他,错误代码
- uint8_t MPU_Read_Len(uint8_t reg, uint8_t len, uint8_t *buf)
- {
- return i2c_mem_read(MPU_ADDR, reg, buf, len);
- }
-
- //IIC写一个字节
- //reg:寄存器地址
- //Data:数据
- //返回值:0,正常
- // 其他,错误代码
- uint8_t MPU_Write_Byte(uint8_t reg, uint8_t Data)
- {
- return i2c_mem_write(MPU_ADDR, reg, &Data, 1);
- }
-
- //IIC读一个字节
- //reg:寄存器地址
- //返回值:读到的数据
- uint8_t MPU_Read_Byte(uint8_t reg)
- {
- uint8_t res;
- i2c_mem_read(MPU_ADDR, reg, &res, 1);
- return res;
- }
-
- //写入8位寄存器的一个位
- uint8_t MPU_Write_Bit(uint8_t addr, uint8_t bitNum, uint8_t Data)
- {
- return i2c_write_bit(MPU_ADDR, addr, bitNum, Data);
- }
-
- //写入8位寄存器的多个位
- uint8_t MPU_Write_Bits(uint8_t addr, uint8_t bitStart, uint8_t length, uint8_t Data)
- {
- return i2c_write_bits(MPU_ADDR, addr, bitStart, length, Data);
- }
-
- //读取一个位从8位器件的寄存器
- uint8_t MPU_Read_Bit(uint8_t addr, uint8_t bitNum, uint8_t *Data)
- {
- return i2c_read_bit(MPU_ADDR, addr, bitNum, Data);
- }
-
- //读取8位寄存器的多个位
- uint8_t MPU_Read_Bits(uint8_t addr, uint8_t bitStart, uint8_t length, uint8_t *Data)
- {
- return i2c_read_bits(MPU_ADDR, addr, bitStart, length, Data);
- }
-
-
- //初始化MPU6050
- //返回值:0,成功
- // 其他,错误代码
- uint8_t MPU_Init(void)
- {
- uint8_t res;
- MPU_Write_Byte(MPU_PWR_MGMT1_REG, 0X80); //复位MPU6050
- MPU_Delay_Ms(100);
- MPU_Write_Byte(MPU_PWR_MGMT1_REG, 0X00); //唤醒MPU6050
- MPU_Set_Gyro_Fsr(3); //陀螺仪传感器,±2000dps
- MPU_Set_Accel_Fsr(0); //加速度传感器,±2g
- MPU_Set_Rate(50); //设置采样率50Hz
- MPU_Write_Byte(MPU_INT_EN_REG, 0X01); //使能数据就绪中断
- MPU_Write_Byte(MPU_USER_CTRL_REG, 0X00); //I2C主模式关闭
- MPU_Write_Byte(MPU_FIFO_EN_REG, 0X00); //关闭FIFO
- MPU_Write_Byte(MPU_INTBP_CFG_REG, 0X80); //INT引脚低电平有效
- res = MPU_Read_Byte(MPU_DEVICE_ID_REG);
- if (res == MPU_ADDR)//器件ID正确
- {
- MPU_Write_Byte(MPU_PWR_MGMT1_REG, 0X01); //设置CLKSEL,PLL X轴为参考
- MPU_Write_Byte(MPU_PWR_MGMT2_REG, 0X00); //加速度与陀螺仪都工作
- MPU_Set_Rate(200); //设置采样率为200Hz
- }
- else
- return 1;
- return 0;
- }
-
- //设置MPU6050陀螺仪传感器满量程范围
- //fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps
- //返回值:0,设置成功
- // 其他,设置失败
- uint8_t MPU_Set_Gyro_Fsr(uint8_t fsr)
- {
- return MPU_Write_Byte(MPU_GYRO_CFG_REG, fsr << 3);//设置陀螺仪满量程范围
- }
-
- //设置MPU6050加速度传感器满量程范围
- //fsr:0,±2g;1,±4g;2,±8g;3,±16g
- //返回值:0,设置成功
- // 其他,设置失败
- uint8_t MPU_Set_Accel_Fsr(uint8_t fsr)
- {
- return MPU_Write_Byte(MPU_ACCEL_CFG_REG, fsr << 3);//设置加速度传感器满量程范围
- }
-
- //设置MPU6050的数字低通滤波器
- //lpf:数字低通滤波频率(Hz)
- //返回值:0,设置成功
- // 其他,设置失败
- uint8_t MPU_Set_LPF(uint16_t lpf)
- {
- uint8_t Data = 0;
- if (lpf >= 188)Data = 1;
- else if (lpf >= 98)Data = 2;
- else if (lpf >= 42)Data = 3;
- else if (lpf >= 20)Data = 4;
- else if (lpf >= 10)Data = 5;
- else Data = 6;
- return MPU_Write_Byte(MPU_CFG_REG, Data);//设置数字低通滤波器
- }
-
- //设置MPU6050的采样率(假定Fs=1KHz)
- //rate:4~1000(Hz)
- //返回值:0,设置成功
- // 其他,设置失败
- uint8_t MPU_Set_Rate(uint16_t rate)
- {
- uint8_t Data;
- if (rate>1000)rate = 1000;
- if (rate<4)rate = 4;
- Data = 1000 / rate - 1;
- Data = MPU_Write_Byte(MPU_SAMPLE_RATE_REG, Data); //设置数字低通滤波器
- return MPU_Set_LPF(rate / 2); //自动设置LPF为采样率的一半
- }
-
- //得到温度值
- //返回值:温度值(扩大了100倍)
- short MPU_Get_Temperature(void)
- {
- uint8_t buf[2];
- short raw;
- float temp;
- MPU_Read_Len(MPU_TEMP_OUTH_REG, 2, buf);
- raw = ((uint16_t)buf[0] << 8) | buf[1];
- temp = 36.53 + ((double)raw) / 340;
- return temp * 100;;
- }
-
- //得到陀螺仪值(原始值)
- //gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
- //返回值:0,成功
- // 其他,错误代码
- uint8_t MPU_Get_Gyroscope(short *gx, short *gy, short *gz)
- {
- uint8_t buf[6], res;
- res = MPU_Read_Len(MPU_GYRO_XOUTH_REG, 6, buf);
- if (res == 0)
- {
- *gx = ((uint16_t)buf[0] << 8) | buf[1];
- *gy = ((uint16_t)buf[2] << 8) | buf[3];
- *gz = ((uint16_t)buf[4] << 8) | buf[5];
- }
- return res;;
- }
-
- //得到加速度值(原始值)
- //gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
- //返回值:0,成功
- // 其他,错误代码
- uint8_t MPU_Get_Accelerometer(short *ax, short *ay, short *az)
- {
- uint8_t buf[6], res;
- res = MPU_Read_Len(MPU_ACCEL_XOUTH_REG, 6, buf);
- if (res == 0)
- {
- *ax = ((uint16_t)buf[0] << 8) | buf[1];
- *ay = ((uint16_t)buf[2] << 8) | buf[3];
- *az = ((uint16_t)buf[4] << 8) | buf[5];
- }
- return res;;
- }
-

mpu6050.h
- #ifndef __MPU6050_H
- #define __MPU6050_H
-
- #include "stdint.h"
-
-
- #define MPU_ACCEL_OFFS_REG 0X06 //accel_offs寄存器,可读取版本号,寄存器手册未提到
- #define MPU_PROD_ID_REG 0X0C //prod id寄存器,在寄存器手册未提到
- #define MPU_SELF_TESTX_REG 0X0D //自检寄存器X
- #define MPU_SELF_TESTY_REG 0X0E //自检寄存器Y
- #define MPU_SELF_TESTZ_REG 0X0F //自检寄存器Z
- #define MPU_SELF_TESTA_REG 0X10 //自检寄存器A
- #define MPU_SAMPLE_RATE_REG 0X19 //采样频率分频器
- #define MPU_CFG_REG 0X1A //配置寄存器
- #define MPU_GYRO_CFG_REG 0X1B //陀螺仪配置寄存器
- #define MPU_ACCEL_CFG_REG 0X1C //加速度计配置寄存器
- #define MPU_MOTION_DET_REG 0X1F //运动检测阀值设置寄存器
- #define MPU_FIFO_EN_REG 0X23 //FIFO使能寄存器
- #define MPU_I2CMST_CTRL_REG 0X24 //IIC主机控制寄存器
- #define MPU_I2CSLV0_ADDR_REG 0X25 //IIC从机0器件地址寄存器
- #define MPU_I2CSLV0_REG 0X26 //IIC从机0数据地址寄存器
- #define MPU_I2CSLV0_CTRL_REG 0X27 //IIC从机0控制寄存器
- #define MPU_I2CSLV1_ADDR_REG 0X28 //IIC从机1器件地址寄存器
- #define MPU_I2CSLV1_REG 0X29 //IIC从机1数据地址寄存器
- #define MPU_I2CSLV1_CTRL_REG 0X2A //IIC从机1控制寄存器
- #define MPU_I2CSLV2_ADDR_REG 0X2B //IIC从机2器件地址寄存器
- #define MPU_I2CSLV2_REG 0X2C //IIC从机2数据地址寄存器
- #define MPU_I2CSLV2_CTRL_REG 0X2D //IIC从机2控制寄存器
- #define MPU_I2CSLV3_ADDR_REG 0X2E //IIC从机3器件地址寄存器
- #define MPU_I2CSLV3_REG 0X2F //IIC从机3数据地址寄存器
- #define MPU_I2CSLV3_CTRL_REG 0X30 //IIC从机3控制寄存器
- #define MPU_I2CSLV4_ADDR_REG 0X31 //IIC从机4器件地址寄存器
- #define MPU_I2CSLV4_REG 0X32 //IIC从机4数据地址寄存器
- #define MPU_I2CSLV4_DO_REG 0X33 //IIC从机4写数据寄存器
- #define MPU_I2CSLV4_CTRL_REG 0X34 //IIC从机4控制寄存器
- #define MPU_I2CSLV4_DI_REG 0X35 //IIC从机4读数据寄存器
-
- #define MPU_I2CMST_STA_REG 0X36 //IIC主机状态寄存器
- #define MPU_INTBP_CFG_REG 0X37 //中断/旁路设置寄存器
- #define MPU_INT_EN_REG 0X38 //中断使能寄存器
- #define MPU_INT_STA_REG 0X3A //中断状态寄存器
-
- #define MPU_ACCEL_XOUTH_REG 0X3B //加速度值,X轴高8位寄存器
- #define MPU_ACCEL_XOUTL_REG 0X3C //加速度值,X轴低8位寄存器
- #define MPU_ACCEL_YOUTH_REG 0X3D //加速度值,Y轴高8位寄存器
- #define MPU_ACCEL_YOUTL_REG 0X3E //加速度值,Y轴低8位寄存器
- #define MPU_ACCEL_ZOUTH_REG 0X3F //加速度值,Z轴高8位寄存器
- #define MPU_ACCEL_ZOUTL_REG 0X40 //加速度值,Z轴低8位寄存器
-
- #define MPU_TEMP_OUTH_REG 0X41 //温度值高八位寄存器
- #define MPU_TEMP_OUTL_REG 0X42 //温度值低8位寄存器
-
- #define MPU_GYRO_XOUTH_REG 0X43 //陀螺仪值,X轴高8位寄存器
- #define MPU_GYRO_XOUTL_REG 0X44 //陀螺仪值,X轴低8位寄存器
- #define MPU_GYRO_YOUTH_REG 0X45 //陀螺仪值,Y轴高8位寄存器
- #define MPU_GYRO_YOUTL_REG 0X46 //陀螺仪值,Y轴低8位寄存器
- #define MPU_GYRO_ZOUTH_REG 0X47 //陀螺仪值,Z轴高8位寄存器
- #define MPU_GYRO_ZOUTL_REG 0X48 //陀螺仪值,Z轴低8位寄存器
-
- #define MPU_I2CSLV0_DO_REG 0X63 //IIC从机0数据寄存器
- #define MPU_I2CSLV1_DO_REG 0X64 //IIC从机1数据寄存器
- #define MPU_I2CSLV2_DO_REG 0X65 //IIC从机2数据寄存器
- #define MPU_I2CSLV3_DO_REG 0X66 //IIC从机3数据寄存器
-
- #define MPU_I2CMST_DELAY_REG 0X67 //IIC主机延时管理寄存器
- #define MPU_SIGPATH_RST_REG 0X68 //信号通道复位寄存器
- #define MPU_MDETECT_CTRL_REG 0X69 //运动检测控制寄存器
- #define MPU_USER_CTRL_REG 0X6A //用户控制寄存器
- #define MPU_PWR_MGMT1_REG 0X6B //电源管理寄存器1
- #define MPU_PWR_MGMT2_REG 0X6C //电源管理寄存器2
- #define MPU_FIFO_CNTH_REG 0X72 //FIFO计数寄存器高八位
- #define MPU_FIFO_CNTL_REG 0X73 //FIFO计数寄存器低八位
- #define MPU_FIFO_RW_REG 0X74 //FIFO读写寄存器
- #define MPU_DEVICE_ID_REG 0X75 //器件ID寄存器
-
- //如果AD0脚(9脚)接地,IIC地址为0X68(不包含最低位).
- //如果接V3.3,则IIC地址为0X69(不包含最低位).
- #define MPU_ADDR 0X68 //此为7位地址
-
- //因为模块AD0默认接GND,所以转为读写地址后,为0XD1和0XD0(如果接VCC,则为0XD3和0XD2)
- #define MPU_READ 0XD1
- #define MPU_WRITE 0XD0
-
- uint8_t MPU_Init(void); //初始化MPU6050
- uint8_t MPU_Read_Len(uint8_t reg, uint8_t len, uint8_t *buf); //IIC连续读
- uint8_t MPU_Write_Len(uint8_t reg, uint8_t len, uint8_t *buf); //IIC连续写
- uint8_t MPU_Write_Byte(uint8_t reg, uint8_t Data); //IIC写一个字节
- uint8_t MPU_Read_Byte(uint8_t reg); //IIC读一个字节
- uint8_t MPU_Write_Bit(uint8_t addr, uint8_t bitNum, uint8_t Data); //写入8位寄存器的一个位
- uint8_t MPU_Write_Bits(uint8_t addr, uint8_t bitStart, uint8_t length, uint8_t Data);//写入8位寄存器的多个位
- uint8_t MPU_Read_Bit(uint8_t addr, uint8_t bitNum, uint8_t *Data); //读取一个位从8位器件的寄存器
- uint8_t MPU_Read_Bits(uint8_t addr, uint8_t bitStart, uint8_t length, uint8_t *Data);//读取8位寄存器的多个位
-
- uint8_t MPU_Set_Gyro_Fsr(uint8_t fsr);
- uint8_t MPU_Set_Accel_Fsr(uint8_t fsr);
- uint8_t MPU_Set_LPF(uint16_t lpf);
- uint8_t MPU_Set_Rate(uint16_t rate);
-
- int16_t MPU_Get_Temperature(void);
- uint8_t MPU_Get_Gyroscope(int16_t *gx, int16_t *gy, int16_t *gz);
- uint8_t MPU_Get_Accelerometer(int16_t *ax, int16_t *ay, int16_t *az);
-
- #define MPU_Refresh() MPU_Write_Byte(MPU_PWR_MGMT1_REG, 0X00) //唤醒MPU6050
-
- void MPU_Delay_Ms(uint16_t Milliseconds); //
-
- #endif
-

iic.c
- #include "Soft_I2C.h"
-
- #define I2C_TIMEOUT_TIMES 100 //超时倍数
-
- //延时 用于等待应答时的超时判断
- void i2c_timeout_delay(void)
- {
-
- }
-
- void i2c_delay() //每步的间隔 用于等待电平稳定和控制通讯速率
- {
-
- }
-
- //SCL拉高
- void I2C_SCL_H(void)
- {
- I2C_SCL = 1;
- }
-
- //SCL拉低
- void I2C_SCL_L(void)
- {
- I2C_SCL = 0;
- }
-
- //SDA拉高
- void I2C_SDA_H(void)
- {
- I2C_SDA = 1;
- }
-
- //SDA拉低
- void I2C_SDA_L(void)
- {
- I2C_SDA = 0;
- }
-
- //读取SDA
- uint8_t I2C_SDA_Read(void)
- {
- return I2C_SDA;
- }
-
- /*******************************************************************************
- * 函 数 名 : i2c_start
- * 函数功能 : 产生I2C起始信号
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void i2c_start(void)
- {
- I2C_SDA_H();
- I2C_SCL_H();
- i2c_delay();
-
- I2C_SDA_L(); //当SCL为高电平时,SDA由高变为低
- i2c_delay();
- I2C_SCL_L(); //钳住I2C总线,准备发送或接收数据
- }
-
- /*******************************************************************************
- * 函 数 名 : i2c_stop
- * 函数功能 : 产生I2C停止信号
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void i2c_stop(void)
- {
- I2C_SDA_L();
- I2C_SCL_H();
- i2c_delay();
-
- I2C_SDA_H(); //当SCL为高电平时,SDA由低变为高
- i2c_delay();
- }
-
- /*******************************************************************************
- * 函 数 名 : i2c_ack
- * 函数功能 : 产生ACK应答
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void i2c_ack(void)
- {
- I2C_SCL_L();
- I2C_SDA_L(); //SDA为低电平
- i2c_delay();
-
- I2C_SCL_H();
- i2c_delay();
- I2C_SCL_L();
- I2C_SDA_H();
- }
-
- /*******************************************************************************
- * 函 数 名 : i2c_nack
- * 函数功能 : 产生NACK非应答
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void i2c_nack(void)
- {
- I2C_SCL_L();
- I2C_SDA_H(); //SDA为高电平
- i2c_delay();
-
- I2C_SCL_H();
- i2c_delay();
- I2C_SCL_L();
- }
-
- /*******************************************************************************
- * 函 数 名 : i2c_wait_ack
- * 函数功能 : 等待应答信号到来
- * 输 入 : 无
- * 输 出 : 1,接收应答失败
- 0,接收应答成功
- *******************************************************************************/
- uint8_t i2c_wait_ack(void)
- {
- uint16_t time_temp = 0;
-
- I2C_SCL_H();
- i2c_delay();
- while(I2C_SDA_Read()) //等待SDA为低电平
- {
- time_temp++;
- i2c_timeout_delay();
- if(time_temp > I2C_TIMEOUT_TIMES) //超时则强制结束I2C通信
- {
- i2c_stop();
- return 1;
- }
- }
- I2C_SCL_L();
- return 0;
- }
-
- /*******************************************************************************
- * 函 数 名 : i2c_write_byte
- * 函数功能 : I2C发送一个字节
- * 输 入 : dat:发送一个字节
- * 输 出 : 无
- *******************************************************************************/
- void i2c_write_byte(uint8_t dat)
- {
- uint8_t i = 0;
-
- I2C_SCL_L();
- for(i = 0; i<8; i++) //循环8次将一个字节传出,先传高再传低位
- {
- if((dat & 0x80) > 0)
- I2C_SDA_H();
- else
- I2C_SDA_L();
- dat <<= 1;
- i2c_delay();
- I2C_SCL_H();
- i2c_delay();
- I2C_SCL_L();
- i2c_delay();
- }
- }
-
- /*******************************************************************************
- * 函 数 名 : i2c_read_byte
- * 函数功能 : I2C读一个字节
- * 输 入 : ack = 1时,发送ACK,ack = 0,发送nACK
- * 输 出 : 应答或非应答
- *******************************************************************************/
- uint8_t i2c_read_byte(uint8_t ack)
- {
- uint8_t i = 0, receive = 0;
-
- for(i = 0; i < 8; i++ ) //循环8次将一个字节读出,先读高再传低位
- {
- I2C_SCL_L();
- i2c_delay();
- I2C_SCL_H();
- receive <<= 1;
- if(I2C_SDA_Read())
- receive++;
- i2c_delay();
- }
- if (!ack)
- i2c_nack();
- else
- i2c_ack();
-
- return receive;
- }
-
- /*******************************************************************************
- * 函 数 名 : i2c_mem_write
- * 函数功能 : I2C对指定器件、指定寄存器连续写入
- * 输 入 : 器件地址、器件寄存器地址、待输入数据首地址、待输入数据长度
- * 输 出 : 0: 成功 1:失败
- *******************************************************************************/
- uint8_t i2c_mem_write(uint8_t DevAddress, uint8_t MemAddress, uint8_t *pData, uint16_t Len)
- {
- i2c_start();
- i2c_write_byte(DevAddress << 1);
- if(i2c_wait_ack())
- return 1;
- i2c_write_byte(MemAddress);
- if(i2c_wait_ack())
- return 1;
- while(Len--)
- {
- i2c_write_byte(*pData++);
- if(i2c_wait_ack())
- return 1;
- }
- i2c_stop();
- return 0;
- }
-
- /*******************************************************************************
- * 函 数 名 : i2c_mem_read
- * 函数功能 : I2C对指定器件、指定寄存器连续读取
- * 输 入 : 器件地址、器件寄存器地址、数据缓冲区首地址、数据长度
- * 输 出 : 0: 成功 1:失败
- *******************************************************************************/
- uint8_t i2c_mem_read(uint8_t DevAddress, uint8_t MemAddress, uint8_t *pBuffer, uint16_t Len)
- {
- i2c_start();
- i2c_write_byte(DevAddress << 1); //发送写命令
- if(i2c_wait_ack())
- return 1;
- i2c_write_byte(MemAddress); //发送字地址
- if(i2c_wait_ack())
- return 1;
- i2c_start();
- i2c_write_byte(DevAddress << 1 | 1); //进入接收模式
- if(i2c_wait_ack())
- return 1;
- while(Len--)
- {
- *pBuffer++ = i2c_read_byte(Len!=0); //读取字节
- }
- i2c_stop(); //产生一个停止条件
- return 0;
- }
-
- /**写入8位寄存器的一个位。
- * @参数 DevAddress I2C从器件地址
- * @参数 addr I2C从器件内部地址
- * @参数 bitNum 写入的比特位(0-7)
- * @参数 data 写入数据
- * @返回值 返回状态 (0=成功)
- */
- uint8_t i2c_write_bit(uint8_t DevAddress, uint8_t addr, uint8_t bitNum, uint8_t Data)
- {
- uint8_t b;
- if (!i2c_mem_read(DevAddress, addr, &b, 1))
- {
- b = (Data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum));
- return i2c_mem_write(DevAddress, addr, &b, 1); //写入数据
- }
- else
- return 1;
- }
-
- /**写入8位寄存器的多个位。
- * @参数 DevAddress I2C从器件地址
- * @参数 addr I2C从器件内部地址
- * @参数 bitStart 第一位的写入位置(0-7)
- * @参数 length 写的比特数(不超过8)
- * @参数 Data 写入数据
- * @返回值 返回状态 (0=成功)
- */
- uint8_t i2c_write_bits(uint8_t DevAddress, uint8_t addr, uint8_t bitStart, uint8_t length, uint8_t Data)
- {
- // 010 要写入的值
- // 76543210 比特位
- // xxx args: bitStart=4, length=3
- // 00011100 掩码字节
- // 10101111 原始值(样本)
- // 10100011 原始值 & ~掩码
- // 10101011 掩码 | 原始值
- uint8_t b, mask = 0;
- if (!i2c_mem_read(DevAddress, addr, &b, 1))
- {
- mask = (((1 << length) - 1) << (bitStart - length + 1)); //掩码
- Data <<= (bitStart - length + 1); //把写入的数据移动到位
- Data &= mask;
- b &= ~(mask);
- b |= Data;
-
- return i2c_mem_write(DevAddress, addr, &b, 1); //写入数据
- }
- else
- return 1;
- }
- /**读取一个位从8位器件的寄存器。
- * @参数 DevAddress I2C从器件地址
- * @参数 addr I2C从器件内部地址
- * @参数 bitNum 位的位置来读取(0-7)
- * @参数 *data 数据存储地址
- * @返回值(0=成功)
- */
- uint8_t i2c_read_bit(uint8_t DevAddress, uint8_t addr, uint8_t bitNum, uint8_t *Data)
- {
- uint8_t b;
- if (!i2c_mem_read(DevAddress, addr, &b, 1))
- {
- *Data = b & (1 << bitNum);
- return 0;
- }
- else
- {
- return 1;
- }
- }
- /**读取8位寄存器的多个位。
- * @参数 DevAddress I2C从器件地址
- * @参数 addr I2C从器件内部地址
- * @参数 bitStart第一位的位置读取(0-7)
- * @参数 length 位读取@参数长度数(不超过8)
- * @参数 *data 数据存储地址(即'101'任何bitStart位置读取将等于0X05)
- * @返回值(0=成功)
- */
- uint8_t i2c_read_bits(uint8_t DevAddress, uint8_t addr, uint8_t bitStart, uint8_t length, uint8_t *Data)
- {
- // 01101001 读取字节
- // 76543210 比特位
- // xxx args: bitStart=4, length=3
- // 010 masked
- // -> 010 shifted
- uint8_t b, mask = 0;
- if (!i2c_mem_read(DevAddress, addr, &b, 1))
- {
-
- mask = ((1 << length) - 1) << (bitStart - length + 1);
- b &= mask;
- b >>= (bitStart - length + 1);
- *Data = b;
- return 0;
- }
- else
- return 1;
- }

i2c.h
- #ifndef SOFT_I2C_H_
- #define SOFT_I2C_H_
-
- #include <reg52.h>
- #include "stdint.h"
-
- //定义I2C控制脚
- sbit I2C_SCL = P3^4; //SCL时钟线
- sbit I2C_SDA = P3^5; //SDA数据线
-
- //I2C所有操作函数
- void i2c_start(void); //发送I2C开始信号
- void i2c_stop(void); //发送I2C停止信号
- uint8_t i2c_wait_ack(void); //I2C等待ACK信号
- void i2c_ack(void); //I2C发送ACK信号
- void i2c_nack(void); //I2C不发送ACK信号
-
- void i2c_write_byte(uint8_t txd); //I2C发送一个字节
- uint8_t i2c_read_byte(uint8_t ack); //I2C读取一个字节
- uint8_t i2c_mem_write(uint8_t DevAddress, uint8_t MemAddress, uint8_t *pData, uint16_t Len); //I2C对指定器件、指定寄存器连续写入
- uint8_t i2c_mem_read(uint8_t DevAddress, uint8_t MemAddress, uint8_t *pBuffer, uint16_t Len); //I2C对指定器件、指定寄存器连续读取
- uint8_t i2c_write_bit(uint8_t DevAddress, uint8_t addr, uint8_t bitNum, uint8_t Data); //写入8位寄存器的一个位
- uint8_t i2c_write_bits(uint8_t DevAddress, uint8_t addr, uint8_t bitStart, uint8_t length, uint8_t Data);//写入8位寄存器的多个位
- uint8_t i2c_read_bit(uint8_t DevAddress, uint8_t addr, uint8_t bitNum, uint8_t *Data); //读取一个位从8位器件的寄存器
- uint8_t i2c_read_bits(uint8_t DevAddress, uint8_t addr, uint8_t bitStart, uint8_t length, uint8_t *Data);//读取8位寄存器的多个位
-
- #endif
-

mpu6050资料众多,使用方便,适用于多种应用场景,传统的51单片机受限于i2c读取速率,实时性不一定符合应用需求,建议用32位单片机。
好耶,又水了一篇
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。