标题: Mpu6050的I2C控制技术详解以及单片机例程 [打印本页]

作者: RainityZhou    时间: 2018-3-24 16:24
标题: Mpu6050的I2C控制技术详解以及单片机例程
C总线协议与MPU6050
在keil c里bit是一位的,属于对标准c扩展的数据类型。我举个例子说明bit的强制转换规则,例如有变量unsigned char num,变量bit tmp,那么tmp =(bit) num就是把unsigned char型变量强制转换为bit型,不过规则有点和一般的强制转换不一样,bit进行强制转换时,只要num不等于0(或者0x00),那么tmp =(bit) num的结果就是1,自然地如果num=0,那么tmp=0。
         机器周期=晶振周期*12;
  1. #include <reg52.h>
  2. #include <intrins.h>      //包含机器周期延时函数_nop_()
  3. #define OP_READ 0xa1    //器件地址以及读取操作 1010 0001B
  4. #define OP_WRITE 0xa0   //器件地址以及写入操作 1010 0000B
  5. /*说明:器件地址为前7位,最低一位为选择读或写*/
  6. sbit SDA=P3^5;
  7. sbit SCL=P3^4;
  8. /* 延时1ms*/
  9. void delay1ms()
  10. {
  11. unsigned char I,j;
  12. for(i=0;i<10;i++)
  13. for(j=0;j<33;j++)
  14. ;
  15. }
  16. /*延时若干毫秒*/
  17. void delayms(unsigned char n)
  18. {
  19. Unsigned char j;
  20. For(i=0;i<n;i++)
  21. Delay1ms();
  22. }
  23. /*开始数据传送的前期准备*/
  24. Void start()
  25. {
  26. SDA=1;      //SDA初始化为高电平
  27. SCL=1;      //SCL初始化为高电平
  28. _nop_();
  29. _nop_();
  30. _nop_();
  31. _nop_();
  32. SDA=0;    //在SCL为高电平时,SDA由1置0被认为是开始信号
  33. _nop_();
  34. _nop_();
  35. _nop_();
  36. _nop_();
  37. SCL=0;   //SCL变为低电平,开始传送数据
  38. }
  39. /*结束数据传送*/
  40. Void stop()
  41. {
  42. SDA=0;   //SDA初始化为低电平,准备发出终止信号
  43. SCL=1;   //SCL变成高电平,此时SDA的一切变化都将被认为是开始或终止信号
  44. _nop_();
  45. _nop_();
  46. _nop_();
  47. _nop_();
  48. SDA=1;    //在SCL为高电平时,SDA由0置1被认为是终止信号
  49. _nop_();
  50. _nop_();
  51. _nop_();
  52. _nop_();
  53. SCL=0;   
  54. SDA=0;    //解除总线的占用
  55. }

  56. /*从子器件读取数据*/
  57. Unsigned char ReadData()
  58. {
  59. Unsigned char i,x;  //规定两个中间变量用于暂时存储数据
  60. For(i=0;i<8;i++)    //循环8次,刚好记录一个字节
  61. {
  62.               SCL=1;    //先不允许SDA变化,便于记录数据
  63.               X <<=1;     //将x各二进制位向左移一位
  64. X |=(unsigned char)SDA;   //将SDA的数据存到X里
  65. /***说明: X有定义之后默认为0x00,SDA为从最高位向最低位变化,所以左移可以将数据按从高到低存储在x里;
  66. SDA为一个二进制位,转换成unsigned char 之后变成字节的最低位,所以按位与运算之后可将SDA当前数据存储在X的当前最低位*******/
  67. SCL=0;   //允许SDA变换到下一位
  68. }
  69. Return (x);  //将最终记录好的X值返回给外函数变量
  70. }


  71. /* 向从机写入数据*/
  72. //调用该函数之前要先调用start(),所以SCL=0;
  73. Bit WriteCurrent(unsigned char y)
  74. {
  75. Unsigned char i;
  76. Bit ack_bit;          //储存应答位
  77. For(i=0;i<8;i++)
  78. {
  79.               SDA=(bit)(y&0x80);
  80. /**先与0x80按位与运算以得到最高位信息(发送时仍先发送最高位),再按照bit 的强制类型转换规则,如果得到1000 0000,则最高位为1,此时SDA为1;如果得到0000 0000,则最高位为0,SDA=0**/
  81.               _nop_();
  82. SCL=1;    //不允许SDA变化,方便从机记录数据
  83.               _nop_();
  84. _nop_();
  85.               SCL=0;  //从机记录完成该位,可变换为下一位
  86.               Y<<=1;   //让次高位位变成最高位以进行下一次数据传输
  87. }
  88. /*开始检测应答位*/
  89. SDA=1;    //初始化SDA,并让其自由变换
  90. _nop_();
  91. _nop_();
  92. SCL=1;   //SCL置1,开始检测是否应答(SDA的值在这之前已经变化完成)
  93. _nop_();
  94. _nop_();
  95. _nop_();
  96. _nop_();
  97. Ack_bit=SDA;  //记录应答位的值
  98. SCL=0;     
  99. return ack_bit;   //返回应答位的值,让外部得知是否应答
  100. }

  101. /* 向指定从机写入地址和数据,add存储指定地址,dat存储待写入的数据*/
  102. Void WriteSet(unsigned char add,unsigned char dat)
  103. {
  104. Start();  //初始化总线
  105. WriteCurrent(OP_WRITE);  //选择从机并告知要对它写入数据
  106. WriteCurrent(add);    //写入指定地址
  107. WriteCurrent(dat);    //写入数据
  108. Stop();    //停止数据传输
  109. Delayms(4);    //一个字节的写入周期为1ms,所以最好延时1ms以上
  110. }
  111. /**从从机的当前地址读取数据**/
  112. Unsigned char ReadCurrent()
  113. {
  114. Unsigned char x;
  115. Start();    //初始化总线
  116. WriteCurrent(OP_READ);   //选择从机并告知要读取数据
  117. X=ReadData();    //将读取的数据存入x
  118. Stop();         //终止数据传输
  119. Return x;    //返回读取数据
  120. }
  121. /**从从机中的某个地址读取数据,set_addr为地址**/
  122. Unsigned char ReadSet(unsigned char set_addr)
  123. {
  124. Start();    //初始化总线
  125. WriteCurrent(OP_WRITE);    //选择从机并告知要写入数据
  126. WriteCurrent(set_addr);    //写入指定地址
  127. return(ReadCurrent());    //从指定地址读取数据并返回
  128. }
  129. /*主函数*/
  130. Main(void)
  131. {
  132. SDA=1;    //使主从设备处于空闲状态
  133. SCL=1;
  134. WriteSet(add,dat);    //例如:在指定地址“0x36”中写入数据“0x0f”
  135. 完成其他功能
  136. }
