10xjzheng 发表于 2014-5-11 11:48:41

MPU6050作为从机地址设置的疑问

我知道I2C通讯的时候最低位地址是决定读写的,但是我看到有两组地址,一组是0x68和0x69,一组是0xd0和0xd1。我看见别人51的设置的是0xD0,但是看到数据手册又是0x68。


疑问1:究竟这两个地址那个是I2C从机地址?
疑问2:另一个地址究竟是什么?做什么用的?
新手上路,请大神多多指教。

10xjzheng 发表于 2014-5-11 12:33:07

我知道了,Who_I_AM是只有7位的,是slave adress的高7位,哈哈,没有注意照顾细节

jiang887786 发表于 2014-5-14 18:00:06

10xjzheng 发表于 2014-5-11 12:33
我知道了,Who_I_AM是只有7位的,是slave adress的高7位,哈哈,没有注意照顾细节
...

在下愚钝,0位和7位已经保留了而且默认为0.为啥他就是D0呢??想不通!一会我D0在写一下试试,我写68连ack都不返回,读全部是ff,晕的蛋疼!

jiang887786 发表于 2014-5-14 18:42:37

固然,有反应了,我靠!虽然不知道为啥,呵呵!但是现在数据还不稳定!继续研究吧!

jiang887786 发表于 2014-5-14 18:44:51

本帖最后由 jiang887786 于 2014-5-14 18:45 编辑

我想我的时序还是有问题,看看问题在哪吧!

10xjzheng 发表于 2014-5-14 19:39:15

jiang887786 发表于 2014-5-14 18:44
我想我的时序还是有问题,看看问题在哪吧!

我觉得懂I2C的原理就可以了,模拟时序我觉得可以不要亲自去做,或者做一两个就好,直接网上找程序,如果你想要程序的话,可以留言。QQ:934345073

jiang887786 发表于 2014-5-15 10:01:38

10xjzheng 发表于 2014-5-14 19:39
我觉得懂I2C的原理就可以了,模拟时序我觉得可以不要亲自去做,或者做一两个就好,直接网上找程序,如果 ...

谢谢,我是飞思卡尔的单片机,你的代码我可能不好用,我发现是红色部分的问题,我修改了读字节的部分,写字节的根本没动!现在连ACK都没有返回了。不知道问题在哪了!我擦!/** ###################################################################
**   Filename: XD256_MPU6050_TEST.c
**   Project   : XD256_MPU6050_TEST
**   Processor : MC9S12XD256BCPV
**   Version   : Driver 01.14
**   Compiler: CodeWarrior HCS12X C Compiler
**   Date/Time : 2014-5-12, 17:25
**   Abstract:
**         Main module.
**         This module contains user's application code.
**   Settings:
**   Contents:
**         No public methods
**
** ###################################################################*/
/* MODULE XD256_MPU6050_TEST */

/* Including needed modules to compile this module/procedure */
#include "Cpu.h"
#include "Events.h"
/* Include shared modules, which are used for whole project */
#include "PE_Types.h"
#include "PE_Error.h"
#include "PE_Const.h"
#include "IO_Map.h"
#include "MPU6050.h"

/* User includes (#include below this line is not maintained by Processor Expert) */

#define SCL PTJ_PTJ7
#define SDA PTJ_PTJ6
#define SCL_dir DDRJ_DDRJ7
#define SDA_dir DDRJ_DDRJ6

#define somenop(); asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");\
                   asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");\
                   asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");\
                   asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");

/****************************************/
// 定义MPU6050内部地址
//****************************************/
#define        SMPLRT_DIV                0x19        //陀螺仪采样率,典型值:0x07(125Hz)
#define        CONFIG                          0x1A        //低通滤波频率,典型值:0x06(5Hz)
#define        GYRO_CONFIG                0x1B        //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
#define        ACCEL_CONFIG        0x1C        //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)
#define        ACCEL_XOUT_H        0x3B
#define        ACCEL_XOUT_L        0x3C
#define        ACCEL_YOUT_H        0x3D
#define        ACCEL_YOUT_L        0x3E
#define        ACCEL_ZOUT_H        0x3F
#define        ACCEL_ZOUT_L        0x40
#define        TEMP_OUT_H                0x41
#define        TEMP_OUT_L                0x42
#define        GYRO_XOUT_H                0x43
#define        GYRO_XOUT_L                0x44       
#define        GYRO_YOUT_H                0x45
#define        GYRO_YOUT_L                0x46
#define        GYRO_ZOUT_H                0x47
#define        GYRO_ZOUT_L                0x48
#define        PWR_MGMT_1                0x6B        //电源管理,典型值:0x00(正常启用)
#define        WHO_AM_I                        0x75        //IIC地址寄存器(默认数值0x68,只读)
#define        SlaveAddress        0xd0        //IIC写入时的地址字节数据,+1为读取

