当前位置:   article > 正文

51单片机(九)驱动mpu6050_单片机 mpu6050

单片机 mpu6050

文章目录

mpu6050介绍

        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的内部结构图如下:

        如图所示,mpu6050内置陀螺仪,通过六路adc采集加速度和加速度并通过i2c接口输出数据。详细的介绍将在以后的文章中展现。

mpu6050驱动代码(来自git)

mpu6050.c

  1. #include "MPU6050.h"
  2. #include "Soft_I2C.h"
  3. void Delay1ms(); //@11.0592MHz
  4. void MPU_Delay_Ms(uint16_t Milliseconds) //
  5. {
  6. while(Milliseconds--)
  7. Delay1ms();
  8. }
  9. //IIC连续写
  10. //reg:要写入的寄存器地址
  11. //len:要写入的长度
  12. //buf:要写入的数据的首地址
  13. //返回值:0,正常
  14. // 其他,错误代码
  15. uint8_t MPU_Write_Len(uint8_t reg, uint8_t len, uint8_t *buf)
  16. {
  17. return i2c_mem_write(MPU_ADDR, reg, buf, len);
  18. }
  19. //IIC连续读
  20. //reg:要读取的寄存器地址
  21. //len:要读取的长度
  22. //buf:读取到的数据存储区
  23. //返回值:0,正常
  24. // 其他,错误代码
  25. uint8_t MPU_Read_Len(uint8_t reg, uint8_t len, uint8_t *buf)
  26. {
  27. return i2c_mem_read(MPU_ADDR, reg, buf, len);
  28. }
  29. //IIC写一个字节
  30. //reg:寄存器地址
  31. //Data:数据
  32. //返回值:0,正常
  33. // 其他,错误代码
  34. uint8_t MPU_Write_Byte(uint8_t reg, uint8_t Data)
  35. {
  36. return i2c_mem_write(MPU_ADDR, reg, &Data, 1);
  37. }
  38. //IIC读一个字节
  39. //reg:寄存器地址
  40. //返回值:读到的数据
  41. uint8_t MPU_Read_Byte(uint8_t reg)
  42. {
  43. uint8_t res;
  44. i2c_mem_read(MPU_ADDR, reg, &res, 1);
  45. return res;
  46. }
  47. //写入8位寄存器的一个位
  48. uint8_t MPU_Write_Bit(uint8_t addr, uint8_t bitNum, uint8_t Data)
  49. {
  50. return i2c_write_bit(MPU_ADDR, addr, bitNum, Data);
  51. }
  52. //写入8位寄存器的多个位
  53. uint8_t MPU_Write_Bits(uint8_t addr, uint8_t bitStart, uint8_t length, uint8_t Data)
  54. {
  55. return i2c_write_bits(MPU_ADDR, addr, bitStart, length, Data);
  56. }
  57. //读取一个位从8位器件的寄存器
  58. uint8_t MPU_Read_Bit(uint8_t addr, uint8_t bitNum, uint8_t *Data)
  59. {
  60. return i2c_read_bit(MPU_ADDR, addr, bitNum, Data);
  61. }
  62. //读取8位寄存器的多个位
  63. uint8_t MPU_Read_Bits(uint8_t addr, uint8_t bitStart, uint8_t length, uint8_t *Data)
  64. {
  65. return i2c_read_bits(MPU_ADDR, addr, bitStart, length, Data);
  66. }
  67. //初始化MPU6050
  68. //返回值:0,成功
  69. // 其他,错误代码
  70. uint8_t MPU_Init(void)
  71. {
  72. uint8_t res;
  73. MPU_Write_Byte(MPU_PWR_MGMT1_REG, 0X80); //复位MPU6050
  74. MPU_Delay_Ms(100);
  75. MPU_Write_Byte(MPU_PWR_MGMT1_REG, 0X00); //唤醒MPU6050
  76. MPU_Set_Gyro_Fsr(3); //陀螺仪传感器,±2000dps
  77. MPU_Set_Accel_Fsr(0); //加速度传感器,±2g
  78. MPU_Set_Rate(50); //设置采样率50Hz
  79. MPU_Write_Byte(MPU_INT_EN_REG, 0X01); //使能数据就绪中断
  80. MPU_Write_Byte(MPU_USER_CTRL_REG, 0X00); //I2C主模式关闭
  81. MPU_Write_Byte(MPU_FIFO_EN_REG, 0X00); //关闭FIFO
  82. MPU_Write_Byte(MPU_INTBP_CFG_REG, 0X80); //INT引脚低电平有效
  83. res = MPU_Read_Byte(MPU_DEVICE_ID_REG);
  84. if (res == MPU_ADDR)//器件ID正确
  85. {
  86. MPU_Write_Byte(MPU_PWR_MGMT1_REG, 0X01); //设置CLKSEL,PLL X轴为参考
  87. MPU_Write_Byte(MPU_PWR_MGMT2_REG, 0X00); //加速度与陀螺仪都工作
  88. MPU_Set_Rate(200); //设置采样率为200Hz
  89. }
  90. else
  91. return 1;
  92. return 0;
  93. }
  94. //设置MPU6050陀螺仪传感器满量程范围
  95. //fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps
  96. //返回值:0,设置成功
  97. // 其他,设置失败
  98. uint8_t MPU_Set_Gyro_Fsr(uint8_t fsr)
  99. {
  100. return MPU_Write_Byte(MPU_GYRO_CFG_REG, fsr << 3);//设置陀螺仪满量程范围
  101. }
  102. //设置MPU6050加速度传感器满量程范围
  103. //fsr:0,±2g;1,±4g;2,±8g;3,±16g
  104. //返回值:0,设置成功
  105. // 其他,设置失败
  106. uint8_t MPU_Set_Accel_Fsr(uint8_t fsr)
  107. {
  108. return MPU_Write_Byte(MPU_ACCEL_CFG_REG, fsr << 3);//设置加速度传感器满量程范围
  109. }
  110. //设置MPU6050的数字低通滤波器
  111. //lpf:数字低通滤波频率(Hz)
  112. //返回值:0,设置成功
  113. // 其他,设置失败
  114. uint8_t MPU_Set_LPF(uint16_t lpf)
  115. {
  116. uint8_t Data = 0;
  117. if (lpf >= 188)Data = 1;
  118. else if (lpf >= 98)Data = 2;
  119. else if (lpf >= 42)Data = 3;
  120. else if (lpf >= 20)Data = 4;
  121. else if (lpf >= 10)Data = 5;
  122. else Data = 6;
  123. return MPU_Write_Byte(MPU_CFG_REG, Data);//设置数字低通滤波器
  124. }
  125. //设置MPU6050的采样率(假定Fs=1KHz)
  126. //rate:4~1000(Hz)
  127. //返回值:0,设置成功
  128. // 其他,设置失败
  129. uint8_t MPU_Set_Rate(uint16_t rate)
  130. {
  131. uint8_t Data;
  132. if (rate>1000)rate = 1000;
  133. if (rate<4)rate = 4;
  134. Data = 1000 / rate - 1;
  135. Data = MPU_Write_Byte(MPU_SAMPLE_RATE_REG, Data); //设置数字低通滤波器
  136. return MPU_Set_LPF(rate / 2); //自动设置LPF为采样率的一半
  137. }
  138. //得到温度值
  139. //返回值:温度值(扩大了100倍)
  140. short MPU_Get_Temperature(void)
  141. {
  142. uint8_t buf[2];
  143. short raw;
  144. float temp;
  145. MPU_Read_Len(MPU_TEMP_OUTH_REG, 2, buf);
  146. raw = ((uint16_t)buf[0] << 8) | buf[1];
  147. temp = 36.53 + ((double)raw) / 340;
  148. return temp * 100;;
  149. }
  150. //得到陀螺仪值(原始值)
  151. //gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
  152. //返回值:0,成功
  153. // 其他,错误代码
  154. uint8_t MPU_Get_Gyroscope(short *gx, short *gy, short *gz)
  155. {
  156. uint8_t buf[6], res;
  157. res = MPU_Read_Len(MPU_GYRO_XOUTH_REG, 6, buf);
  158. if (res == 0)
  159. {
  160. *gx = ((uint16_t)buf[0] << 8) | buf[1];
  161. *gy = ((uint16_t)buf[2] << 8) | buf[3];
  162. *gz = ((uint16_t)buf[4] << 8) | buf[5];
  163. }
  164. return res;;
  165. }
  166. //得到加速度值(原始值)
  167. //gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
  168. //返回值:0,成功
  169. // 其他,错误代码
  170. uint8_t MPU_Get_Accelerometer(short *ax, short *ay, short *az)
  171. {
  172. uint8_t buf[6], res;
  173. res = MPU_Read_Len(MPU_ACCEL_XOUTH_REG, 6, buf);
  174. if (res == 0)
  175. {
  176. *ax = ((uint16_t)buf[0] << 8) | buf[1];
  177. *ay = ((uint16_t)buf[2] << 8) | buf[3];
  178. *az = ((uint16_t)buf[4] << 8) | buf[5];
  179. }
  180. return res;;
  181. }