复制代码

从机整个有一个地址OP,从机内部有多个寄存器,所以地址要写两个,即先写整个的,再写寄存器的。
MPU6050的R/W位是最低位,如图
SPI Address format
MSB
LSB
A6
A5
A4
A3
A2
A1
A0
R/W
SPI Data format
MSB
LSB
D7
D6
D5
D4
D3
D2
D1
D0
MPU-60X0的Slave地址为b110100X,7位字长,最低有效位X由AD0管脚上的逻辑电平决定。这样就可以允许两个MPU-60X0连接到同一条I2C总线,此时,一个设备的地址为b1101000(AD0为逻辑低电平),另一个为b1101001(
AD0为逻辑高)。
MPU6050的默认SLAVE地址的高七位是1101000(),最低位默认为0,有需要时置1;
WHO_AM_I寄存器的低七位的高6位存放的是110100,最低位存放的是AD0引脚电平,它的最高位(第八位)没有任何作用,不用管。
WHO_AM_I 的寄存器地址为0x75,默认值就是0x68
陀螺仪角速度量程:单位为 度每秒(°/s),指的是如果陀螺仪每秒转动不超过多少度则陀螺仪可以测量。比如±125,就是在每秒转动125°之内的能测出来。陀螺仪量程越大,精度越低。
陀螺仪加速度量程:单位为计数单位为g(重力加速度).
陀螺仪角速度灵敏度:单位为 LSB/(°/s),LSB是数字输出方式下的最小有效位,在这里就是一个二进制位。
    所以灵敏度=65536/量程的区间长度(比如量程为100°/s,则除以200);
陀螺仪的加速度灵敏度:可以用LSB/g来表示,则灵敏度可以表示为:
65536/加速度量程区间长度(比如量程是g,则除以4)
加速度:1g代表一个重力加速度,即以9.8m/s为单位大小。
在数字输出方式下,陀螺仪灵敏度可用mg/LSB来表示。
陀螺仪输出的ADC角速度值与°/s(角速度)之间的换算:输出的ADC值的单位是LSB,则
某一个轴的角速度=ADC值/角速度灵敏度;
陀螺仪输出的ADCRx加速度值与g之间的换算:
某一个轴的加速度=ADCRx值/加速度灵敏度;
MPU6050的重要寄存器:
WHO_AM_I寄存器的低七位的高6位存放的是110100,最低位存放的是AD0引脚电平,它的最高位(第八位)没有任何作用,不用管。
用于配置电源模式和时钟源。提供了一位用来重置整个仪器,以及一位用来禁用温度传感器。

Register(Hex)

Register(Decimal)

