MPU6050作为从机地址设置的疑问
我知道I2C通讯的时候最低位地址是决定读写的,但是我看到有两组地址,一组是0x68和0x69,一组是0xd0和0xd1。我看见别人51的设置的是0xD0,但是看到数据手册又是0x68。疑问1:究竟这两个地址那个是I2C从机地址?
疑问2:另一个地址究竟是什么?做什么用的?
新手上路,请大神多多指教。 我知道了,Who_I_AM是只有7位的,是slave adress的高7位,哈哈,没有注意照顾细节
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:45 编辑
我想我的时序还是有问题,看看问题在哪吧! jiang887786 发表于 2014-5-14 18:44
我想我的时序还是有问题,看看问题在哪吧!
我觉得懂I2C的原理就可以了,模拟时序我觉得可以不要亲自去做,或者做一两个就好,直接网上找程序,如果你想要程序的话,可以留言。QQ:934345073 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.
**
** ###################################################################
*/
jiang887786 发表于 2014-5-15 10:01
谢谢,我是飞思卡尔的单片机,你的代码我可能不好用,我发现是红色部分的问题,我修改了读字节的部分,写 ...
不好意思啊,I2C没有什么调试经验,我就只是卡在地址那里,你自己找下。 10xjzheng 发表于 2014-5-15 11:58
不好意思啊,I2C没有什么调试经验,我就只是卡在地址那里,你自己找下。 ...
请问你的是51的代码吗?方便的话发我邮箱一份吧,我想拿51先调一下试试吧,纠结的快不行了,2091881672@qq。com。谢谢!{:handshake:} STM32103我也有单片机,但是不知道什么编译器还不了解呢现在! 疑惑了好几天的问题终于解决了,感谢楼主啊 一直存在的疑问终于解决了,谢谢楼主的分享! liushenyoko 发表于 2014-6-9 09:43
一直存在的疑问终于解决了,谢谢楼主的分享!
不谢,我就知道终有一天会发生这样的场景,一起来为论坛做点贡献哈!! jiang887786 发表于 2014-5-15 15:06
请问你的是51的代码吗?方便的话发我邮箱一份吧,我想拿51先调一下试试吧,纠结的快不行了,2091881672@q ...
你上面的那张图片是什么来着?程序再这里,51的I2C读取MPU6050数据,通过液晶输出取MPU6050数据,通过1602液晶输出: 10xjzheng 发表于 2014-6-9 10:10
你上面的那张图片是什么来着?程序再这里,51的I2C读取MPU6050数据,通过液晶输出取MPU6050数据,通过160 ...
逻辑分析仪,公司买的,搞这些东西可以存储时序,看看一目了然,我们这行的必备利器!哈哈!谢谢,哥们{:lol:} {:handshake:} jiang887786 发表于 2014-6-9 10:28
逻辑分析仪,公司买的,搞这些东西可以存储时序,看看一目了然,我们这行的必备利器!哈哈!谢谢,哥们{: ...
很厉害的样子!!估计很贵吧 不贵啊,莫大这边就有300多元吧,上次我调试DS1302就是用它看出时序有些不对,提前几个空操作,结果就有数据出来了,利器!把数据上升沿提前一点点... 牛
{:smile:} 大神,请问一下,我的6050读出来的数据不变怎么回事啊? 自己弄的程序 IIC总线通了,因为仿真看,给寄存器写数据,在读数据能正常读出,但是算其他参数的时候,MPU6050不动的情况下,数据在变,如图Gyro_y的值程序打断点运行时看数据,有时候会出现其他数据! 不错 ....... 这里表述的不太好。应该说:当AD0 为逻辑低电平,从机地址为b1101000(0x68);当AD0 为逻辑ym 电平,从机地址为b1101001(0x69)。
AD0与WHO_AM_I的bit1有关,而与bit0无关。8位从机地址的最高位都为0。
可以近似认为bit0决定的是读或写操作(即认为读写的地址不一样。因为根据手册的协议,地址只有7位,而最后一位决定的是读或者写。). 请问楼主 ,这个宏定义有什么使用吗? #define WHO_AM_I 0x75 who与争锋 发表于 2014-9-24 14:16
请问楼主 ,这个宏定义有什么使用吗? #define WHO_AM_I 0x75
可能是验证你读取寄存器对不对吧,我不大清楚 10xjzheng 发表于 2014-9-24 18:26
可能是验证你读取寄存器对不对吧,我不大清楚
1,程序里好像都没用到
2,上面也说默认是0x68.
所以有点奇怪了。。。 who与争锋 发表于 2014-9-25 09:37
1,程序里好像都没用到
2,上面也说默认是0x68.
所以有点奇怪了。。。
今天才知道,那个是7位+1位构成I2C地址 本帖最后由 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地址没关系?
who与争锋 发表于 2014-9-25 10:30
I2C地址是(根据手册的定义):bit7~bit1(这里是7位 bit1的取值根据AD0来确定)。bit0位不用。
根据手册 ...
我觉得是官方的数据手册搞错了 10xjzheng 发表于 2014-9-25 13:11
我觉得是官方的数据手册搞错了
没错啊。当AD0接地时,地址0XD0是读的地址,0XD1是写的地址。是把读写融合到地址里了。 茅塞顿开!{:handshake:} 学习了,虽然不善编程 顶起,同24C02,EEPROM的固定地址为1101 再加三位从机地址*** 再加R/W地址,共构成一个8位地址 10xjzheng 发表于 2014-5-11 12:33
我知道了,Who_I_AM是只有7位的,是slave adress的高7位,哈哈,没有注意照顾细节
...
楼主正解, 本帖最后由 王晨 于 2015-7-10 23:05 编辑
谢谢楼主,但是还是不知道OXD0是怎么来的呀?0XD0=1101 0000,但是bit7默认为0呀 ,bit6~bit0为1101 00,地址应该是0 1110100 +最低位呀,, jiang887786 发表于 2014-5-14 18:00
在下愚钝,0位和7位已经保留了而且默认为0.为啥他就是D0呢??想不通!一会我D0在写一下试试,我写68连ac ...
知道为什么是D0了吗,我也想不通呀 王晨 发表于 2015-7-10 23:26
知道为什么是D0了吗,我也想不通呀
当时想通了,现在又忘记了,不好意思,一年多没玩了, 王晨 发表于 2015-7-10 23:26
知道为什么是D0了吗,我也想不通呀
D0在硬件引脚引出了,可以通过接地和接VCC来得到两个不同的地址。 多谢楼主
页:
[1]