LZ19992005 发表于 2014-1-4 13:23:00

MPU6050 陀螺仪输出的数据

输出的数据不停的跳变,为什么?希望有人指教一下。
#include<reg52.h>
#include<math.h>
#include<stdio.h>
#include<intrins.h>
typedef unsigned charuchar;
typedef unsigned short ushort;
typedef unsigned int   uint;
//***********************************
//       单片机端口定义
//***********************************
sbit RS=P1^3;                      //寄存器
sbit CS=P1^2;                      //片选
sbit SCLK=P1^1;                      //串行时钟输入
sbit SID=P1^0;                      //串行数据输入
sbit SCL=P0^2;                                  //I2C时钟引脚定义
sbit SDA=P0^3;                                  //I2C数据引脚定义   
//***********************************
//       MPU6050内部地址定义
//***********************************
#define SMPLRT_DIV    0x19           //陀螺仪采样率,典型值:0x07(125Hz)
#define CONFIG      0X1A           //低通滤波频率,典型值:0x06(5Hz)
#define GYRO_CONFIG   0X1B           //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
#define ACCEL_CONFIG0X1C           //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)
#define ACCEL_XOUT_H0X3B           //存储最近的X轴、Y轴、Z轴加速度感应器的测量值
#define ACCEL_XOUT_L0X3C
#define ACCEL_YOUT_H0X3D
#define ACCEL_YOUT_L0X3E
#define ACCEL_ZOUT_H0X3F
#define ACCEL_ZOUT_L0X40
#define GYRO_XOUT_H   0X43                //存储最近的X轴、Y轴、Z轴陀螺仪感应器的测量值 */
#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 SlaveAddress0xd0               //IIC写入时的地址字节数据,+1为读取
//*************************************
//                          LCD缓存区分配
//*************************************
uchar xdata display_buf=0x20;
//显示存贮器安排        第一行           0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12,13,14,15
//
//显示值                                           A         0   0   0       -   0   0   0      -   0   0   0       
//
//                  第二行   16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
//
//显示值                                           G       -   0        0   0      -        0   0   0         0   0   0
#define ACCEL_XOUT0           //按照上述显示缓存区定义的显示X轴加速度显示第一位位置
#define ACCEL_YOUT7           //按照上述显示缓存区定义的显示Y轴加速度显示第一位位置
#define ACCEL_ZOUT 12           //按照上述显示缓存区定义的显示Z轴加速度显示第一位位置
#define GYRO_XOUT16      //按照上述显示缓存区定义的显示X轴角速度显示第一位位置
#define GYRO_YOUT23           //按照上述显示缓存区定义的显示Y轴角速度显示第一位位置
#define GYRO_ZOUT29           //按照上述显示缓存区定义的显示Z轴角速度显示第一位位置

//********************延时子程序***********//
void delay(uint i)
{
        uint j,k;
        for(j=0;j<i;j++)
        for(k=0;k<50;k++);
}