Bit7
Bit6
Bit5
Bit4
Bit3
Bit2
Bit1
Bit0
6B
107
DEVICE
_RESET
SLEEP
CYCLE
-
TEMP_DIS
CLKSEL[2:0]
7:置1时所有寄存器复位,然后自动置0.
6:置1时进入低电压休眠状态;当SLEEP1时,若CYCLE1,则进入循环模式。在循环模式下,仪器将在睡眠和活动状态下来回转换来从活动状态的传感器获取一个数据样本,其频率由LP_WAKE_CTRL决定。为了配置唤醒频率,需要配合使用LP_WAKE_CTRL和两个电源管理寄存器。
31禁用温度传感器。
210:选择时钟源。                                   
CLKSEL
Clock Source
000
内部8MHZ振荡器,平时用这个即可
001
具有X轴陀螺基准的锁相环
010
具有Y轴陀螺基准的锁相环
011
具有Z轴陀螺基准的锁相环
100
PLL with external 32.768kHz reference
101
PLL with external 19.2MHz reference
110
储存保留
111
停止时钟并让计时发生器保持重置状态
Register(Hex)
Bit7
Bit6
Bit5
Bit4
Bit3
Bit2
Bit1
Bit0
19
SMPLRT_DIV[7:0]
用于指定陀螺仪的采样率。
采样速率=陀螺仪输出速率/(1+SMPLRT_DIV)
其中,当DLPF_CFG=000或111时(详情见CONFIG寄存器),陀螺仪输出速率=8KHZ;当数字低通滤波器(DLPF)被禁用时,陀螺仪输出频率是1KHZ(平时禁用就行了);
注意:加速度计的输出频率是1KHZ。这意味着当采样速率高于1KHZ时,同样的加速度计采样江北输出到FIFO,DMP,和不止一个寄存器中。
3:CONFIG:地址0x1a,默认值0x00

Register(Hex)

Register(Decimal)

Bit7
Bit6
Bit5
Bit4
Bit3
Bit2
Bit1
Bit0
1A
26
-
-
EXT_SYNC_SET[2:0]
DLPF_CFG[2:0]
此寄存器用于配置外部帧同步引脚采样,以及 陀螺仪和加速度计的 数字低通滤波器的相关设置。
与FSYNC引脚链接的外部信号可以被EXT_SYNC_SET采样。
FSYNC引脚的信号变化会被锁存,这样就可以获得很短的频闪信号。被锁存的FSYNC引脚数据会被认为是采样率,就像SMPLRT_DIV里定义的那样。采样过后,锁存器会重置成当前的FSYNC信号状态。
采样值将被反馈到由EXT_SYNC_SET的值决定的传感器的数据寄存器的最低有效位。   
位5,4,3:EXT_SYNC_SET
EXT_SYNC_SET
FSYNC Bit Location
0
禁止输入,平时用这个
1
TEMP_OUT_L[0]   温度传感器的低八位寄存器的最低有效位
2
GYRO_XOUT_L[0]    陀螺仪X轴
3
GYRO_YOUT_L[0]     陀螺仪Y轴
4
GYRO_ZOUT_L[0]     陀螺仪Z轴
5
ACCEL_XOUT_L[0]    加速度计X轴
6
ACCEL_YOUT_L[0]    加速度计Y轴
7
ACCEL_ZOUT_L[0]    加速度计Z轴
位2,1,0:DLPF_CFG,用于设置陀螺仪和加速度计的数字低通滤波频率(DLPF)
,如下表:
DLPF_CFG

加速度计 (Fs  = 1kHz)

                       陀螺仪
Bandwidth(带宽)(Hz)
Delay (ms)
Bandwidth (Hz)
Delay (ms)
Fs (kHz)
000
260
0
256
0.98
8
001
184
2.0
188
1.9
1
010
94
3.0
98
2.8
1
011
44
4.9
42
4.8
1
100
21
8.5
20
8.3
1
101
10
13.8
10
13.4
1
110,平时用这个
5
19.0
5
18.6
1
111
RESERVED(保留)
RESERVED(保留)
8
  • Register(Hex)

Register(Decimal)

Bit7
Bit6
Bit5
Bit4
Bit3
Bit2
Bit1
Bit0
1B
27
XG_ST
YG_ST
ZG_ST
FS_SEL[1:0]
-
-
-
这个寄存器用于触发陀螺仪自检,以及配置陀螺仪量程。
陀螺仪自检的作用:允许用户检测陀螺仪的机械和电气部分。陀螺仪的每个轴的自检可以通过控制XG_ST,YG_ST和ZG_ST来激活。每个轴的自检可以同时独立运行。
当自检被激活时,在线的电气部分将会驱动合适的传感器。这种驱动将移动传感器的依据质量在相当于一个预先定义的科里奥利力的距离。这个依据质量的取代将会导致传感器输出的变化,而这又将导致输出信号被反射。输出信号被用来观察自检响应情况。平时不用自检。
自检响应的定义如下:
   自检响应=自检允许情况下的传感器输出值-自检不允许情况下的传感器输出值
