边个叫我 发表于 2013-5-7 21:18:01

【求助】关于mpu6050模块,数据全是FF

本帖最后由 边个叫我 于 2013-5-7 21:20 编辑

小弟不才,买了个mpu6050模块,打算用avr单片机(mega16)先读数出来。但是怎样都是FF的读数。。。
我不知道是什么情况。
检查过iic时序图,还没发现错误。。。。
恳请各位英雄帮帮忙。。。{:3_60:}/*avr_usart_mpu6050*/
#include"iom16v.h"
#include"macros.h"
#include"mpu6050.h"
void main(void)
{
       uint b;
       delayms(5000);                //上电延时
       I2C_Init();               
//       InitLcd();                //液晶初始化
       uart_init(19200);
       InitMPU6050();        //初始化MPU6050
       delayms(5000);                //上电延时       
       while(1)
        {
/*       
                Display10BitData(GetData(ACCEL_XOUT_H),2,0);        //显示X轴加速度
                Display10BitData(GetData(ACCEL_YOUT_H),7,0);        //显示Y轴加速度
                Display10BitData(GetData(ACCEL_ZOUT_H),12,0);        //显示Z轴加速度
                Display10BitData(GetData(GYRO_XOUT_H),2,1);        //显示X轴角速度
                Display10BitData(GetData(GYRO_YOUT_H),7,1);        //显示Y轴角速度
                Display10BitData(GetData(GYRO_ZOUT_H),12,1);        //显示
*/

              uart_sendB('a');
                  b = GetData(ACCEL_XOUT_H);
//                  uart_sendB(b);
/*          
              uart_sendB(GetData(ACCEL_XOUT_H));
              uart_sendB(GetData(ACCEL_YOUT_H));
                  uart_sendB(GetData(ACCEL_ZOUT_H));
                  uart_sendB(GetData(GYRO_XOUT_H));
                  uart_sendB(GetData(GYRO_YOUT_H));
                  uart_sendB(GetData(GYRO_ZOUT_H));*/
                  //flag=0;

                     uart_sendB(b>>8);
                  uart_sendB(b&0xff);
                delayms(5000);
        }
}



/*mpu6050.h*/

/*****************************************************

普通IO模拟I2C通信,MPU-6050数据处理

*****************************************************/

#ifndef__MPU6050_H__
#define__MPU6050_H__

typedef unsigned charuchar;
typedef unsigned int   uint;

//-------------------------------------------------------
//端口定义
//-------------------------------------------------------

//#define SCL       PC0       //输出1
#define   Hign_SCL    PORTC |= (1 << PC0)
#define   Low_SCL   PORTC &= ~(1 << PC0)

//#define SDA      PC1      //输出1/输入0
#define   Hign_SDA    PORTC |= (1 << PC1)   
#define   Low_SDA   PORTC &= ~(1 << PC1)
#define   Read_SDA    PINC & (1 << PC1)

#define   EN_SDA_1    DDRC |= (1 << PC1)//输出1
#define   EN_SDA_0    DDRC &= ~(1 << PC1) //输入0

//-------------------------------------------------------
// 定义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为读取
#definemclk   12000000
#pragma interrupt_handler uart_rx:12

//-------------------------------------------------------
// 函数声明
//-------------------------------------------------------

voidInitMPU6050(void);                                        //初始化MPU6050
voiddelayus(uint n);
voiddelayms(uint lms);
voidI2C_Init(void);
voidI2C_Start(void);
voidI2C_Stop(void);
voidI2C_Ack(void);
voidI2C_NoAck(void);
uchar I2C_WaitAck(void);
voidI2C_SendByte(uchar dat);
uchar I2C_RecvByte(uchar ack);
uchar Single_ReadI2C(uchar REG_Address);
voidSingle_WriteI2C(uchar REG_Address,uchar REG_data);


int   GetData(uchar REG_Address);                  //16位数据合成

//-------------------------------------------------------
// 延时函数
//-------------------------------------------------------
void delayus(unsigned int n)
{
   unsigned int i=0;   
       for(i=0;i<n;i++)
       asm("nop");

}

//-------------------------------------------------------
// 延时函数
//8M 延时计算公式 = 2.88+(n-1)*0.75 us
//