//**************************************
//延时5微秒(STC90C52RC@12M)
//不同的工作环境,需要调整此函数
//当改用1T的MCU时,请调整此延时函数
//**************************************
void Delay5us()
{
        _nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();
       
}
//**************************************
//I2C起始信号
//**************************************
void I2C_Start()
{
    SDA = 1;                     //拉高数据线
    SCL = 1;                     //拉高时钟线
    Delay5us();                  //延时
    SDA = 0;                     //产生下降沿
    Delay5us();                  //延时
    SCL = 0;                     //拉低时钟线
}
//**************************************
//I2C停止信号
//**************************************
void I2C_Stop()
{
    SDA = 0;                     //拉低数据线
    SCL = 1;                     //拉高时钟线
    Delay5us();                  //延时
    SDA = 1;                     //产生上升沿
    Delay5us();                  //延时
}
//**************************************
//I2C发送应答信号
//入口参数:ack (0:ACK 1:NAK)
//**************************************
void I2C_SendACK(bit ack)
{
    SDA = ack;                   //写应答信号 ACK=0表示应答   ACK=1表示不应答
    SCL = 1;                     //拉高时钟线
    Delay5us();                  //延时
    SCL = 0;                     //拉低时钟线
    Delay5us();                  //延时
}
//**************************************
//I2C接收应答信号
//**************************************
bit I2C_RecvACK()
{
    SCL = 1;                     //拉高时钟线
    Delay5us();                  //延时
    CY = SDA;                  //读应答信号
    SCL = 0;                     //拉低时钟线
    Delay5us();                  //延时
    return CY;
}
//**************************************
//向I2C总线发送一个字节数据
//**************************************
void I2C_SendByte(uchar dat)
{
    uchar i;
    for (i=0; i<8; i++)          //8位计数器
    {
      dat <<= 1;               //把当前最高位左移入PSW寄存器的CY位
                SCL=0;
                Delay5us();
      SDA = CY;                //把CY位内容发送到I2C总线       
      SCL = 1;               //拉高时钟线
      Delay5us();            //延时
      SCL = 0;               //拉低时钟线
      Delay5us();            //延时
    }
               
    I2C_RecvACK();
}
//**************************************
//从I2C总线接收一个字节数据
//**************************************
uchar I2C_RecvByte()
{
    uchar i;
    uchar dat = 0;
    SDA = 1;                  //使能内部上拉,准备读取数据,
    for (i=0; i<8; i++)         //8位计数器
    {
      SCL = 1;               //拉高时钟线
      Delay5us();            //延时
      dat=(dat<<1) |SDA;            //读数据
      SCL = 0;               //拉低时钟线
      Delay5us();            //延时
    }
    return dat;
}
//**************************************
//向I2C设备写入一个字节数据
//**************************************
void Single_WriteI2C(uchar REG_Address,uchar REG_data)
{
    I2C_Start();                     //起始信号
    I2C_SendByte(SlaveAddress);      //写入地址字节数据
    I2C_SendByte(REG_Address);       //内部寄存器地址,
    I2C_SendByte(REG_data);          //内部寄存器数据,
    I2C_Stop();                      //发送停止信号
}
//**************************************
//从I2C设备读取一个字节数据
//**************************************
uchar Single_ReadI2C(uchar REG_Address)
{
        uchar 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)
}
//**************************************
//合成数据
//**************************************
int GetData(uchar REG_Address)
{
        char H,L;
        H=Single_ReadI2C(REG_Address);
        L=Single_ReadI2C(REG_Address+1);
        return (H<<8)+L;                        //合成数据
}

