宁采儿 发表于 2013-11-7 11:34:41

读MPU6050数据输出全是0,郁闷,求大神指点

本帖最后由 宁采儿 于 2013-11-7 11:35 编辑

#include"sys.h"
#include"usart.h"
#include"delay.h"
#include"led.h"
#include"sys.h"
#include"delay.h"
#include "i2c.h"

typedef enum
{
        FALSE=0,
        TRUE=!FALSE
}bool;

//****************************************
// 定义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为读取


void I2c_Start()
{
      SDA_H;
      SCL_H;
      delay_us(5);
      SDA_L;
      delay_us(5);
      SCL_L;
               
}
void I2c_Stop()
{
          SCL_L;
      SDA_L;
      delay_us(5);
         SCL_H;
      SDA_H;
      delay_us(5);
}
void I2C_GPIO_Config(void)
{
GPIO_InitTypeDefGPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_6|GPIO_Pin_7;//SCL+SDA
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}

/************IIC start or stop ***************/
//开始信号:在SCL为高电平的时候,SDA由高电平向低电平跳变,开始传送数据;
//结束信号:在SCL为高电平的是后,SDA由低电平向高电平跳变,结束传送数据;
// 应答信号:接收数据的IC在接收到8bit后,向发送数据的IC发出特定的低电平脉冲,表示已收到数据。CPU向受控单元发出一个信号后,
//等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传输数据的判断

//**************************************
//I2C发送应答信号
//入口参数:ack (0:ACK 1:NAK)
//**************************************
void I2C_SendACK(u8 ack)
{
    if(!ack)
        SDA_L;                  //写应答信号
        else
        SDA_H;

    SCL_H;                  //拉高时钟线
    delay_us(5);               //延时
    SCL_L;                  //拉低时钟线
    delay_us(5);               //延时
}

//**************************************
//I2C接收应答信号
//**************************************
bool I2C_RecvACK()
{
    u8 CY;
        SCL_H;                  //拉高时钟线
    delay_us(5);               //延时
        if(SDA_read)
        CY=1;
        else
        CY=0;

    SCL_L;                  //拉低时钟线
    delay_us(5);                //延时
        if(CY)
    return TRUE;
        else
        return FALSE;
}

//**************************************
//向I2C总线发送一个字节数据
//**************************************
void I2C_SendByte(u8 dat)
{
    u8 i;
    for (i=0; i<8; i++)         //8位计数器
    {
                if(dat&0x80)
               SDA_H;
               else
               SDA_L;

      SCL_H;                //拉高时钟线
      delay_us(5);             //延时
      SCL_L;                //拉低时钟线
      delay_us(5);             //延时
                dat <<= 1;            //移出数据的最高位
    }
    I2C_RecvACK();
}
//**************************************
//从I2C总线接收一个字节数据
//**************************************
u8 I2C_RecvByte()
{
    u8 i;
    u8 dat = 0;
    SDA_H;                  //使能内部上拉,准备读取数据,
    for (i=0; i<8; i++)         //8位计数器
    {
      
      SCL_H;                //拉高时钟线
      delay_us(5);             //延时
                if(SDA_read)
      dat |=0x01;             //读数据
                           
      SCL_L;                //拉低时钟线
      delay_us(5);             //延时
                dat <<= 1;
    }
    return dat;
}

//**************************************
//向I2C设备写入一个字节数据
//**************************************
void Single_WriteI2C(u8 REG_Address,u8 REG_data)
{
    I2c_Start();                  //起始信号
    I2C_SendByte(SlaveAddress);   //发送设备地址+写信号
    I2C_SendByte(REG_Address);    //内部寄存器地址,
    I2C_SendByte(REG_data);       //内部寄存器数据,
    I2c_Stop();                   //发送停止信号
}
//**************************************
//从I2C设备读取一个字节数据
//**************************************
u8 Single_ReadI2C(u8 REG_Address)
{
        u8 REG_data;
        I2c_Start();                   //起始信号
        I2C_SendByte(SlaveAddress);    //发送设备地址+写信号
        I2C_SendByte(REG_Address);   //发送存储单元地址,从0开始       
        I2c_Start();                   //起始信号
        I2C_SendByte(SlaveAddress+1);//发送设备地址+读信号
        REG_data=I2C_RecvByte();       //读出寄存器数据
        I2C_SendACK(1);                //接收应答信号
        I2c_Stop();                  //停止信号
        return REG_data;
}
//**************************************
//初始化MPU6050
//**************************************
void InitMPU6050()
{
        Single_WriteI2C(PWR_MGMT_1, 0x00);        //解除休眠状态电源管理寄存器
        Single_WriteI2C(SMPLRT_DIV, 0x07);        //陀螺仪采样率,典型值:0x07(125Hz)
        Single_WriteI2C(CONFIG, 0x06);                //低通滤波频率,典型值:0x06(5Hz)
        Single_WriteI2C(GYRO_CONFIG, 0x18);        //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
        Single_WriteI2C(ACCEL_CONFIG, 0x01); //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)
}
//**************************************
//合成数据
//**************************************
//int32_t GetData(u8 REG_Address)
int32_t GetData(u8 REG_Address)
{
        u8 H,L;
        H=Single_ReadI2C(REG_Address);           //#define        ACCEL_XOUT_H        0x3B
        L=Single_ReadI2C(REG_Address+1);   //#define        ACCEL_XOUT_L        0x3C
        return (H<<8)+L;   //合成数据
       
}