//ms级别的延时函数
void delayms(unsigned int lms)
{
        while(lms--)
        {
                delayus(1000);      //延时1ms
    }
}
//-------------------------------------------------------
//USART
//-------------------------------------------------------
uchar rdata,flag=0;
void uart_init(uint baud)
{
    UCSRB=0x00;
   UCSRA=0x00;                   //控制寄存器清零
   UCSRC=(1<<URSEL)|(0<<UPM0)|(3<<UCSZ0);   
                                                      //选择UCSRC,异步模式,禁止                        
                                                   //   校验,1位停止位,8位数据位
   baud=mclk/16/baud-1        ;   //波特率最大为65K
   UBRRL=baud;                                                        
   UBRRH=baud>>8;                    //设置波特率
   UCSRB=(1<<TXEN)|(1<<RXEN)|(1<<RXCIE);
                                                       //接收、发送使能,接收中断使能
   SREG=BIT(7);                      //全局中断开放
   DDRD|=0X02;                      //配置TX为输出(很重要)

}
void uart_sendB(uchar data)
{
   while(!(UCSRA&(BIT(UDRE)))) ;
   UDR=data;
   while(!(UCSRA&(BIT(TXC))));
   UCSRA|=BIT(TXC);
}
void uart_rx(void)
{
    UCSRB&=~BIT(RXCIE);
        rdata=UDR;
        flag=1;
        UCSRB|=BIT(RXCIE);
}
//-------------------------------------------------------
//I2C初始化
//--
void I2C_Init(void)
{
        PORTC &= ~(1 << PC0);    //SCL的PORT状态锁定为0,以后不再改变
        DDRC &= ~(1 << PC0);   //SCL设置为输入口
       
        PORTC &= ~(1 << PC1);    //SDA的PORT状态锁定为0,以后不再改变
        DDRC &= ~(1 << PC1);    //SDA设置为输入口
        delayus(10);
}
//-------------------------------------------------------
//I2C起始信号
//在SCL为高电平的时候,SDA由高电平向低电平跳变,开始传送数据
//-------------------------------------------------------
void I2C_Start(void)
{
    EN_SDA_1;                                       //使能输出
       
        Hign_SDA;                  //拉高数据线
    Hign_SCL;                  //拉高时钟线
    delayus(5);
        Low_SDA;                  //产生下降沿
    delayus(5);
        Low_SCL;
}

//-------------------------------------------------------
//I2C停止信号
//在SCL为高电平的时候,SDA由低电平向高电平跳变,结束传送数据
//-------------------------------------------------------
void I2C_Stop(void)
{
    EN_SDA_1;                                       //使能输出
       
        Low_SDA;
    Hign_SCL;       
        delayus(5);
//        Hign_SCL;            
    Hign_SDA;                  
    delayus(5);               
}

//-------------------------------------------------------
//I2C产生应答信号
//-------------------------------------------------------
void I2C_Ack(void)
{
    Low_SCL;
        EN_SDA_1;                   //使能SDA输出
       
        Low_SDA;
        delayus(5);
        Hign_SCL;
        delayus(5);
        Low_SCL;
        delayus(5);         
}

//-------------------------------------------------------
//I2C不产生应答信号
//-------------------------------------------------------
void I2C_NoAck(void)
{
    Low_SCL;
        EN_SDA_1;                   //使能SDA输出
       
        Hign_SDA;
        delayus(5);
        Hign_SCL;
        delayus(5);
        Low_SCL;       
        delayus(5);   
}

/*******************************************************************************
* Function Name: I2C_WaitAck
* Input          : None
* Output         : 1,接收应答失败
                   0,接收应答成功
* Return         : Wheather       Reserive Slave Acknowledge Single
****************************************************************************** */
uchar I2C_WaitAck(void)        //返回为:=1有ACK,=0无ACK
{
        uchar errTime = 0;
        EN_SDA_0;
        Hign_SDA;
        delayus(10);
        Hign_SCL;
        delayus(10);
        while(Read_SDA)
        {
                errTime++;
                if(errTime>250)
                {
                        I2C_Stop();
                        return 1;
                }
        }
        Low_SCL;//时钟输出0           
        return 0;
}

//-------------------------------------------------------
//向I2C总线发送一个字节数据
//返回从机有无应答,1,有应答,0,无应答
//-------------------------------------------------------
void I2C_SendByte(uchar dat)
{
    uchar i;
        EN_SDA_1;                   //使能SDA输出
   
        Low_SCL;
    for (i=0; i<8; i++)         //8位计数器
    {               
                if(dat & 0x80)
         {Hign_SDA;}
      else
         {Low_SDA;}
                dat <<= 1;            //移出数据的最高位
      Hign_SCL;                                //SCL高电平,保持数据                                  
      delayus(10);
                Low_SCL;                                //SCL低电平,数据被送入I2C
      delayus(10);
        }
}