//***************************************
// 加速度传感器值X、Y、Z轴
//***************************************
void ACCEL()
{ uchar i,x,y,z;
uint t;
   
   x=GetData(ACCEL_XOUT_H);                               //显示X轴加速度

   i=x/100;
   t=x%100;
   display_buf=i+0x30;      //取百位数
   i=t/10;
   t=t%10;
   display_buf[ ACCEL_XOUT+4]=i+0x30;   //取十位数
   i=t%10;
   display_buf[ ACCEL_XOUT+5]=i+0x30;   //取个位数
   display_buf[ ACCEL_XOUT+0]='A';
   


   y=GetData(ACCEL_YOUT_H);                                   //显示Y轴加速度
   
   i=y/100;
   t=y%100;
   display_buf=i+0x30;      //取百位数
   i=t/10;
   t=t%10;
   display_buf=i+0x30;      //取十位数
   i=t%10;
   display_buf=i+0X30;      //取个位数
   display_buf='-';             
   
   z=GetData(ACCEL_ZOUT_H);                                  //显示Z轴加速
   i=z/100;
   t=z%100;
   display_buf=i+0x30;      //取百位数
   i=t/10;
   t=t%10;
   display_buf=i+0x30;      //取十位数
   i=t%10;
   display_buf=i+0X30;      //取个位数
   display_buf='-';             
}
//***********************************************
//                   陀螺仪
//***********************************************
void GYRO()
{
   uchar i,x,y,z;
   uint t;
   
   x=GetData(GYRO_XOUT_H);
   i=x/100;
   t=x%100;
   display_buf=i+0x30;
   i=t/10;
   t=t%10;
   display_buf=i+0x30;
   i=t%10;
   display_buf=i+0x30;
   display_buf='-';               
   display_buf='G';


   y=GetData(GYRO_YOUT_H);
   i=y/100;
   t=y%100;
   display_buf=i+0x30;
   i=t/10;
   t=t%10;
   display_buf=i+0x30;
   i=t%10;
   display_buf=i+0x30;
   display_buf='-';
   

   z=GetData(GYRO_ZOUT_H);
   i=z/100;
   t=z%100;
   display_buf=i+0x30;
   i=t/10;
   t=t%10;
   display_buf=i+0x30;
   i=t%10;
   display_buf=i+0x30;
       
}
//***************写指令到LCD模块***********//
void tranfser_command(int data1)
{
        char i;
        CS=0;
        RS=0;
        for(i=0;i<8;i++)
        {
                SCLK=0;
                if(data1&0x80)
                     SID=1;
                else   SID=0;
                delay(5);
                SCLK=1;
                delay(5);
                data1=data1<<=1;
        }

}

//****************写数据到LCD模块***********//
void tranfser_data(int data2)
{
   char i;
   CS=0;
   RS=1;
   for(i=0;i<8;i++)
        {
                SCLK=0;
                if(data2&0x80)   SID=1;
                else             SID=0;
                delay(1);
                SCLK=1;
                delay(1);
                data2=data2<<=1;
        }
}

//*********LCD模块初始化***********//
void initial_lcd()
{
        CS=0;
        delay(10);
        tranfser_command(0x38);           //设置16X2显示,5X7点阵,8位数据接口
        delay(10);
        tranfser_command(0x0c);           //显示模式设置:显示开,无光标,光标不闪烁
        delay(10);
        tranfser_command(0x01);           //清屏幕指令,将以前的显示内容清除
        delay(10);
        tranfser_command(0x06);           //显示模式设置:光标右移,字符不移
        delay(10);
}

//*******在指定的列和位显示指定的字母、数字、符号****//
void disp_char()
{
        uint i;
        tranfser_command(0x80+0+0);
        for(i=0;i<16;i++)
        {
                tranfser_data(display_buf);
        }
        tranfser_command(0x80+0x40+0);
        for(i=16;i<32;i++)
        {
                tranfser_data(display_buf);
        }
}
//*********LCD清屏******************//
void clr_screen()
        {
        uchar i;
        for(i=0;i<32;i++) display_buf=0x20;
       
        disp_char();
        }


void main()
{
    delay(500);
           initial_lcd();            //LCD屏初始化
    clr_screen();                         //LCD清屏
        InitMPU6050();
        delay(150);
        while(1)
        { delay(10000);
          ACCEL();                           //加速度显示
          GYRO();                           //陀螺仪显示
        }
}

youyou_1 发表于 2014-1-4 14:34:13

加上滤波就相对来说稳定了,具体方法可以在论坛上搜索平衡车……

LZ19992005 发表于 2014-1-4 15:38:55

youyou_1 发表于 2014-1-4 14:34
加上滤波就相对来说稳定了,具体方法可以在论坛上搜索平衡车……

谢谢您的指导。

四轴飞行器 发表于 2014-1-4 15:40:10

嘿嘿 这里高手很多

LZ19992005 发表于 2014-1-5 12:12:55

谢谢您的指导。

haha0088 发表于 2014-1-8 17:04:47

收藏代码。。。{:lol:}
页: [1]
查看完整版本: MPU6050 陀螺仪输出的数据