int main(void)
{
      SystemInit();
      delay_init(72);
      uart_init(9600);
                I2C_GPIO_Config();
                InitMPU6050();
      delay_ms(100);
      while(1)
      {
      

                               
               printf("XSpeed is %d\n\n",GetData(ACCEL_XOUT_H));                //显示X轴加速度
                printf("YSpeed is %d\n\n",GetData(ACCEL_YOUT_H));                //显示Y轴加速度
                printf("ZSpeed is %d\n\n",GetData(ACCEL_ZOUT_H));                //显示Z轴加速度
               printf("XCSpeed is %d\n\n",GetData(GYRO_XOUT_H));                //显示X轴加速度
                printf("YCSpeed is %d\n\n",GetData(GYRO_YOUT_H));                //显示Y轴加速度
                printf("ZCSpeed is %d\n\n",GetData(GYRO_ZOUT_H));                //显示Z轴加速度
                LED0=!LED0;
                LED1=!LED1;
                delay_ms(100);
                delay_ms(100);
      }
}
我试过读0X68,结果也读错数据。我用的是MPU6050的模块。

samo110 发表于 2013-11-7 12:15:13

void InitMPU6050()函数里面先复位一下器件试试,也是操作PWR_MGMT_1寄存器

avrwoo 发表于 2013-11-7 12:35:33

本帖最后由 avrwoo 于 2013-11-7 12:37 编辑

调试中发现是加速度一直有数值显示,运动停下来的话是数据保持不动,陀螺仪不动的话数据就是零,运动后才有数据,总感觉加速度和陀螺的输出都应该是静止时是零,运动才应有数据显示,不知道哪位用过的朋友给讲解下?LZ的可能是I2C的这地方程序有问题,可能是时序不准,

宁采儿 发表于 2013-11-7 13:48:26

samo110 发表于 2013-11-7 12:15 static/image/common/back.gif
void InitMPU6050()函数里面先复位一下器件试试,也是操作PWR_MGMT_1寄存器

用51调试就能正常读取数据,这个代码是移植的51的,居然不通。。。晚上看看你的方法行不

samo110 发表于 2013-11-7 15:21:49

avrwoo 发表于 2013-11-7 12:35 static/image/common/back.gif
调试中发现是加速度一直有数值显示,运动停下来的话是数据保持不动,陀螺仪不动的话数据就是零,运动后才有 ...

陀螺仪测的是角速度,要运动才有数据,但是由于存在零漂,静止时一般也有较小的数据
加速度计测得就是加速度,这个数据是包括重力加速度的,所以静止时有数据,但是变化不大,一般就找姿态的话加速度计就是用这个本地重力加速度来测角度的

avrwoo 发表于 2013-11-7 18:00:10

宁采儿 发表于 2013-11-7 13:48 static/image/common/back.gif
用51调试就能正常读取数据,这个代码是移植的51的,居然不通。。。晚上看看你的方法行不 ...

这个是论坛里一个网友的AVR的程序,我试了可以读出数据,你看看。

avrwoo 发表于 2013-11-7 18:01:36

samo110 发表于 2013-11-7 15:21 static/image/common/back.gif
陀螺仪测的是角速度,要运动才有数据,但是由于存在零漂,静止时一般也有较小的数据
加速度计测得就是加 ...

哦。明白了。谢谢。

-阿发- 发表于 2013-11-7 19:09:34

慢慢来,有条件话对照着IIC总线时序调试调试,应答信号要有。不然不是全0就是全1.我前段时间也是遇到这种问题。后来发现是IIC通信中没有给应答信号造成的

宁采儿 发表于 2013-11-8 02:00:05

samo110 发表于 2013-11-7 12:15 static/image/common/back.gif
void InitMPU6050()函数里面先复位一下器件试试,也是操作PWR_MGMT_1寄存器

这位大神,我现在对你真是佩服的五体投地啊,调了4天左右,一直搞不好。无奈试了一下你的方案,草,一下子就有数据读出来了。感激。。。

samo110 发表于 2013-11-8 09:11:08

宁采儿 发表于 2013-11-8 02:00 static/image/common/back.gif
这位大神,我现在对你真是佩服的五体投地啊,调了4天左右,一直搞不好。无奈试了一下你的方案,草,一下 ...

之前我也是遇到你这种情况,一直读出-1……
页: [1]
查看完整版本: 读MPU6050数据输出全是0,郁闷,求大神指点