mpu6050.h

  1. #ifndef __MPU6050_H
  2. #define __MPU6050_H
  3. #include "stdint.h"
  4. #define MPU_ACCEL_OFFS_REG 0X06 //accel_offs寄存器,可读取版本号,寄存器手册未提到
  5. #define MPU_PROD_ID_REG 0X0C //prod id寄存器,在寄存器手册未提到
  6. #define MPU_SELF_TESTX_REG 0X0D //自检寄存器X
  7. #define MPU_SELF_TESTY_REG 0X0E //自检寄存器Y
  8. #define MPU_SELF_TESTZ_REG 0X0F //自检寄存器Z
  9. #define MPU_SELF_TESTA_REG 0X10 //自检寄存器A
  10. #define MPU_SAMPLE_RATE_REG 0X19 //采样频率分频器
  11. #define MPU_CFG_REG 0X1A //配置寄存器
  12. #define MPU_GYRO_CFG_REG 0X1B //陀螺仪配置寄存器
  13. #define MPU_ACCEL_CFG_REG 0X1C //加速度计配置寄存器
  14. #define MPU_MOTION_DET_REG 0X1F //运动检测阀值设置寄存器
  15. #define MPU_FIFO_EN_REG 0X23 //FIFO使能寄存器
  16. #define MPU_I2CMST_CTRL_REG 0X24 //IIC主机控制寄存器
  17. #define MPU_I2CSLV0_ADDR_REG 0X25 //IIC从机0器件地址寄存器
  18. #define MPU_I2CSLV0_REG 0X26 //IIC从机0数据地址寄存器
  19. #define MPU_I2CSLV0_CTRL_REG 0X27 //IIC从机0控制寄存器
  20. #define MPU_I2CSLV1_ADDR_REG 0X28 //IIC从机1器件地址寄存器
  21. #define MPU_I2CSLV1_REG 0X29 //IIC从机1数据地址寄存器
  22. #define MPU_I2CSLV1_CTRL_REG 0X2A //IIC从机1控制寄存器
  23. #define MPU_I2CSLV2_ADDR_REG 0X2B //IIC从机2器件地址寄存器
  24. #define MPU_I2CSLV2_REG 0X2C //IIC从机2数据地址寄存器
  25. #define MPU_I2CSLV2_CTRL_REG 0X2D //IIC从机2控制寄存器
  26. #define MPU_I2CSLV3_ADDR_REG 0X2E //IIC从机3器件地址寄存器
  27. #define MPU_I2CSLV3_REG 0X2F //IIC从机3数据地址寄存器
  28. #define MPU_I2CSLV3_CTRL_REG 0X30 //IIC从机3控制寄存器
  29. #define MPU_I2CSLV4_ADDR_REG 0X31 //IIC从机4器件地址寄存器
  30. #define MPU_I2CSLV4_REG 0X32 //IIC从机4数据地址寄存器
  31. #define MPU_I2CSLV4_DO_REG 0X33 //IIC从机4写数据寄存器
  32. #define MPU_I2CSLV4_CTRL_REG 0X34 //IIC从机4控制寄存器
  33. #define MPU_I2CSLV4_DI_REG 0X35 //IIC从机4读数据寄存器
  34. #define MPU_I2CMST_STA_REG 0X36 //IIC主机状态寄存器
  35. #define MPU_INTBP_CFG_REG 0X37 //中断/旁路设置寄存器
  36. #define MPU_INT_EN_REG 0X38 //中断使能寄存器
  37. #define MPU_INT_STA_REG 0X3A //中断状态寄存器
  38. #define MPU_ACCEL_XOUTH_REG 0X3B //加速度值,X轴高8位寄存器
  39. #define MPU_ACCEL_XOUTL_REG 0X3C //加速度值,X轴低8位寄存器
  40. #define MPU_ACCEL_YOUTH_REG 0X3D //加速度值,Y轴高8位寄存器
  41. #define MPU_ACCEL_YOUTL_REG 0X3E //加速度值,Y轴低8位寄存器
  42. #define MPU_ACCEL_ZOUTH_REG 0X3F //加速度值,Z轴高8位寄存器
  43. #define MPU_ACCEL_ZOUTL_REG 0X40 //加速度值,Z轴低8位寄存器
  44. #define MPU_TEMP_OUTH_REG 0X41 //温度值高八位寄存器
  45. #define MPU_TEMP_OUTL_REG 0X42 //温度值低8位寄存器
  46. #define MPU_GYRO_XOUTH_REG 0X43 //陀螺仪值,X轴高8位寄存器
  47. #define MPU_GYRO_XOUTL_REG 0X44 //陀螺仪值,X轴低8位寄存器
  48. #define MPU_GYRO_YOUTH_REG 0X45 //陀螺仪值,Y轴高8位寄存器
  49. #define MPU_GYRO_YOUTL_REG 0X46 //陀螺仪值,Y轴低8位寄存器
  50. #define MPU_GYRO_ZOUTH_REG 0X47 //陀螺仪值,Z轴高8位寄存器
  51. #define MPU_GYRO_ZOUTL_REG 0X48 //陀螺仪值,Z轴低8位寄存器
  52. #define MPU_I2CSLV0_DO_REG 0X63 //IIC从机0数据寄存器
  53. #define MPU_I2CSLV1_DO_REG 0X64 //IIC从机1数据寄存器
  54. #define MPU_I2CSLV2_DO_REG 0X65 //IIC从机2数据寄存器
  55. #define MPU_I2CSLV3_DO_REG 0X66 //IIC从机3数据寄存器
  56. #define MPU_I2CMST_DELAY_REG 0X67 //IIC主机延时管理寄存器
  57. #define MPU_SIGPATH_RST_REG 0X68 //信号通道复位寄存器
  58. #define MPU_MDETECT_CTRL_REG 0X69 //运动检测控制寄存器
  59. #define MPU_USER_CTRL_REG 0X6A //用户控制寄存器
  60. #define MPU_PWR_MGMT1_REG 0X6B //电源管理寄存器1
  61. #define MPU_PWR_MGMT2_REG 0X6C //电源管理寄存器2
  62. #define MPU_FIFO_CNTH_REG 0X72 //FIFO计数寄存器高八位
  63. #define MPU_FIFO_CNTL_REG 0X73 //FIFO计数寄存器低八位
  64. #define MPU_FIFO_RW_REG 0X74 //FIFO读写寄存器
  65. #define MPU_DEVICE_ID_REG 0X75 //器件ID寄存器
  66. //如果AD0脚(9脚)接地,IIC地址为0X68(不包含最低位).
  67. //如果接V3.3,则IIC地址为0X69(不包含最低位).
  68. #define MPU_ADDR 0X68 //此为7位地址
  69. //因为模块AD0默认接GND,所以转为读写地址后,为0XD1和0XD0(如果接VCC,则为0XD3和0XD2)
  70. #define MPU_READ 0XD1
  71. #define MPU_WRITE 0XD0
  72. uint8_t MPU_Init(void); //初始化MPU6050
  73. uint8_t MPU_Read_Len(uint8_t reg, uint8_t len, uint8_t *buf); //IIC连续读
  74. uint8_t MPU_Write_Len(uint8_t reg, uint8_t len, uint8_t *buf); //IIC连续写
  75. uint8_t MPU_Write_Byte(uint8_t reg, uint8_t Data); //IIC写一个字节
  76. uint8_t MPU_Read_Byte(uint8_t reg); //IIC读一个字节
  77. uint8_t MPU_Write_Bit(uint8_t addr, uint8_t bitNum, uint8_t Data); //写入8位寄存器的一个位
  78. uint8_t MPU_Write_Bits(uint8_t addr, uint8_t bitStart, uint8_t length, uint8_t Data);//写入8位寄存器的多个位
  79. uint8_t MPU_Read_Bit(uint8_t addr, uint8_t bitNum, uint8_t *Data); //读取一个位从8位器件的寄存器
  80. uint8_t MPU_Read_Bits(uint8_t addr, uint8_t bitStart, uint8_t length, uint8_t *Data);//读取8位寄存器的多个位
  81. uint8_t MPU_Set_Gyro_Fsr(uint8_t fsr);
  82. uint8_t MPU_Set_Accel_Fsr(uint8_t fsr);
  83. uint8_t MPU_Set_LPF(uint16_t lpf);
  84. uint8_t MPU_Set_Rate(uint16_t rate);
  85. int16_t MPU_Get_Temperature(void);
  86. uint8_t MPU_Get_Gyroscope(int16_t *gx, int16_t *gy, int16_t *gz);
  87. uint8_t MPU_Get_Accelerometer(int16_t *ax, int16_t *ay, int16_t *az);
  88. #define MPU_Refresh() MPU_Write_Byte(MPU_PWR_MGMT1_REG, 0X00) //唤醒MPU6050
  89. void MPU_Delay_Ms(uint16_t Milliseconds); //
  90. #endif