int        Temperature,Temp_h,Temp_l;        //温度及高低位数据
unsigned int ACCEL_XOUT,ACCEL_YOUT,ACCEL_ZOUT,GYRO_XOUT,GYRO_YOUT,GYRO_ZOUT;
//****************************************
//函数声明
//****************************************
//MPU6050操作函数
voidInitMPU6050();                                                                                                        //初始化MPU6050



/*************************************************************/
/*                        初始化IIC                        */
/*************************************************************/
void INIT_IIC(void)
{

SCL_dir = 1;
SCL_dir = 1;
SCL = 1;
SDA = 1;
}

/*************************************************************/
/*                         启动IIC                           */
/*************************************************************/
void I2Cstart(void)
{
SCL_dir = 1;
SDA_dir = 1;
SDA = 1;
somenop();
SCL = 1;
somenop();
somenop();
SDA = 0;
somenop();
somenop();
SCL = 0;
}

/*************************************************************/
/*                     IIC发送数据                         */
/*************************************************************/
void I2Csend(byte data)
{
unsigned char i=8;
SCL_dir = 1;
SDA_dir = 1;
while(i)
{
      SCL = 0;
      somenop();
      SDA=(data&0x80)>>7;
      data<<=1;
      somenop();
      SCL = 1;
      somenop();
      somenop();
      i--;   
}
SCL = 0;
SDA_dir = 0;
}

/*************************************************************/
/*                     IIC接收数据                         */
/*************************************************************/
unsigned char I2Creceive(void)
{
unsigned char i=8;
unsigned char data=0;

SCL_dir = 1;
SDA_dir = 0;
while(i)
{
      SCL = 0;
      somenop();
      somenop();
      SCL = 1;
      somenop();
      data<<=1;
      data|=SDA;
      somenop();
      i--;   
}
SCL = 0;
return(data);
}

/*************************************************************/
/*                      IIC读取应答位                        */
/*************************************************************/
byte I2Creadack(void)
{
unsigned int i=0;
SCL_dir = 1;
SDA_dir = 0;
SCL = 0;
somenop();
somenop();
SCL = 1;
somenop();
if(SDA == 1)
{
for(;;) if(++i>=20000)
return 0xff;}
somenop();
SCL = 0;
somenop();
somenop();
return 0;
}

/*************************************************************/
/*                      IIC发送应答位                        */
/*************************************************************/
void I2Csendack(void)
{
SCL_dir = 1;
SDA_dir = 1;
SCL = 0;
somenop();
SDA = 0;
somenop();
SCL = 1;
somenop();
somenop();
SCL = 0;
somenop();
somenop();
}

/*************************************************************/
/*                         停止IIC                           */
/*************************************************************/
void I2Cstop(void)
{
SCL = 0;
SDA = 0;
SCL_dir = 1;
SDA_dir = 1;
SCL = 0;
SDA = 0;
somenop();
somenop();
SCL = 1;
somenop();
SDA = 1;
somenop();
somenop();
SCL_dir = 0;
SDA_dir = 0;
}
//**************************************
//向I2C设备写入一个字节数据
//**************************************
byte Single_WriteI2C(byte address,byte REG,byte value){
I2Cstart();//启动总线开始发送数据
I2Csend(address) ;//发送要接受数据的器件地址
    if (I2Creadack())
return 0xff;    //读取应答码
I2Csend(REG) ;//发送要写入寄存器的地址
    if (I2Creadack())
return 0xff;    //读取应答码
I2Csend(value) ; //发送要写入寄存器的参数值
    if (I2Creadack())
return 0xff;    //读取应答码
I2Cstop();
return 0;

}
//**************************************
//向I2C设备读取一个字节数据
//**************************************
byte Single_ReadI2C(byte address,byte REG){
byte value;
I2Cstart();//启动总线开始发送数据
I2Csend(address) ;//发送要接受数据的器件地址
    if (I2Creadack())
return 0xff;    //读取应答码
I2Csend(REG) ;//发送要写入寄存器的地址
    if (I2Creadack())
I2Cstart();//启动总线开始发送数据
I2Csend(address+1) ;//发送要接受数据的器件地址
    if (I2Creadack())   
return 0xff;    //读取应答码
value=I2Creceive() ; //发送要写入寄存器的参数值
I2Cstop();
return value;

}

//初始化MPU6050
//**************************************
void InitMPU6050()
{
        Single_WriteI2C(SlaveAddress,PWR_MGMT_1, 0x00);        //解除休眠状态
        Single_WriteI2C(SlaveAddress,SMPLRT_DIV, 0x07);
        Single_WriteI2C(SlaveAddress,CONFIG, 0x06);
        Single_WriteI2C(SlaveAddress,GYRO_CONFIG, 0x18);
        Single_WriteI2C(SlaveAddress,ACCEL_CONFIG, 0x01);
}