//-------------------------------------------------------
//从I2C总线接收一个字节数据
//ack=1时,发送ACK,ack=0,发送nACK
//-------------------------------------------------------
uchar I2C_RecvByte(uchar ack)
{
    uchar i;
    uchar dat = 0;
        EN_SDA_0;                   //使能SDA输入

    for (i=0; i<8; i++)         //8位计数器
    {      
      Low_SCL;
                delayus(10);
                Hign_SCL;
                dat <<= 1;
                if(Read_SDA) dat++;       
      delayus(10);               
    }

        if(!ack)
        {
          I2C_NoAck();
        }
        else
        {
          I2C_Ack();
        }      
    return dat;
}

//-------------------------------------------------------
//向I2C设备写入一个字节数据
//-------------------------------------------------------
void Single_WriteI2C(uchar REG_Address,uchar REG_data)
{                  
        I2C_Start();                                     //起始信号
    I2C_SendByte(SlaveAddress);   //发送设备地址+写信号
        I2C_WaitAck();
    I2C_SendByte(REG_Address);    //内部寄存器地址
        I2C_WaitAck();
    I2C_SendByte(REG_data);       //内部寄存器数据
        I2C_WaitAck();
    I2C_Stop();                   //发送停止信号
}

//-------------------------------------------------------
//从I2C设备读取一个字节数据
//-------------------------------------------------------
uchar Single_ReadI2C(uchar REG_Address)
{
        uchar REG_data;
        I2C_Start();                   //起始信号
        I2C_SendByte(SlaveAddress);    //发送设备地址+写信号
        I2C_WaitAck();
        I2C_SendByte(REG_Address);   //发送存储单元地址,从0开始       
        I2C_WaitAck();
        I2C_Start();                   //起始信号
        I2C_SendByte(SlaveAddress+1);//发送设备地址+读信号
        I2C_WaitAck();
        REG_data=I2C_RecvByte(0);       //读出寄存器数据               
        I2C_Stop();                  //停止信号
        return REG_data;
}

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

//-------------------------------------------------------
//合成数据
//-------------------------------------------------------
int GetData(uchar REG_Address)
{
        uint H;
        uchar L;
        H=Single_ReadI2C(REG_Address);
        L=Single_ReadI2C(REG_Address+1);
        return (H<<8)+L;   //合成数据
}

#endif

边个叫我 发表于 2013-5-8 08:34:03

大神呢?
自顶。。。

cdd329958 发表于 2013-8-3 20:35:24

请问楼主的问题得到解决了吗,我也正困惑呢,要是楼主完成了希望分享一下

-阿发- 发表于 2013-10-14 21:09:04

我也遇到了跟你同样的问题,读出的寄存器值全部都是255,迷茫无助了,求神兵天降。。。楼主解决了能告知一下吗?

岗本科技 发表于 2013-10-14 21:16:44

兄弟给你个治疗吧,这种问题只有靠时间来解决,熟悉的工程师 估计10分钟搞定,本身找问题也是种学习

-阿发- 发表于 2013-10-16 17:22:04

兄弟,我的问题今天解决了,问题出在IIC上了。我的是忘记了应答信号,拔下模块也是返回FF,你用示波器试试看跟我的问题一样吗。

LZ19992005 发表于 2014-1-2 20:13:12

兄弟给我指点指点吧

茶亦爽 发表于 2014-1-6 15:10:07

我的问题是mpu6050 id 是FF,是什么问题,求救啊

xlwuhai 发表于 2014-5-12 21:06:48

这种问题最好对照示波器去检查一遍,使用stm32模拟的I2C程序,发现不知道是谁挖了个坑,如下
AD+R填错了,所以读出全为FF。大家留点心!

fengbuding 发表于 2014-5-27 22:32:32

是不是论坛里的程序?我也是用的这个,读不出来,只要把 I2C_Stop();改成 Low_SCL;就OK了;你试试

uchar I2C_WaitAck(void)          //返回为:=1有ACK,=0无ACK
{
      uchar errTime = 0;
      EN_SDA_0;
      Hign_SDA;
      delayus(10);
      Hign_SCL;
      delayus(10);
      while(Read_SDA)
      {
                errTime++;
                if(errTime>250)
                {
                        I2C_Stop();
                        return 1;
                }
      }
      Low_SCL;//时钟输出0            
      return 0;
}

Mac_Alex 发表于 2015-2-5 15:56:07

我也遇到这个问题了,全部是FF,楼主解决了吗?
页: [1]
查看完整版本: 【求助】关于mpu6050模块,数据全是FF