搜索
bottom↓
回复: 5

MPU6050 陀螺仪输出的数据

[复制链接]

出0入0汤圆

发表于 2014-1-4 13:23:00 | 显示全部楼层 |阅读模式
输出的数据不停的跳变,为什么?希望有人指教一下。
#include<reg52.h>
#include<math.h>
#include<stdio.h>
#include<intrins.h>
typedef unsigned char  uchar;
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_CONFIG  0X1C           //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)
#define ACCEL_XOUT_H  0X3B           //存储最近的X轴、Y轴、Z轴加速度感应器的测量值
#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 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 SlaveAddress  0xd0                 //IIC写入时的地址字节数据,+1为读取
//*************************************
//                          LCD缓存区分配
//*************************************
uchar xdata display_buf[32]=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_XOUT  0           //按照上述显示缓存区定义的显示X轴加速度显示第一位位置
#define ACCEL_YOUT  7           //按照上述显示缓存区定义的显示Y轴加速度显示第一位位置
#define ACCEL_ZOUT 12           //按照上述显示缓存区定义的显示Z轴加速度显示第一位位置
#define GYRO_XOUT  16      //按照上述显示缓存区定义的显示X轴角速度显示第一位位置
#define GYRO_YOUT  23           //按照上述显示缓存区定义的显示Y轴角速度显示第一位位置
#define GYRO_ZOUT  29           //按照上述显示缓存区定义的显示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[ACCEL_XOUT+3]=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[ACCEL_YOUT+1]=i+0x30;        //取百位数
   i=t/10;
   t=t%10;
   display_buf[ACCEL_YOUT+2]=i+0x30;        //取十位数
   i=t%10;
   display_buf[ACCEL_YOUT+3]=i+0X30;        //取个位数
   display_buf[ACCEL_YOUT+0]='-';               
   
   z=GetData(ACCEL_ZOUT_H);                                    //显示Z轴加速
   i=z/100;
   t=z%100;
   display_buf[ACCEL_ZOUT+1]=i+0x30;        //取百位数
   i=t/10;
   t=t%10;
   display_buf[ACCEL_ZOUT+2]=i+0x30;        //取十位数
   i=t%10;
   display_buf[ACCEL_ZOUT+3]=i+0X30;        //取个位数
   display_buf[ACCEL_ZOUT+0]='-';               
  }
//***********************************************
//                     陀螺仪
//***********************************************
void GYRO()
{
   uchar i,x,y,z;
   uint t;
   
   x=GetData(GYRO_XOUT_H);
   i=x/100;
   t=x%100;
   display_buf[GYRO_XOUT+3]=i+0x30;
   i=t/10;
   t=t%10;
   display_buf[GYRO_XOUT+4]=i+0x30;
   i=t%10;
   display_buf[GYRO_XOUT+5]=i+0x30;
   display_buf[GYRO_XOUT+2]='-';               
   display_buf[GYRO_XOUT+0]='G';


   y=GetData(GYRO_YOUT_H);
   i=y/100;
   t=y%100;
   display_buf[GYRO_YOUT+1]=i+0x30;
   i=t/10;
   t=t%10;
   display_buf[GYRO_YOUT+2]=i+0x30;
   i=t%10;
   display_buf[GYRO_YOUT+3]=i+0x30;
   display_buf[GYRO_YOUT+0]='-';
   

   z=GetData(GYRO_ZOUT_H);
   i=z/100;
   t=z%100;
   display_buf[GYRO_ZOUT+0]=i+0x30;
   i=t/10;
   t=t%10;
   display_buf[GYRO_ZOUT+1]=i+0x30;
   i=t%10;
   display_buf[GYRO_ZOUT+2]=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[i]);
        }
        tranfser_command(0x80+0x40+0);
        for(i=16;i<32;i++)
        {
                tranfser_data(display_buf[i]);
        }
}
//*********LCD清屏******************//
void clr_screen()
        {
        uchar i;
        for(i=0;i<32;i++) display_buf[i]=0x20;
       
        disp_char();
        }

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

出0入0汤圆

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

出0入0汤圆

 楼主| 发表于 2014-1-4 15:38:55 | 显示全部楼层
youyou_1 发表于 2014-1-4 14:34
加上滤波就相对来说稳定了,具体方法可以在论坛上搜索平衡车……

谢谢您的指导。

出0入0汤圆

发表于 2014-1-4 15:40:10 | 显示全部楼层
嘿嘿 这里高手很多

出0入0汤圆

 楼主| 发表于 2014-1-5 12:12:55 | 显示全部楼层
谢谢您的指导。

出0入0汤圆

发表于 2014-1-8 17:04:47 | 显示全部楼层
收藏代码。。。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-2 15:11

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表