//**************************************
//合成数据
//**************************************
int GetData(unsigned char REG_Address)
{
volatile unsigned        int H,L;
        H=Single_ReadI2C(SlaveAddress,REG_Address);
        L=Single_ReadI2C(SlaveAddress,REG_Address+1);
        return H=(H<<8)|L;   //合成数据
}


void main(void)
{
/* Write your local variable definition here */

/*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
PE_low_level_init();
/*** End of Processor Expert internal initialization.                  ***/

/* Write your code here */
INIT_IIC();
   InitMPU6050();
   
   for(;;){
    ACCEL_XOUT=GetData(ACCEL_XOUT_H);        //显示X轴加速度
                ACCEL_YOUT=GetData(ACCEL_YOUT_H);        //显示Y轴加速度
                ACCEL_ZOUT=GetData(ACCEL_ZOUT_H);        //显示Z轴加速度
                GYRO_XOUT=GetData(GYRO_XOUT_H);        //显示X轴角速度
                GYRO_YOUT=GetData(GYRO_YOUT_H);        //显示Y轴角速度
                GYRO_ZOUT=GetData(GYRO_ZOUT_H);        //显示Z轴角速度
   
   }
/*** Processor Expert end of main routine. DON'T MODIFY THIS CODE!!! ***/
for(;;){}
/*** Processor Expert end of main routine. DON'T WRITE CODE BELOW!!! ***/
} /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/

/* END XD256_MPU6050_TEST */
/*
** ###################################################################
**
**   This file was created by Processor Expert 3.02
**   for the Freescale HCS12X series of microcontrollers.
**
** ###################################################################
*/

10xjzheng 发表于 2014-5-15 11:58:47

jiang887786 发表于 2014-5-15 10:01
谢谢,我是飞思卡尔的单片机,你的代码我可能不好用,我发现是红色部分的问题,我修改了读字节的部分,写 ...

不好意思啊,I2C没有什么调试经验,我就只是卡在地址那里,你自己找下。

jiang887786 发表于 2014-5-15 15:06:23

10xjzheng 发表于 2014-5-15 11:58
不好意思啊,I2C没有什么调试经验,我就只是卡在地址那里,你自己找下。 ...

请问你的是51的代码吗?方便的话发我邮箱一份吧,我想拿51先调一下试试吧,纠结的快不行了,2091881672@qq。com。谢谢!{:handshake:} STM32103我也有单片机,但是不知道什么编译器还不了解呢现在!

swh267 发表于 2014-5-15 16:58:27

疑惑了好几天的问题终于解决了,感谢楼主啊

liushenyoko 发表于 2014-6-9 09:43:43

一直存在的疑问终于解决了,谢谢楼主的分享!

10xjzheng 发表于 2014-6-9 10:00:36

liushenyoko 发表于 2014-6-9 09:43
一直存在的疑问终于解决了,谢谢楼主的分享!

不谢,我就知道终有一天会发生这样的场景,一起来为论坛做点贡献哈!!

10xjzheng 发表于 2014-6-9 10:10:24

jiang887786 发表于 2014-5-15 15:06
请问你的是51的代码吗?方便的话发我邮箱一份吧,我想拿51先调一下试试吧,纠结的快不行了,2091881672@q ...

你上面的那张图片是什么来着?程序再这里,51的I2C读取MPU6050数据,通过液晶输出取MPU6050数据,通过1602液晶输出:

jiang887786 发表于 2014-6-9 10:28:05

10xjzheng 发表于 2014-6-9 10:10
你上面的那张图片是什么来着?程序再这里,51的I2C读取MPU6050数据,通过液晶输出取MPU6050数据,通过160 ...

逻辑分析仪,公司买的,搞这些东西可以存储时序,看看一目了然,我们这行的必备利器!哈哈!谢谢,哥们{:lol:} {:handshake:}

10xjzheng 发表于 2014-6-9 14:45:09