当自检响应值被限制在最小或者最大产品规格时,该部分已通过自检。当自检响应超过产品规格文档中指定的最小/最大值时,该部分被视为自检失败。
位4,3(FS_SEL):是用来选择陀螺仪的量程的,具体见下表:
FS_SEL
Full Scale Range
00
± 250 °/s
01
± 500 °/s
10
± 1000 °/s
11
± 2000 °/s,平时用这个
            

Register(Hex)

Register(Decimal)

Bit7
Bit6
Bit5
Bit4
Bit3
Bit2
Bit1
Bit0
1C
28
XA_ST
YA_ST
ZA_ST
AFS_SEL[1:0]
ACCEL_HPF[2:0]
此寄存器用于启动加速度计自检以及配置加速度计的量程。也用于配置数字高通滤波器(DHPF)。
(说明同GYRO_CONFIG,平时不自检)
   位4,3(AFS_SEL):用于设置加速度计量程,具体如下表:
AFS_SEL
Full Scale Range
00
± 2g平时用这个
01
± 4g
10
± 8g
11
± 16g
位2,1,0(ACCEL_HPF):用于配置数字高通滤波器(DHPF)的路径可用并导致运动探测器(自由落体,运动阈值和零运动)。高通滤波器的输出对于数据寄存器来说并不可用(详情见产品规格说明书第八部分)。
高通滤波器有三种模式:
1.Reset: 滤波器输出在一个采样中归零。这可以有效的禁用高通滤波器。此模式可以切换快速解决滤波器。
2.On:     数字高通滤波器会让频率高过截止频率的信号通过。
3.Hold:  切换到此模式时,滤波器将保持现有采样。滤波器输出将会是输入采样和保持采样之间的区别。
      具体如下表:
ACCEL_HPF
Filter Mode
Cut-off Frequency(高通滤波频率)
000
Reset
None
001
On
5Hz,平时用这个
010
On
2.5Hz
011
On
1.25Hz
100
On
0.63Hz
111
Hold
None
                     
   ACCEL_XOUT_H:地址0x3b:加速度计X轴高八位
   ACCEL_XOUT_L:     0x3c: 加速度计X轴低八位
   ACCEL_YOUT_H:     0x3d: 加速度计Y轴高八位
   ACCEL_YOUT_L:     0x3e: 加速度计Y轴低八位                   初始值0x00
   ACCEL_ZOUT_H:     0x3f: 加速度计Z轴高八位
   ACCEL_ZOUT_L:     0x40: 加速度计Z轴低八位
用于存储加速度计的最近测量值,所记录的数据是以LSB为单位的加速度值。
加速度传感器内部寄存器组中的数据总是以采样速率更新,同时,当串行接口空闲时,面向用户的读寄存器组重复内部寄存器组的数据值,这保证了传感器寄存器的突发读取将读取来自同一采样时刻的测量。
每一个加速度计测量器偶有一个在ACCEL_FS寄存器里定义的满刻度。对于每一个满刻度设置,每LSB的加速度计灵敏度如下表:
AFS_SEL
量程
LSB 灵敏度
00
±2g
16384 LSB/mg
01
±4g
8192 LSB/mg
10
±8g
4096 LSB/mg
11
±16g
2048 LSB/mg
TEMP_OUT_H:地址0x41:温度传感器测量值寄存器高八位              初始值0x00
TEMP_OUT_L:地址0x42:温度传感器测量值寄存器低八位
GYRO_XOUT_H:地址0x43
GYRO_XOUT_L:     0x44
GYRO_YOUT_H:     0x45                    用于记录陀螺仪各轴测量值,默认值0x00
GYRO_YOUT_L:     0x46
GYRO_ZOUT_H:     0x47
GYRO_ZOUT_L:     0x48
同加速度计测量值寄存器,量程与LSB表示的灵敏度关系如下表:
FS_SEL
Full Scale Range
LSB Sensitivity
0
± 250 °/s
131 LSB/°/s
1
± 500 °/s
65.5 LSB/°/s
2
± 1000 °/s
32.8 LSB/°/s
3
± 2000 °/s
16.4 LSB/°/s
这几个寄存器的数据的含义是以LSB为单位的角速度值。

完整的Word格式文档51黑下载地址:
I2C总线协议与MPU6050.docx (121.53 KB, 下载次数: 65)




作者: 4049218    时间: 2018-3-24 22:41
没看懂
作者: jasexie    时间: 2019-9-6 09:46
下载下来看一下




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1