iic.c

  1. #include "Soft_I2C.h"
  2. #define I2C_TIMEOUT_TIMES 100 //超时倍数
  3. //延时 用于等待应答时的超时判断
  4. void i2c_timeout_delay(void)
  5. {
  6. }
  7. void i2c_delay() //每步的间隔 用于等待电平稳定和控制通讯速率
  8. {
  9. }
  10. //SCL拉高
  11. void I2C_SCL_H(void)
  12. {
  13. I2C_SCL = 1;
  14. }
  15. //SCL拉低
  16. void I2C_SCL_L(void)
  17. {
  18. I2C_SCL = 0;
  19. }
  20. //SDA拉高
  21. void I2C_SDA_H(void)
  22. {
  23. I2C_SDA = 1;
  24. }
  25. //SDA拉低
  26. void I2C_SDA_L(void)
  27. {
  28. I2C_SDA = 0;
  29. }
  30. //读取SDA
  31. uint8_t I2C_SDA_Read(void)
  32. {
  33. return I2C_SDA;
  34. }
  35. /*******************************************************************************
  36. * 函 数 名 : i2c_start
  37. * 函数功能 : 产生I2C起始信号
  38. * 输 入 : 无
  39. * 输 出 : 无
  40. *******************************************************************************/
  41. void i2c_start(void)
  42. {
  43. I2C_SDA_H();
  44. I2C_SCL_H();
  45. i2c_delay();
  46. I2C_SDA_L(); //当SCL为高电平时,SDA由高变为低
  47. i2c_delay();
  48. I2C_SCL_L(); //钳住I2C总线,准备发送或接收数据
  49. }
  50. /*******************************************************************************
  51. * 函 数 名 : i2c_stop
  52. * 函数功能 : 产生I2C停止信号
  53. * 输 入 : 无
  54. * 输 出 : 无
  55. *******************************************************************************/
  56. void i2c_stop(void)
  57. {
  58. I2C_SDA_L();
  59. I2C_SCL_H();
  60. i2c_delay();
  61. I2C_SDA_H(); //当SCL为高电平时,SDA由低变为高
  62. i2c_delay();
  63. }
  64. /*******************************************************************************
  65. * 函 数 名 : i2c_ack
  66. * 函数功能 : 产生ACK应答
  67. * 输 入 : 无
  68. * 输 出 : 无
  69. *******************************************************************************/
  70. void i2c_ack(void)
  71. {
  72. I2C_SCL_L();
  73. I2C_SDA_L(); //SDA为低电平
  74. i2c_delay();
  75. I2C_SCL_H();
  76. i2c_delay();
  77. I2C_SCL_L();
  78. I2C_SDA_H();
  79. }
  80. /*******************************************************************************
  81. * 函 数 名 : i2c_nack
  82. * 函数功能 : 产生NACK非应答
  83. * 输 入 : 无
  84. * 输 出 : 无
  85. *******************************************************************************/
  86. void i2c_nack(void)
  87. {
  88. I2C_SCL_L();
  89. I2C_SDA_H(); //SDA为高电平
  90. i2c_delay();
  91. I2C_SCL_H();
  92. i2c_delay();
  93. I2C_SCL_L();
  94. }
  95. /*******************************************************************************
  96. * 函 数 名 : i2c_wait_ack
  97. * 函数功能 : 等待应答信号到来
  98. * 输 入 : 无
  99. * 输 出 : 1,接收应答失败
  100. 0,接收应答成功
  101. *******************************************************************************/
  102. uint8_t i2c_wait_ack(void)
  103. {
  104. uint16_t time_temp = 0;
  105. I2C_SCL_H();
  106. i2c_delay();
  107. while(I2C_SDA_Read()) //等待SDA为低电平
  108. {
  109. time_temp++;
  110. i2c_timeout_delay();
  111. if(time_temp > I2C_TIMEOUT_TIMES) //超时则强制结束I2C通信
  112. {
  113. i2c_stop();
  114. return 1;
  115. }
  116. }
  117. I2C_SCL_L();
  118. return 0;
  119. }
  120. /*******************************************************************************
  121. * 函 数 名 : i2c_write_byte
  122. * 函数功能 : I2C发送一个字节
  123. * 输 入 : dat:发送一个字节
  124. * 输 出 : 无
  125. *******************************************************************************/
  126. void i2c_write_byte(uint8_t dat)
  127. {
  128. uint8_t i = 0;
  129. I2C_SCL_L();
  130. for(i = 0; i<8; i++) //循环8次将一个字节传出,先传高再传低位
  131. {
  132. if((dat & 0x80) > 0)
  133. I2C_SDA_H();
  134. else
  135. I2C_SDA_L();
  136. dat <<= 1;
  137. i2c_delay();
  138. I2C_SCL_H();
  139. i2c_delay();
  140. I2C_SCL_L();
  141. i2c_delay();
  142. }
  143. }
  144. /*******************************************************************************
  145. * 函 数 名 : i2c_read_byte
  146. * 函数功能 : I2C读一个字节
  147. * 输 入 : ack = 1时,发送ACK,ack = 0,发送nACK
  148. * 输 出 : 应答或非应答
  149. *******************************************************************************/
  150. uint8_t i2c_read_byte(uint8_t ack)
  151. {
  152. uint8_t i = 0, receive = 0;
  153. for(i = 0; i < 8; i++ ) //循环8次将一个字节读出,先读高再传低位
  154. {
  155. I2C_SCL_L();
  156. i2c_delay();
  157. I2C_SCL_H();
  158. receive <<= 1;
  159. if(I2C_SDA_Read())
  160. receive++;
  161. i2c_delay();
  162. }
  163. if (!ack)
  164. i2c_nack();
  165. else
  166. i2c_ack();
  167. return receive;
  168. }
  169. /*******************************************************************************
  170. * 函 数 名 : i2c_mem_write
  171. * 函数功能 : I2C对指定器件、指定寄存器连续写入
  172. * 输 入 : 器件地址、器件寄存器地址、待输入数据首地址、待输入数据长度
  173. * 输 出 : 0: 成功 1:失败
  174. *******************************************************************************/
  175. uint8_t i2c_mem_write(uint8_t DevAddress, uint8_t MemAddress, uint8_t *pData, uint16_t Len)
  176. {
  177. i2c_start();
  178. i2c_write_byte(DevAddress << 1);
  179. if(i2c_wait_ack())
  180. return 1;
  181. i2c_write_byte(MemAddress);
  182. if(i2c_wait_ack())
  183. return 1;
  184. while(Len--)
  185. {
  186. i2c_write_byte(*pData++);
  187. if(i2c_wait_ack())
  188. return 1;
  189. }
  190. i2c_stop();
  191. return 0;
  192. }
  193. /*******************************************************************************
  194. * 函 数 名 : i2c_mem_read
  195. * 函数功能 : I2C对指定器件、指定寄存器连续读取
  196. * 输 入 : 器件地址、器件寄存器地址、数据缓冲区首地址、数据长度
  197. * 输 出 : 0: 成功 1:失败
  198. *******************************************************************************/
  199. uint8_t i2c_mem_read(uint8_t DevAddress, uint8_t MemAddress, uint8_t *pBuffer, uint16_t Len)
  200. {
  201. i2c_start();
  202. i2c_write_byte(DevAddress << 1); //发送写命令
  203. if(i2c_wait_ack())
  204. return 1;
  205. i2c_write_byte(MemAddress); //发送字地址
  206. if(i2c_wait_ack())
  207. return 1;
  208. i2c_start();
  209. i2c_write_byte(DevAddress << 1 | 1); //进入接收模式
  210. if(i2c_wait_ack())
  211. return 1;
  212. while(Len--)
  213. {
  214. *pBuffer++ = i2c_read_byte(Len!=0); //读取字节
  215. }
  216. i2c_stop(); //产生一个停止条件
  217. return 0;
  218. }
  219. /**写入8位寄存器的一个位。
  220. * @参数 DevAddress I2C从器件地址
  221. * @参数 addr I2C从器件内部地址
  222. * @参数 bitNum 写入的比特位(0-7)
  223. * @参数 data 写入数据
  224. * @返回值 返回状态 (0=成功)
  225. */
  226. uint8_t i2c_write_bit(uint8_t DevAddress, uint8_t addr, uint8_t bitNum, uint8_t Data)
  227. {
  228. uint8_t b;
  229. if (!i2c_mem_read(DevAddress, addr, &b, 1))
  230. {
  231. b = (Data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum));
  232. return i2c_mem_write(DevAddress, addr, &b, 1); //写入数据
  233. }
  234. else
  235. return 1;
  236. }
  237. /**写入8位寄存器的多个位。
  238. * @参数 DevAddress I2C从器件地址
  239. * @参数 addr I2C从器件内部地址
  240. * @参数 bitStart 第一位的写入位置(0-7)
  241. * @参数 length 写的比特数(不超过8)
  242. * @参数 Data 写入数据
  243. * @返回值 返回状态 (0=成功)
  244. */
  245. uint8_t i2c_write_bits(uint8_t DevAddress, uint8_t addr, uint8_t bitStart, uint8_t length, uint8_t Data)
  246. {
  247. // 010 要写入的值
  248. // 76543210 比特位
  249. // xxx args: bitStart=4, length=3
  250. // 00011100 掩码字节
  251. // 10101111 原始值(样本)
  252. // 10100011 原始值 & ~掩码
  253. // 10101011 掩码 | 原始值
  254. uint8_t b, mask = 0;
  255. if (!i2c_mem_read(DevAddress, addr, &b, 1))
  256. {
  257. mask = (((1 << length) - 1) << (bitStart - length + 1)); //掩码
  258. Data <<= (bitStart - length + 1); //把写入的数据移动到位
  259. Data &= mask;
  260. b &= ~(mask);
  261. b |= Data;
  262. return i2c_mem_write(DevAddress, addr, &b, 1); //写入数据
  263. }
  264. else
  265. return 1;
  266. }
  267. /**读取一个位从8位器件的寄存器。
  268. * @参数 DevAddress I2C从器件地址
  269. * @参数 addr I2C从器件内部地址
  270. * @参数 bitNum 位的位置来读取(0-7)
  271. * @参数 *data 数据存储地址
  272. * @返回值(0=成功)
  273. */
  274. uint8_t i2c_read_bit(uint8_t DevAddress, uint8_t addr, uint8_t bitNum, uint8_t *Data)
  275. {
  276. uint8_t b;
  277. if (!i2c_mem_read(DevAddress, addr, &b, 1))
  278. {
  279. *Data = b & (1 << bitNum);
  280. return 0;
  281. }
  282. else
  283. {
  284. return 1;
  285. }
  286. }
  287. /**读取8位寄存器的多个位。
  288. * @参数 DevAddress I2C从器件地址
  289. * @参数 addr I2C从器件内部地址
  290. * @参数 bitStart第一位的位置读取(0-7)
  291. * @参数 length 位读取@参数长度数(不超过8)
  292. * @参数 *data 数据存储地址(即'101'任何bitStart位置读取将等于0X05)
  293. * @返回值(0=成功)
  294. */
  295. uint8_t i2c_read_bits(uint8_t DevAddress, uint8_t addr, uint8_t bitStart, uint8_t length, uint8_t *Data)
  296. {
  297. // 01101001 读取字节
  298. // 76543210 比特位
  299. // xxx args: bitStart=4, length=3
  300. // 010 masked
  301. // -> 010 shifted
  302. uint8_t b, mask = 0;
  303. if (!i2c_mem_read(DevAddress, addr, &b, 1))
  304. {
  305. mask = ((1 << length) - 1) << (bitStart - length + 1);
  306. b &= mask;
  307. b >>= (bitStart - length + 1);
  308. *Data = b;
  309. return 0;
  310. }
  311. else
  312. return 1;
  313. }

i2c.h

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

总结

        mpu6050资料众多,使用方便,适用于多种应用场景,传统的51单片机受限于i2c读取速率,实时性不一定符合应用需求,建议用32位单片机。

好耶,又水了一篇

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/568327
推荐阅读
相关标签
  

闽ICP备14008679号