jiang887786 发表于 2014-6-9 10:28
逻辑分析仪,公司买的,搞这些东西可以存储时序,看看一目了然,我们这行的必备利器!哈哈!谢谢,哥们{: ...

很厉害的样子!!估计很贵吧

jiang887786 发表于 2014-6-9 14:48:00

不贵啊,莫大这边就有300多元吧,上次我调试DS1302就是用它看出时序有些不对,提前几个空操作,结果就有数据出来了,利器!把数据上升沿提前一点点...

liuyang8023 发表于 2014-6-21 20:27:34


{:smile:}

CandD 发表于 2014-6-25 14:51:56

大神,请问一下,我的6050读出来的数据不变怎么回事啊?

ningsnail 发表于 2014-8-19 21:01:14

自己弄的程序 IIC总线通了,因为仿真看,给寄存器写数据,在读数据能正常读出,但是算其他参数的时候,MPU6050不动的情况下,数据在变,如图Gyro_y的值程序打断点运行时看数据,有时候会出现其他数据!

111111000 发表于 2014-8-28 00:26:12

不错 .......

who与争锋 发表于 2014-9-24 11:04:09

这里表述的不太好。应该说:当AD0 为逻辑低电平,从机地址为b1101000(0x68);当AD0 为逻辑ym 电平,从机地址为b1101001(0x69)。
AD0与WHO_AM_I的bit1有关,而与bit0无关。8位从机地址的最高位都为0。

可以近似认为bit0决定的是读或写操作(即认为读写的地址不一样。因为根据手册的协议,地址只有7位,而最后一位决定的是读或者写。).

who与争锋 发表于 2014-9-24 14:16:39

请问楼主 ,这个宏定义有什么使用吗?         #define        WHO_AM_I                0x75

10xjzheng 发表于 2014-9-24 18:26:44

who与争锋 发表于 2014-9-24 14:16
请问楼主 ,这个宏定义有什么使用吗?         #define        WHO_AM_I                0x75

可能是验证你读取寄存器对不对吧,我不大清楚

who与争锋 发表于 2014-9-25 09:37:10

10xjzheng 发表于 2014-9-24 18:26
可能是验证你读取寄存器对不对吧,我不大清楚

1,程序里好像都没用到
2,上面也说默认是0x68.
所以有点奇怪了。。。

10xjzheng 发表于 2014-9-25 09:58:29

who与争锋 发表于 2014-9-25 09:37
1,程序里好像都没用到
2,上面也说默认是0x68.
所以有点奇怪了。。。

今天才知道,那个是7位+1位构成I2C地址

who与争锋 发表于 2014-9-25 10:30:45

本帖最后由 who与争锋 于 2014-9-25 10:40 编辑

10xjzheng 发表于 2014-9-25 09:58
今天才知道,那个是7位+1位构成I2C地址

I2C地址是(根据手册的定义):bit7~bit1(这里是7位 bit1的取值根据AD0来确定)。bit0位不用。

根据手册,这里IIC地址只有7位的。当有用到IIC地址时,这7位放在前面 ,最后再补一位(读为1,写为0)。 于是,构成8位,即:地址+读 或者 地址+写。

#define      WHO_AM_I                0x75
也许寄存器的地址是0x75吧,和IIC地址没关系?

10xjzheng 发表于 2014-9-25 13:11:55

who与争锋 发表于 2014-9-25 10:30
I2C地址是(根据手册的定义):bit7~bit1(这里是7位 bit1的取值根据AD0来确定)。bit0位不用。

根据手册 ...

我觉得是官方的数据手册搞错了

who与争锋 发表于 2014-9-26 10:28:29

10xjzheng 发表于 2014-9-25 13:11
我觉得是官方的数据手册搞错了

没错啊。当AD0接地时,地址0XD0是读的地址,0XD1是写的地址。是把读写融合到地址里了。

zzipeng 发表于 2014-10-7 13:00:19

茅塞顿开!{:handshake:}

dashiyedewa 发表于 2014-10-7 13:08:32

学习了,虽然不善编程

魏道志 发表于 2015-4-23 09:38:04

顶起,同24C02,EEPROM的固定地址为1101 再加三位从机地址*** 再加R/W地址,共构成一个8位地址

wyudcl 发表于 2015-4-27 11:37:12

10xjzheng 发表于 2014-5-11 12:33
我知道了,Who_I_AM是只有7位的,是slave adress的高7位,哈哈,没有注意照顾细节
...

楼主正解,

王晨 发表于 2015-7-10 21:50:33

本帖最后由 王晨 于 2015-7-10 23:05 编辑

谢谢楼主,但是还是不知道OXD0是怎么来的呀?0XD0=1101 0000,但是bit7默认为0呀 ,bit6~bit0为1101 00,地址应该是0 1110100 +最低位呀,,

王晨 发表于 2015-7-10 23:26:46

jiang887786 发表于 2014-5-14 18:00
在下愚钝,0位和7位已经保留了而且默认为0.为啥他就是D0呢??想不通!一会我D0在写一下试试,我写68连ac ...

知道为什么是D0了吗,我也想不通呀

jiang887786 发表于 2015-7-11 18:03:06

王晨 发表于 2015-7-10 23:26
知道为什么是D0了吗,我也想不通呀

当时想通了,现在又忘记了,不好意思,一年多没玩了,

starsnow 发表于 2015-10-25 00:43:51

王晨 发表于 2015-7-10 23:26
知道为什么是D0了吗,我也想不通呀

D0在硬件引脚引出了,可以通过接地和接VCC来得到两个不同的地址。

光脚丫 发表于 2018-12-20 11:36:57

多谢楼主
页: [1]
查看完整版本: MPU6050作为从机地址设置的疑问